Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions deps/rabbitmq_management/priv/www/js/tmpl/feature-flags.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</p>
<button id="ff-enable-all-button" onclick='enable_all_stable_feature_flags(this);'>Enable all stable feature flags</button>
</div>
<div class="section">
<div class="section" id="feature-flags">
<h2>Feature Flags</h2>
<div class="hider">
<%= filter_ui(nonreq_feature_flags) %>
Expand Down Expand Up @@ -301,7 +301,7 @@ function enable_feature_flag(checkbox, feature_flag) {
</svg>
<% } %>
</td>
<td class="c ff-stability-<%= feature_flag.stability %> ff-state-<%= feature_flag.state %>">
<td id="ff-td-<%= feature_flag.name %>" class="c ff-stability-<%= feature_flag.stability %> ff-state-<%= feature_flag.state %>">
<input id="ff-checkbox-<%= feature_flag.name %>" type="checkbox" class="toggle"
<% if (feature_flag.state == 'enabled') { %>
checked disabled
Expand Down Expand Up @@ -349,7 +349,7 @@ function enable_feature_flag(checkbox, feature_flag) {
Therefore, upgrades to a later version of RabbitMQ with this feature flag
enabled are supported.
</p>
<p>
<p id="ff-exp-ack-supported">
<input id="ff-exp-ack-supported-checkbox" type="checkbox"/>
<label for="ff-exp-ack-supported-checkbox">I understand that this feature is experimental and should be tested first.</label>
</p>
Expand Down
1 change: 1 addition & 0 deletions selenium/full-suite-management-ui
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ mgt/exchanges.sh
mgt/limits.sh
mgt/mgt-only-exchanges.sh
mgt/queuesAndStreams.sh
mgt/feature-flags.sh
2 changes: 1 addition & 1 deletion selenium/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"chromedriver": "^137.0",
"chromedriver": "^139.0",
"ejs": "^3.1.8",
"express": "^4.18.2",
"geckodriver": "^3.0.2",
Expand Down
1 change: 1 addition & 0 deletions selenium/short-suite-management-ui
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ mgt/queuesAndStreams.sh
mgt/limits.sh
mgt/amqp10-connections.sh
mgt/mqtt-connections.sh
mgt/feature-flags.sh
9 changes: 9 additions & 0 deletions selenium/suites/mgt/feature-flags.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

TEST_CASES_PATH=/feature-flags
TEST_CONFIG_PATH=/basic-auth

source $SCRIPT/../../bin/suite_template $@
run
65 changes: 65 additions & 0 deletions selenium/test/feature-flags/feature-flags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const { By, Key, until, Builder } = require('selenium-webdriver')
require('chromedriver')
const assert = require('assert')
const { buildDriver, goToHome, captureScreensFor, teardown, findTableRow, doUntil } = require('../utils')

const LoginPage = require('../pageobjects/LoginPage')
const OverviewPage = require('../pageobjects/OverviewPage')
const AdminTab = require('../pageobjects/AdminTab')
const FeatureFlagsAdminTab = require('../pageobjects/FeatureFlagsAdminTab')

describe('Feature flags in Admin tab', function () {
let login
let overview
let ffTab
let captureScreen

before(async function () {
driver = buildDriver()
await goToHome(driver)
login = new LoginPage(driver)
overview = new OverviewPage(driver)
adminTab = new AdminTab(driver)
ffTab = new FeatureFlagsAdminTab(driver)
captureScreen = captureScreensFor(driver, __filename)

await login.login('guest', 'guest')
if (!await overview.isLoaded()) {
throw new Error('Failed to login')
}
await overview.selectRefreshOption("Do not refresh")
})

it('it has at least one feature flag', async function () {
await overview.clickOnAdminTab()
await adminTab.clickOnFeatureFlags()
let ffTable = await ffTab.getAll()
assert(ffTable.length > 0)
})
it('it has khepri_db feature flag', async function () {
await overview.clickOnAdminTab()
await adminTab.clickOnFeatureFlags()
let ffTable = await ffTab.getAll()
assert(findTableRow(ffTable, function(row) {
return row[0] === 'khepri_db'
}))
})
it('enable khepri_db feature flag', async function () {
await overview.clickOnAdminTab()
await adminTab.clickOnFeatureFlags()
let prev_state = await ffTab.getState('khepri_db')
assert(!await prev_state.isSelected())
await ffTab.enable('khepri_db')
await doUntil(async function() {
return ffTab.getState('khepri_db')
}, function(state) {
return state.isSelected()
}, 6000)

})


after(async function () {
await teardown(driver, this, captureScreen)
})
})
10 changes: 8 additions & 2 deletions selenium/test/pageobjects/BasePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ module.exports = class BasePage {
this.polling = parseInt(process.env.SELENIUM_POLLING) || 500 // how frequent selenium searches for an element
this.interactionDelay = parseInt(process.env.SELENIUM_INTERACTION_DELAY) || 0 // slow down interactions (when rabbit is behind a http proxy)
}

async ensureSectionIsVisible(section) {
let classes = await this.driver.findElement(section).getAttribute("class")
if (classes.search('section-visible') < 0) {
return this.click(section)
} else {
return Promise.resolve(true)
}
}
async goTo(path) {
return driver.get(d.baseUrl + path)
}
Expand Down Expand Up @@ -381,7 +388,6 @@ module.exports = class BasePage {

async click (locator) {
if (this.interactionDelay) await this.driver.sleep(this.interactionDelay)

const element = await this.waitForDisplayed(locator)
try {
return element.click()
Expand Down
59 changes: 59 additions & 0 deletions selenium/test/pageobjects/FeatureFlagsAdminTab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const { By, Key, until, Builder } = require('selenium-webdriver')
const { delay } = require('../utils')

const AdminTab = require('./AdminTab')


const FEATURE_FLAGS_SECTION = By.css('div#main div#feature-flags')
const FEATURE_FLAGS_TABLE = By.css('div#main div#feature-flags div#ff-table-section table')

const ACCEPT_ENABLE_EXPERIMENTAL_FEATURE_FLAG = By.css('p#ff-exp-ack-supported')
const CONFIRM_ENABLE_EXPERIMENTAL_FEATURE_FLAG = By.css('button#ff-exp-confirm')


module.exports = class FeatureFlagsAdminTab extends AdminTab {
async isLoaded () {
await this.waitForDisplayed(FEATURE_FLAGS_SECTION)
}

async getAll() {
await this.ensureSectionIsVisible(FEATURE_FLAGS_SECTION)
try
{
return this.getTable(FEATURE_FLAGS_TABLE, 4)
} catch (NoSuchElement) {
return Promise.resolve([])
}
}

async enable(name, isExperimental = false) {
let state = await this.getState(name)
if (!await state.isSelected()) {
await this.driver.findElement(this.getParentCheckboxLocator(name)).click()
if (isExperimental) {
await delay(1000)
const dialog = await this.driver.wait(
until.elementLocated(By.css('dialog#ff-exp-dialog[open]')),
10000 // 10 seconds timeout
)
await dialog.findElement(ACCEPT_ENABLE_EXPERIMENTAL_FEATURE_FLAG).click()
await dialog.findElement(CONFIRM_ENABLE_EXPERIMENTAL_FEATURE_FLAG).click()
return delay(1000)
}else {
return Promise.resolve()
}
}else {
return Promise.resolve()
}
}
getCheckboxLocator(name) {
return By.css('div#ff-table-section table input#ff-checkbox-' + name)
}
getParentCheckboxLocator(name) {
return By.css('div#ff-table-section table td#ff-td-' + name)
}
async getState(name) {
return this.driver.findElement(this.getCheckboxLocator(name))
}

}
Loading