From 01ca72edc0f13d05738f43c869713dd53c242361 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Wed, 30 Apr 2025 18:08:58 +0200 Subject: [PATCH 1/7] Test adding vhost --- .../priv/www/js/tmpl/vhosts.ejs | 4 +- selenium/.node-xmlhttprequest-sync-88011 | 0 selenium/test/mgt-api.js | 112 ++++++++++++++++++ selenium/test/pageobjects/VhostsAdminTab.js | 9 +- selenium/test/utils.js | 55 ++++++++- selenium/test/vhosts/admin-vhosts.js | 24 +++- 6 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 selenium/.node-xmlhttprequest-sync-88011 create mode 100644 selenium/test/mgt-api.js diff --git a/deps/rabbitmq_management/priv/www/js/tmpl/vhosts.ejs b/deps/rabbitmq_management/priv/www/js/tmpl/vhosts.ejs index c3dacaad7ce3..ce9613a56c45 100644 --- a/deps/rabbitmq_management/priv/www/js/tmpl/vhosts.ejs +++ b/deps/rabbitmq_management/priv/www/js/tmpl/vhosts.ejs @@ -1,12 +1,12 @@

Virtual Hosts

-
+

All virtual hosts

<%= filter_ui(vhosts) %>
<% if (vhosts.length > 0) { %> - +
<%= group_heading('vhosts', 'Overview', [true, true, true]) %> diff --git a/selenium/.node-xmlhttprequest-sync-88011 b/selenium/.node-xmlhttprequest-sync-88011 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/selenium/test/mgt-api.js b/selenium/test/mgt-api.js new file mode 100644 index 000000000000..2ff69328a690 --- /dev/null +++ b/selenium/test/mgt-api.js @@ -0,0 +1,112 @@ +const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest +const {log, error} = require('./utils.js') + +const baseUrl = randomly_pick_baseurl(process.env.RABBITMQ_URL || 'http://localhost:15672/') +const otherBaseUrl = randomly_pick_baseurl(process.env.OTHER_RABBITMQ_URL || 'http://localhost:15675/') +const hostname = process.env.RABBITMQ_HOSTNAME || 'localhost' +const otherHostname = process.env.OTHER_RABBITMQ_HOSTNAME || 'localhost' + +function randomly_pick_baseurl (baseUrl) { + urls = baseUrl.split(",") + return urls[getRandomInt(urls.length)] +} +function getRandomInt(max) { + return Math.floor(Math.random() * max) +} + +module.exports = { + + getManagementUrl: () => { + return baseUrl + }, + + geOtherManagementUrl: () => { + return otherBaseUrl + }, + + setPolicy: (url, vhost, name, pattern, definition, appliedTo = "queues") => { + let policy = { + "pattern": pattern, + "apply-to": appliedTo, + "definition": definition + } + log("Setting policy " + JSON.stringify(policy) + + " with name " + name + " for vhost " + vhost + " on "+ url) + const req = new XMLHttpRequest() + let base64Credentials = btoa('administrator-only' + ":" + 'guest') + let finalUrl = url + "/api/policies/" + encodeURIComponent(vhost) + "/" + + encodeURIComponent(name) + req.open('PUT', finalUrl, false) + req.setRequestHeader("Authorization", "Basic " + base64Credentials) + req.setRequestHeader('Content-Type', 'application/json') + + req.send(JSON.stringify(policy)) + if (req.status == 200 || req.status == 204 || req.status == 201) { + log("Succesfully set policy " + name) + return + }else { + error("status:" + req.status + " : " + req.responseText) + throw new Error(req.responseText) + } + }, + deletePolicy: (url, vhost, name) => { + log("Deleting policy " + name + " on vhost " + vhost) + const req = new XMLHttpRequest() + let base64Credentials = btoa('administrator-only' + ":" + 'guest') + let finalUrl = url + "/api/policies/" + encodeURIComponent(vhost) + "/" + + encodeURIComponent(name) + req.open('DELETE', finalUrl, false) + req.setRequestHeader("Authorization", "Basic " + base64Credentials) + + req.send() + if (req.status == 200 || req.status == 204) { + log("Succesfully deleted policy " + name) + return + }else { + error("status:" + req.status + " : " + req.responseText) + throw new Error(req.responseText) + } + }, + createVhost: (url, name, description = "", tags = []) => { + let vhost = { + "description": description, + "tags": tags + } + log("Create vhost " + JSON.stringify(vhost) + + " with name " + name + " on " + url) + const req = new XMLHttpRequest() + let base64Credentials = btoa('administrator-only' + ":" + 'guest') + let finalUrl = url + "/api/vhosts/" + encodeURIComponent(name) + req.open('PUT', finalUrl, false) + req.setRequestHeader("Authorization", "Basic " + base64Credentials) + req.setRequestHeader('Content-Type', 'application/json') + + req.send(JSON.stringify(vhost)) + if (req.status == 200 || req.status == 204 || req.status == 201) { + log("Succesfully created vhost " + name) + return + }else { + error("status:" + req.status + " : " + req.responseText) + throw new Error(req.responseText) + } + }, + deleteVhost: (url, vhost) => { + log("Deleting vhost " + vhost) + const req = new XMLHttpRequest() + let base64Credentials = btoa('administrator-only' + ":" + 'guest') + let finalUrl = url + "/api/vhosts/" + encodeURIComponent(vhost) + req.open('DELETE', finalUrl, false) + req.setRequestHeader("Authorization", "Basic " + base64Credentials) + + req.send() + if (req.status == 200 || req.status == 204) { + log("Succesfully deleted vhost " + vhost) + return + }else { + error("status:" + req.status + " : " + req.responseText) + throw new Error(req.responseText) + } + } + + +} diff --git a/selenium/test/pageobjects/VhostsAdminTab.js b/selenium/test/pageobjects/VhostsAdminTab.js index 34ae729da33d..7aa5604649e0 100644 --- a/selenium/test/pageobjects/VhostsAdminTab.js +++ b/selenium/test/pageobjects/VhostsAdminTab.js @@ -2,15 +2,18 @@ const { By, Key, until, Builder } = require('selenium-webdriver') const AdminTab = require('./AdminTab') +const MAIN_SECTION = By.css('div#main div#vhosts.section') + const SELECTED_VHOSTS_ON_RHM = By.css('div#rhs ul li a[href="#/vhosts"]') const FILTER_VHOST = By.css('div#main div.filter input#filter') const CHECKBOX_REGEX = By.css('div#main div.filter input#filter-regex-mode') const VHOSTS_TABLE_ROWS = By.css('div#main table.list tbody tr') +const TABLE_SECTION = By.css('div#main table.list') module.exports = class VhostsAdminTab extends AdminTab { async isLoaded () { - await this.waitForDisplayed(SELECTED_VHOSTS_ON_RHM) + await this.waitForDisplayed(MAIN_SECTION) } async searchForVhosts(vhost, regex = false) { await this.sendKeys(FILTER_VHOST, vhost) @@ -32,5 +35,7 @@ module.exports = class VhostsAdminTab extends AdminTab { } throw "Vhost " + vhost + " not found" } - + async getVhostsTable(firstNColumns) { + return this.getTable(TABLE_SECTION, firstNColumns) + } } diff --git a/selenium/test/utils.js b/selenium/test/utils.js index b7db51d25341..3f83654f39f7 100644 --- a/selenium/test/utils.js +++ b/selenium/test/utils.js @@ -5,6 +5,7 @@ const path = require('path') const { By, Key, until, Builder, logging, Capabilities } = require('selenium-webdriver') const proxy = require('selenium-webdriver/proxy') require('chromedriver') +var chrome = require("selenium-webdriver/chrome"); const UAALoginPage = require('./pageobjects/UAALoginPage') const KeycloakLoginPage = require('./pageobjects/KeycloakLoginPage') const assert = require('assert') @@ -47,7 +48,9 @@ module.exports = { log: (message) => { console.log(new Date() + " " + message) }, - + error: (message) => { + console.error(new Date() + " " + message) + }, hasProfile: (profile) => { return profiles.includes(profile) }, @@ -58,19 +61,33 @@ module.exports = { builder = builder.usingServer(seleniumUrl) } let chromeCapabilities = Capabilities.chrome(); - chromeCapabilities.setAcceptInsecureCerts(true); + const options = new chrome.Options() + chromeCapabilities.setAcceptInsecureCerts(true); chromeCapabilities.set('goog:chromeOptions', { + excludeSwitches: [ // disable info bar + 'enable-automation', + ], + prefs: { + 'profile.managed_default_content_settings.popups' : 2, + 'profile.managed_default_content_settings.notifications' : 2, + }, args: [ + "disable-infobars", + "--disable-notifications", "--lang=en", "--disable-search-engine-choice-screen", - "--disable-popup-blocking", + "disable-popup-blocking", "--credentials_enable_service=false", - "--profile.password_manager_enabled=false", - "--profile.password_manager_leak_detection=false" + "profile.password_manager_enabled=false", + "profile.reduce-security-for-testing", + "profile.managed_default_content_settings.popups=1", + "profile.managed_default_content_settings.notifications.popups=1", + "profile.password_manager_leak_detection=false" ] }); driver = builder .forBrowser('chrome') + .setChromeOptions(options.excludeSwitches('enable-automation')) .withCapabilities(chromeCapabilities) .build() driver.manage().setTimeouts( { pageLoad: 35000 } ) @@ -111,6 +128,34 @@ module.exports = { return new CaptureScreenshot(driver, require('path').basename(test)) }, + doWhile: async (doCallback, booleanCallback, delayMs = 1000, message = "doWhile failed") => { + let done = false + let attempts = 10 + let ret + do { + try { + console.log("Calling doCallback (attempts:" + attempts + ") ... ") + ret = await doCallback() + console.log("Calling booleanCallback (attempts:" + attempts + ") with arg " + ret + " ... ") + done = booleanCallback(ret) + }catch(error) { + console.log("Caught " + error + " on doWhile callback...") + + }finally { + if (!done) { + console.log("Waiting until next attempt") + await module.exports.delay(delayMs) + } + } + attempts-- + } while (attempts > 0 && !done) + if (!done) { + throw new Error(message) + }else { + return ret + } + }, + idpLoginPage: (driver, preferredIdp) => { if (!preferredIdp) { if (process.env.PROFILES.includes("uaa")) { diff --git a/selenium/test/vhosts/admin-vhosts.js b/selenium/test/vhosts/admin-vhosts.js index 68ca103eb473..b46eea63f107 100644 --- a/selenium/test/vhosts/admin-vhosts.js +++ b/selenium/test/vhosts/admin-vhosts.js @@ -1,7 +1,8 @@ const { By, Key, until, Builder } = require('selenium-webdriver') require('chromedriver') const assert = require('assert') -const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') +const { buildDriver, goToHome, captureScreensFor, teardown, doWhile, log } = require('../utils') +const { getManagementUrl, createVhost, deleteVhost } = require('../mgt-api') const LoginPage = require('../pageobjects/LoginPage') const OverviewPage = require('../pageobjects/OverviewPage') @@ -46,6 +47,27 @@ describe('Virtual Hosts in Admin tab', function () { assert.equal("/", await vhostTab.getName()) }) + describe('given there is a new virtualhost with a tag', async function() { + let vhost = "test_" + Math.floor(Math.random() * 1000) + before(async function() { + createVhost(getManagementUrl(), vhost, "selenium", "selenium-tag") + await overview.clickOnAdminTab() + await adminTab.clickOnVhosts() + }) + it('vhost is listed', async function () { + await vhostsTab.searchForVhosts(vhost) + let vhostTable = await doWhile(async function() { + return vhostsTab.getVhostsTable() + }, function(table) { + return table.length > 0 && vhost.localeCompare(table[0][0]) + }) + log("vhostTable: " + vhostTable) + }) + after(async function () { + deleteVhost(getManagementUrl(), vhost) + }) + + }) after(async function () { await teardown(driver, this, captureScreen) From 1ab81f7901c8de973ec6bdd3d48bab1aaba9a2d8 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Wed, 30 Apr 2025 18:22:20 +0200 Subject: [PATCH 2/7] Select tags column on vhosts table --- selenium/test/pageobjects/VhostsAdminTab.js | 9 +++++++++ selenium/test/vhosts/admin-vhosts.js | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/selenium/test/pageobjects/VhostsAdminTab.js b/selenium/test/pageobjects/VhostsAdminTab.js index 7aa5604649e0..385a29091ddd 100644 --- a/selenium/test/pageobjects/VhostsAdminTab.js +++ b/selenium/test/pageobjects/VhostsAdminTab.js @@ -10,6 +10,9 @@ const CHECKBOX_REGEX = By.css('div#main div.filter input#filter-regex-mode') const VHOSTS_TABLE_ROWS = By.css('div#main table.list tbody tr') const TABLE_SECTION = By.css('div#main table.list') +const ADD_MINUS_BUTTON = By.css('div#main table.list thead tr th.plus-minus') + +const TABLE_COLUMNS_POPUP = By.css('div.form-popup-options') module.exports = class VhostsAdminTab extends AdminTab { async isLoaded () { @@ -38,4 +41,10 @@ module.exports = class VhostsAdminTab extends AdminTab { async getVhostsTable(firstNColumns) { return this.getTable(TABLE_SECTION, firstNColumns) } + async clickOnSelectColumns() { + return this.click(ADD_MINUS_BUTTON) + } + async getSelectableTableColumns() { + return this.waitForDisplayed(TABLE_COLUMNS_POPUP) + } } diff --git a/selenium/test/vhosts/admin-vhosts.js b/selenium/test/vhosts/admin-vhosts.js index b46eea63f107..20f340f3e3b0 100644 --- a/selenium/test/vhosts/admin-vhosts.js +++ b/selenium/test/vhosts/admin-vhosts.js @@ -56,12 +56,13 @@ describe('Virtual Hosts in Admin tab', function () { }) it('vhost is listed', async function () { await vhostsTab.searchForVhosts(vhost) - let vhostTable = await doWhile(async function() { + await doWhile(async function() { return vhostsTab.getVhostsTable() }, function(table) { return table.length > 0 && vhost.localeCompare(table[0][0]) }) - log("vhostTable: " + vhostTable) + await vhostsTab.clickOnSelectColumns() + await vhostsTab.getSelectableTableColumns() }) after(async function () { deleteVhost(getManagementUrl(), vhost) From 7003fefa44af8b20603c7574020e0afcae5586cb Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 2 May 2025 13:05:25 +0200 Subject: [PATCH 3/7] Select columns of vhosts --- .../priv/www/js/tmpl/popup.ejs | 2 +- selenium/test/pageobjects/BasePage.js | 32 ++++++++++++++++- selenium/test/pageobjects/VhostsAdminTab.js | 10 +----- selenium/test/utils.js | 4 +-- selenium/test/vhosts/admin-vhosts.js | 34 ++++++++++++++----- 5 files changed, 61 insertions(+), 21 deletions(-) diff --git a/deps/rabbitmq_management/priv/www/js/tmpl/popup.ejs b/deps/rabbitmq_management/priv/www/js/tmpl/popup.ejs index bf9081fab6cd..d36180221720 100644 --- a/deps/rabbitmq_management/priv/www/js/tmpl/popup.ejs +++ b/deps/rabbitmq_management/priv/www/js/tmpl/popup.ejs @@ -2,5 +2,5 @@ <%= text %>

- Close + Close diff --git a/selenium/test/pageobjects/BasePage.js b/selenium/test/pageobjects/BasePage.js index 989460b6072f..d8ac7331b68a 100644 --- a/selenium/test/pageobjects/BasePage.js +++ b/selenium/test/pageobjects/BasePage.js @@ -14,7 +14,10 @@ const ADMIN_TAB = By.css('div#menu ul#tabs li#admin') const STREAM_CONNECTIONS_TAB = By.css('div#menu ul#tabs li#stream-connections') const FORM_POPUP = By.css('div.form-popup-warn') -const FORM_POPUP_CLOSE_BUTTON = By.css('div.form-popup-warn span') +const FORM_POPUP_CLOSE_BUTTON = By.css('div.form-popup-warn span#close') + +const ADD_MINUS_BUTTON = By.css('div#main table.list thead tr th.plus-minus') +const TABLE_COLUMNS_POPUP = By.css('div.form-popup-options table.form') module.exports = class BasePage { driver @@ -136,6 +139,7 @@ module.exports = class BasePage { } + async getTable(tableLocator, firstNColumns, rowClass) { const table = await this.waitForDisplayed(tableLocator) const rows = await table.findElements(rowClass == undefined ? @@ -199,6 +203,32 @@ module.exports = class BasePage { async closePopupWarning() { return this.click(FORM_POPUP_CLOSE_BUTTON) } + async clickOnSelectTableColumns() { + return this.click(ADD_MINUS_BUTTON) + } + async getSelectableTableColumns() { + const table = await this.waitForDisplayed(TABLE_COLUMNS_POPUP) + const rows = await table.findElements(By.css('tbody tr')) + let table_model = [] + console.log("Found "+ rows.length + " rows") + for (let i = 1; i < rows.length; i++) { // skip first row + let groupNameLabel = await rows[i].findElement(By.css('th label')) + let groupName = await groupNameLabel.getText() + console.log("Found group "+ groupName ) + let columns = await rows[i].findElements(By.css('td label')) + let table_row = [] + console.log("Found "+ columns.length + " columns") + for (let column of columns) { + let checkbox = await column.findElement(By.css('input')) + table_row.push({"name:" : await column.getText(), "id" : await checkbox.getAttribute("id")}) + } + let group = {"name": groupName, "columns": table_row} + console.log("Add group " + group) + table_model.push(group) + } + return table_model + } + async isDisplayed(locator) { try { let element = await driver.findElement(locator) diff --git a/selenium/test/pageobjects/VhostsAdminTab.js b/selenium/test/pageobjects/VhostsAdminTab.js index 385a29091ddd..8ec77fae3ae3 100644 --- a/selenium/test/pageobjects/VhostsAdminTab.js +++ b/selenium/test/pageobjects/VhostsAdminTab.js @@ -10,9 +10,6 @@ const CHECKBOX_REGEX = By.css('div#main div.filter input#filter-regex-mode') const VHOSTS_TABLE_ROWS = By.css('div#main table.list tbody tr') const TABLE_SECTION = By.css('div#main table.list') -const ADD_MINUS_BUTTON = By.css('div#main table.list thead tr th.plus-minus') - -const TABLE_COLUMNS_POPUP = By.css('div.form-popup-options') module.exports = class VhostsAdminTab extends AdminTab { async isLoaded () { @@ -41,10 +38,5 @@ module.exports = class VhostsAdminTab extends AdminTab { async getVhostsTable(firstNColumns) { return this.getTable(TABLE_SECTION, firstNColumns) } - async clickOnSelectColumns() { - return this.click(ADD_MINUS_BUTTON) - } - async getSelectableTableColumns() { - return this.waitForDisplayed(TABLE_COLUMNS_POPUP) - } + } diff --git a/selenium/test/utils.js b/selenium/test/utils.js index 3f83654f39f7..e2f948a096b0 100644 --- a/selenium/test/utils.js +++ b/selenium/test/utils.js @@ -68,10 +68,10 @@ module.exports = { 'enable-automation', ], prefs: { - 'profile.managed_default_content_settings.popups' : 2, - 'profile.managed_default_content_settings.notifications' : 2, + 'profile.password_manager_enabled' : false }, args: [ + "--guest", "disable-infobars", "--disable-notifications", "--lang=en", diff --git a/selenium/test/vhosts/admin-vhosts.js b/selenium/test/vhosts/admin-vhosts.js index 20f340f3e3b0..bb0c01455e46 100644 --- a/selenium/test/vhosts/admin-vhosts.js +++ b/selenium/test/vhosts/admin-vhosts.js @@ -29,7 +29,7 @@ describe('Virtual Hosts in Admin tab', function () { if (!await overview.isLoaded()) { throw new Error('Failed to login') } - + await overview.selectRefreshOption("Do not refresh") }) it('find default vhost', async function () { @@ -38,6 +38,7 @@ describe('Virtual Hosts in Admin tab', function () { assert.equal(true, await vhostsTab.hasVhosts("/")) }) it('find default vhost and view it', async function () { + await overview.clickOnOverviewTab() await overview.clickOnAdminTab() await adminTab.clickOnVhosts() await vhostsTab.clickOnVhost(await vhostsTab.searchForVhosts("/"), "/") @@ -46,25 +47,42 @@ describe('Virtual Hosts in Admin tab', function () { } assert.equal("/", await vhostTab.getName()) }) - + it('vhost selectable columns', async function () { + await overview.clickOnOverviewTab() + await overview.clickOnAdminTab() + await adminTab.clickOnVhosts() + await vhostsTab.clickOnSelectTableColumns() + let table = await vhostsTab.getSelectableTableColumns() + log("Table: " + table) + await doWhile(async function() { + return vhostsTab.getVhostsTable() + }, function(table) { + return table.length > 0 && vhost.localeCompare(table[0][0]) + }) + }) describe('given there is a new virtualhost with a tag', async function() { let vhost = "test_" + Math.floor(Math.random() * 1000) before(async function() { + log("Creating vhost") createVhost(getManagementUrl(), vhost, "selenium", "selenium-tag") + await overview.clickOnOverviewTab() await overview.clickOnAdminTab() - await adminTab.clickOnVhosts() + await adminTab.clickOnVhosts() }) - it('vhost is listed', async function () { - await vhostsTab.searchForVhosts(vhost) + it('vhost is listed with tag', async function () { + log("Searching for vhost") + await vhostsTab.searchForVhosts(vhost) + await vhostsTab.clickOnSelectTableColumns() + let table = vhostsTab.getSelectableTableColumns() + log("Table: " + table) await doWhile(async function() { return vhostsTab.getVhostsTable() }, function(table) { - return table.length > 0 && vhost.localeCompare(table[0][0]) + return table.length > 0 && vhost.localeCompare(table[0][0]) }) - await vhostsTab.clickOnSelectColumns() - await vhostsTab.getSelectableTableColumns() }) after(async function () { + log("Deleting vhost") deleteVhost(getManagementUrl(), vhost) }) From ea66a25dfa5d3a192354efa8fd335d2dc22b76c6 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 2 May 2025 14:56:49 +0200 Subject: [PATCH 4/7] Testing new vhost has the tag --- selenium/test/pageobjects/BasePage.js | 26 +++++--- selenium/test/pageobjects/VhostsAdminTab.js | 2 +- selenium/test/utils.js | 7 +- selenium/test/vhosts/admin-vhosts.js | 72 ++++++++++++++++----- 4 files changed, 77 insertions(+), 30 deletions(-) diff --git a/selenium/test/pageobjects/BasePage.js b/selenium/test/pageobjects/BasePage.js index d8ac7331b68a..82c9fd34600b 100644 --- a/selenium/test/pageobjects/BasePage.js +++ b/selenium/test/pageobjects/BasePage.js @@ -13,11 +13,13 @@ const EXCHANGES_TAB = By.css('div#menu ul#tabs li#exchanges') const ADMIN_TAB = By.css('div#menu ul#tabs li#admin') const STREAM_CONNECTIONS_TAB = By.css('div#menu ul#tabs li#stream-connections') -const FORM_POPUP = By.css('div.form-popup-warn') -const FORM_POPUP_CLOSE_BUTTON = By.css('div.form-popup-warn span#close') +const FORM_POPUP_WARNING = By.css('div.form-popup-warn') +const FORM_POPUP_WARNING_CLOSE_BUTTON = By.css('div.form-popup-warn span#close') +const FORM_POPUP_OPTIONS = By.css('div.form-popup-options') const ADD_MINUS_BUTTON = By.css('div#main table.list thead tr th.plus-minus') const TABLE_COLUMNS_POPUP = By.css('div.form-popup-options table.form') +const FORM_POPUP_OPTIONS_CLOSE_BUTTON = By.css('div.form-popup-options span#close') module.exports = class BasePage { driver @@ -157,7 +159,7 @@ module.exports = class BasePage { } async isPopupWarningDisplayed() { try { - let element = await driver.findElement(FORM_POPUP) + let element = await driver.findElement(FORM_POPUP_WARNING) return element.isDisplayed() } catch(e) { return Promise.resolve(false) @@ -175,7 +177,7 @@ module.exports = class BasePage { } async isPopupWarningNotDisplayed() { - return this.isElementNotVisible(FORM_POPUP) + return this.isElementNotVisible(FORM_POPUP_WARNING) } async isElementNotVisible(locator) { @@ -195,13 +197,13 @@ module.exports = class BasePage { } } async getPopupWarning() { - let element = await driver.findElement(FORM_POPUP) + let element = await driver.findElement(FORM_POPUP_WARNING) return this.driver.wait(until.elementIsVisible(element), this.timeout, 'Timed out after [timeout=' + this.timeout + ';polling=' + this.polling + '] awaiting till visible ' + element, this.polling).getText().then((value) => value.substring(0, value.search('\n\nClose'))) } async closePopupWarning() { - return this.click(FORM_POPUP_CLOSE_BUTTON) + return this.click(FORM_POPUP_WARNING_CLOSE_BUTTON) } async clickOnSelectTableColumns() { return this.click(ADD_MINUS_BUTTON) @@ -210,24 +212,28 @@ module.exports = class BasePage { const table = await this.waitForDisplayed(TABLE_COLUMNS_POPUP) const rows = await table.findElements(By.css('tbody tr')) let table_model = [] - console.log("Found "+ rows.length + " rows") for (let i = 1; i < rows.length; i++) { // skip first row let groupNameLabel = await rows[i].findElement(By.css('th label')) let groupName = await groupNameLabel.getText() - console.log("Found group "+ groupName ) let columns = await rows[i].findElements(By.css('td label')) let table_row = [] - console.log("Found "+ columns.length + " columns") for (let column of columns) { let checkbox = await column.findElement(By.css('input')) table_row.push({"name:" : await column.getText(), "id" : await checkbox.getAttribute("id")}) } let group = {"name": groupName, "columns": table_row} - console.log("Add group " + group) table_model.push(group) } return table_model } + async selectTableColumnsById(arrayOfColumnsIds) { + const table = await this.waitForDisplayed(TABLE_COLUMNS_POPUP) + for (let id of arrayOfColumnsIds) { + let checkbox = await table.findElement(By.css('tbody tr input#'+id)) + await checkbox.click() + } + await this.click(FORM_POPUP_OPTIONS_CLOSE_BUTTON) + } async isDisplayed(locator) { try { diff --git a/selenium/test/pageobjects/VhostsAdminTab.js b/selenium/test/pageobjects/VhostsAdminTab.js index 8ec77fae3ae3..d69f8639ccfd 100644 --- a/selenium/test/pageobjects/VhostsAdminTab.js +++ b/selenium/test/pageobjects/VhostsAdminTab.js @@ -9,7 +9,7 @@ const FILTER_VHOST = By.css('div#main div.filter input#filter') const CHECKBOX_REGEX = By.css('div#main div.filter input#filter-regex-mode') const VHOSTS_TABLE_ROWS = By.css('div#main table.list tbody tr') -const TABLE_SECTION = By.css('div#main table.list') +const TABLE_SECTION = By.css('div#main div#vhosts.section table.list') module.exports = class VhostsAdminTab extends AdminTab { async isLoaded () { diff --git a/selenium/test/utils.js b/selenium/test/utils.js index e2f948a096b0..8718e280e55a 100644 --- a/selenium/test/utils.js +++ b/selenium/test/utils.js @@ -62,7 +62,7 @@ module.exports = { } let chromeCapabilities = Capabilities.chrome(); const options = new chrome.Options() - chromeCapabilities.setAcceptInsecureCerts(true); + chromeCapabilities.setAcceptInsecureCerts(true); chromeCapabilities.set('goog:chromeOptions', { excludeSwitches: [ // disable info bar 'enable-automation', @@ -71,7 +71,8 @@ module.exports = { 'profile.password_manager_enabled' : false }, args: [ - "--guest", + "--enable-automation", + "guest", "disable-infobars", "--disable-notifications", "--lang=en", @@ -87,7 +88,7 @@ module.exports = { }); driver = builder .forBrowser('chrome') - .setChromeOptions(options.excludeSwitches('enable-automation')) + //.setChromeOptions(options.excludeSwitches("disable-popup-blocking", "enable-automation")) .withCapabilities(chromeCapabilities) .build() driver.manage().setTimeouts( { pageLoad: 35000 } ) diff --git a/selenium/test/vhosts/admin-vhosts.js b/selenium/test/vhosts/admin-vhosts.js index bb0c01455e46..d0e521fd2862 100644 --- a/selenium/test/vhosts/admin-vhosts.js +++ b/selenium/test/vhosts/admin-vhosts.js @@ -1,7 +1,7 @@ const { By, Key, until, Builder } = require('selenium-webdriver') require('chromedriver') const assert = require('assert') -const { buildDriver, goToHome, captureScreensFor, teardown, doWhile, log } = require('../utils') +const { buildDriver, goToHome, captureScreensFor, teardown, doWhile, log, delay } = require('../utils') const { getManagementUrl, createVhost, deleteVhost } = require('../mgt-api') const LoginPage = require('../pageobjects/LoginPage') @@ -51,15 +51,51 @@ describe('Virtual Hosts in Admin tab', function () { await overview.clickOnOverviewTab() await overview.clickOnAdminTab() await adminTab.clickOnVhosts() + await doWhile(async function() { return vhostsTab.getVhostsTable() }, + function(table) { return table.length>1 }) + await vhostsTab.clickOnSelectTableColumns() let table = await vhostsTab.getSelectableTableColumns() - log("Table: " + table) - await doWhile(async function() { - return vhostsTab.getVhostsTable() - }, function(table) { - return table.length > 0 && vhost.localeCompare(table[0][0]) - }) + + assert.equal(4, table.length) + let overviewGroup = { + "name" : "Overview:", + "columns": [ + {"name:":"Default queue type","id":"checkbox-vhosts-default-queue-type"}, + {"name:":"Cluster state","id":"checkbox-vhosts-cluster-state"}, + {"name:":"Description","id":"checkbox-vhosts-description"}, + {"name:":"Tags","id":"checkbox-vhosts-tags"} + ] + } + assert.equal(JSON.stringify(table[0]), JSON.stringify(overviewGroup)) + let messagesGroup = { + "name" : "Messages:", + "columns": [ + {"name:":"Ready","id":"checkbox-vhosts-msgs-ready"}, + {"name:":"Unacknowledged","id":"checkbox-vhosts-msgs-unacked"}, + {"name:":"Total","id":"checkbox-vhosts-msgs-total"} + ] + } + assert.equal(JSON.stringify(table[1]), JSON.stringify(messagesGroup)) + let networkGroup = { + "name" : "Network:", + "columns": [ + {"name:":"From client","id":"checkbox-vhosts-from_client"}, + {"name:":"To client","id":"checkbox-vhosts-to_client"} + ] + } + assert.equal(JSON.stringify(table[2]), JSON.stringify(networkGroup)) + let messageRatesGroup = { + "name" : "Message rates:", + "columns": [ + {"name:":"publish","id":"checkbox-vhosts-rate-publish"}, + {"name:":"deliver / get","id":"checkbox-vhosts-rate-deliver"} + ] + } + assert.equal(JSON.stringify(table[3]), JSON.stringify(messageRatesGroup)) + }) + describe('given there is a new virtualhost with a tag', async function() { let vhost = "test_" + Math.floor(Math.random() * 1000) before(async function() { @@ -70,16 +106,19 @@ describe('Virtual Hosts in Admin tab', function () { await adminTab.clickOnVhosts() }) it('vhost is listed with tag', async function () { - log("Searching for vhost") - await vhostsTab.searchForVhosts(vhost) - await vhostsTab.clickOnSelectTableColumns() - let table = vhostsTab.getSelectableTableColumns() - log("Table: " + table) - await doWhile(async function() { - return vhostsTab.getVhostsTable() - }, function(table) { - return table.length > 0 && vhost.localeCompare(table[0][0]) + log("Searching for vhost " + vhost) + await doWhile(async function() { return vhostsTab.searchForVhosts(vhost) }, + function(table) { + return table.length==1 && table[1][0].localeCompare(vhost) + }) + log("Found vhost " + vhost) + await vhostsTab.selectTableColumnsById(["checkbox-vhosts-tags"]) + + await doWhile(async function() { return vhostsTab.getVhostsTable() }, + function(table) { + return table.length==1 && table[1][3].localeCompare("selenium-tag") }) + }) after(async function () { log("Deleting vhost") @@ -87,6 +126,7 @@ describe('Virtual Hosts in Admin tab', function () { }) }) + after(async function () { await teardown(driver, this, captureScreen) From 175abbff874bdf6e27c72c120370f04e2ac092da Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 2 May 2025 15:47:32 +0200 Subject: [PATCH 5/7] Test virtual hosts and select tags column --- selenium/test/pageobjects/BasePage.js | 5 ++++- selenium/test/pageobjects/VhostsAdminTab.js | 4 ++-- selenium/test/utils.js | 6 +++--- selenium/test/vhosts/admin-vhosts.js | 14 ++++++++++---- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/selenium/test/pageobjects/BasePage.js b/selenium/test/pageobjects/BasePage.js index 82c9fd34600b..2b4f40ba476f 100644 --- a/selenium/test/pageobjects/BasePage.js +++ b/selenium/test/pageobjects/BasePage.js @@ -151,7 +151,9 @@ module.exports = class BasePage { let columns = await row.findElements(By.css('td')) let table_row = [] for (let column of columns) { - if (table_row.length < firstNColumns) table_row.push(await column.getText()) + if (firstNColumns == undefined || table_row.length < firstNColumns) { + table_row.push(await column.getText()) + } } table_model.push(table_row) } @@ -227,6 +229,7 @@ module.exports = class BasePage { return table_model } async selectTableColumnsById(arrayOfColumnsIds) { + await this.clickOnSelectTableColumns() const table = await this.waitForDisplayed(TABLE_COLUMNS_POPUP) for (let id of arrayOfColumnsIds) { let checkbox = await table.findElement(By.css('tbody tr input#'+id)) diff --git a/selenium/test/pageobjects/VhostsAdminTab.js b/selenium/test/pageobjects/VhostsAdminTab.js index d69f8639ccfd..e7762e013aaf 100644 --- a/selenium/test/pageobjects/VhostsAdminTab.js +++ b/selenium/test/pageobjects/VhostsAdminTab.js @@ -17,7 +17,7 @@ module.exports = class VhostsAdminTab extends AdminTab { } async searchForVhosts(vhost, regex = false) { await this.sendKeys(FILTER_VHOST, vhost) - await this.sendKeys(FILTER_VHOST, Key.RETURN) + //await this.sendKeys(FILTER_VHOST, Key.RETURN) if (regex) { await this.click(CHECKBOX_REGEX) } @@ -31,7 +31,7 @@ module.exports = class VhostsAdminTab extends AdminTab { const links = await vhost_rows.findElements(By.css("td a")) for (let link of links) { let text = await link.getText() - if ( text === "/" ) return link.click() + if ( text === vhost ) return link.click() } throw "Vhost " + vhost + " not found" } diff --git a/selenium/test/utils.js b/selenium/test/utils.js index 8718e280e55a..3068f68240a7 100644 --- a/selenium/test/utils.js +++ b/selenium/test/utils.js @@ -135,16 +135,16 @@ module.exports = { let ret do { try { - console.log("Calling doCallback (attempts:" + attempts + ") ... ") + //console.log("Calling doCallback (attempts:" + attempts + ") ... ") ret = await doCallback() - console.log("Calling booleanCallback (attempts:" + attempts + ") with arg " + ret + " ... ") + //console.log("Calling booleanCallback (attempts:" + attempts + ") with arg " + ret + " ... ") done = booleanCallback(ret) }catch(error) { console.log("Caught " + error + " on doWhile callback...") }finally { if (!done) { - console.log("Waiting until next attempt") + //console.log("Waiting until next attempt") await module.exports.delay(delayMs) } } diff --git a/selenium/test/vhosts/admin-vhosts.js b/selenium/test/vhosts/admin-vhosts.js index d0e521fd2862..8f815d8d8adb 100644 --- a/selenium/test/vhosts/admin-vhosts.js +++ b/selenium/test/vhosts/admin-vhosts.js @@ -47,12 +47,16 @@ describe('Virtual Hosts in Admin tab', function () { } assert.equal("/", await vhostTab.getName()) }) + it('vhost selectable columns', async function () { await overview.clickOnOverviewTab() await overview.clickOnAdminTab() await adminTab.clickOnVhosts() + await vhostsTab.searchForVhosts("/") await doWhile(async function() { return vhostsTab.getVhostsTable() }, - function(table) { return table.length>1 }) + function(table) { + return table.length>0 + }) await vhostsTab.clickOnSelectTableColumns() let table = await vhostsTab.getSelectableTableColumns() @@ -107,16 +111,18 @@ describe('Virtual Hosts in Admin tab', function () { }) it('vhost is listed with tag', async function () { log("Searching for vhost " + vhost) - await doWhile(async function() { return vhostsTab.searchForVhosts(vhost) }, + await vhostsTab.searchForVhosts(vhost) + await doWhile(async function() { return vhostsTab.getVhostsTable()}, function(table) { - return table.length==1 && table[1][0].localeCompare(vhost) + log("table: "+ JSON.stringify(table) + " table[0][0]:" + table[0][0]) + return table.length==1 && table[0][0].localeCompare(vhost) == 0 }) log("Found vhost " + vhost) await vhostsTab.selectTableColumnsById(["checkbox-vhosts-tags"]) await doWhile(async function() { return vhostsTab.getVhostsTable() }, function(table) { - return table.length==1 && table[1][3].localeCompare("selenium-tag") + return table.length==1 && table[0][3].localeCompare("selenium-tag") == 0 }) }) From ba0510f85de17fd5d78c19c2772531d5954d56a0 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 2 May 2025 16:12:32 +0200 Subject: [PATCH 6/7] Test columns available for queues and stream --- selenium/test/queuesAndStreams/list.js | 63 +++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/selenium/test/queuesAndStreams/list.js b/selenium/test/queuesAndStreams/list.js index 094d8beb1195..788660c047c4 100644 --- a/selenium/test/queuesAndStreams/list.js +++ b/selenium/test/queuesAndStreams/list.js @@ -1,7 +1,7 @@ const { By, Key, until, Builder } = require('selenium-webdriver') require('chromedriver') const assert = require('assert') -const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') +const { buildDriver, goToHome, captureScreensFor, teardown, doWhile } = require('../utils') const LoginPage = require('../pageobjects/LoginPage') const OverviewPage = require('../pageobjects/OverviewPage') @@ -41,6 +41,67 @@ describe('Queues and Streams management', function () { assert.equal(true, text.startsWith('All queues') ) }) + it('queue selectable columns', async function () { + await overview.clickOnOverviewTab() + await overview.clickOnQueuesTab() + await doWhile(async function() { return queuesAndStreams.getQueuesTable() }, + function(table) { + return table.length > 0 + }) + + await queuesAndStreams.clickOnSelectTableColumns() + let table = await queuesAndStreams.getSelectableTableColumns() + console.log("table: " + JSON.stringify(table)) + + assert.equal(4, table.length) + let overviewGroup = { + "name" : "Overview:", + "columns": [ + {"name:":"Type","id":"checkbox-queues-type"}, + {"name:":"Features (with policy)","id":"checkbox-queues-features"}, + {"name:":"Features (no policy)","id":"checkbox-queues-features_no_policy"}, + {"name:":"Policy","id":"checkbox-queues-policy"}, + {"name:":"Consumer count","id":"checkbox-queues-consumers"}, + {"name:":"Consumer capacity","id":"checkbox-queues-consumer_capacity"}, + {"name:":"State","id":"checkbox-queues-state"} + ] + } + assert.equal(JSON.stringify(table[0]), JSON.stringify(overviewGroup)) + let messagesGroup = { + "name" : "Messages:", + "columns": [ + {"name:":"Ready","id":"checkbox-queues-msgs-ready"}, + {"name:":"Unacknowledged","id":"checkbox-queues-msgs-unacked"}, + {"name:":"In memory","id":"checkbox-queues-msgs-ram"}, + {"name:":"Persistent","id":"checkbox-queues-msgs-persistent"}, + {"name:":"Total","id":"checkbox-queues-msgs-total"} + ] + } + assert.equal(JSON.stringify(table[1]), JSON.stringify(messagesGroup)) + let messageBytesGroup = { + "name" : "Message bytes:", + "columns": [ + {"name:":"Ready","id":"checkbox-queues-msg-bytes-ready"}, + {"name:":"Unacknowledged","id":"checkbox-queues-msg-bytes-unacked"}, + {"name:":"In memory","id":"checkbox-queues-msg-bytes-ram"}, + {"name:":"Persistent","id":"checkbox-queues-msg-bytes-persistent"}, + {"name:":"Total","id":"checkbox-queues-msg-bytes-total"} + ] + } + assert.equal(JSON.stringify(table[2]), JSON.stringify(messageBytesGroup)) + let messageRatesGroup = { + "name" : "Message rates:", + "columns": [ + {"name:":"incoming","id":"checkbox-queues-rate-incoming"}, + {"name:":"deliver / get","id":"checkbox-queues-rate-deliver"}, + {"name:":"redelivered","id":"checkbox-queues-rate-redeliver"}, + {"name:":"ack","id":"checkbox-queues-rate-ack"} + ] + } + assert.equal(JSON.stringify(table[3]), JSON.stringify(messageRatesGroup)) + + }) + after(async function () { await teardown(driver, this, captureScreen) }) From fb02466b20acce49f877ffb95c2a24832ba41cf2 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 2 May 2025 16:25:01 +0200 Subject: [PATCH 7/7] Test columns for queues and exchanges --- selenium/test/exchanges/management.js | 37 +++++++++++++++++++++++++- selenium/test/queuesAndStreams/list.js | 1 - 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/selenium/test/exchanges/management.js b/selenium/test/exchanges/management.js index 1111fe251640..631acaebdfe5 100644 --- a/selenium/test/exchanges/management.js +++ b/selenium/test/exchanges/management.js @@ -1,7 +1,7 @@ const { By, Key, until, Builder } = require('selenium-webdriver') require('chromedriver') const assert = require('assert') -const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') +const { buildDriver, goToHome, captureScreensFor, teardown, doWhile } = require('../utils') const LoginPage = require('../pageobjects/LoginPage') const OverviewPage = require('../pageobjects/OverviewPage') @@ -66,6 +66,41 @@ describe('Exchange management', function () { assert.equal("amq.fanout", await exchange.getName()) }) + it('queue selectable columns', async function () { + await overview.clickOnOverviewTab() + await overview.clickOnExchangesTab() + await doWhile(async function() { return exchanges.getExchangesTable() }, + function(table) { + return table.length > 0 + }) + + await exchanges.clickOnSelectTableColumns() + let table = await exchanges.getSelectableTableColumns() + + assert.equal(2, table.length) + let overviewGroup = { + "name" : "Overview:", + "columns": [ + {"name:":"Type","id":"checkbox-exchanges-type"}, + {"name:":"Features (with policy)","id":"checkbox-exchanges-features"}, + {"name:":"Features (no policy)","id":"checkbox-exchanges-features_no_policy"}, + {"name:":"Policy","id":"checkbox-exchanges-policy"} + ] + } + assert.equal(JSON.stringify(table[0]), JSON.stringify(overviewGroup)) + + let messageRatesGroup = { + "name" : "Message rates:", + "columns": [ + {"name:":"rate in","id":"checkbox-exchanges-rate-in"}, + {"name:":"rate out","id":"checkbox-exchanges-rate-out"} + ] + } + assert.equal(JSON.stringify(table[1]), JSON.stringify(messageRatesGroup)) + + }) + + after(async function () { await teardown(driver, this, captureScreen) }) diff --git a/selenium/test/queuesAndStreams/list.js b/selenium/test/queuesAndStreams/list.js index 788660c047c4..cd871435b9bc 100644 --- a/selenium/test/queuesAndStreams/list.js +++ b/selenium/test/queuesAndStreams/list.js @@ -51,7 +51,6 @@ describe('Queues and Streams management', function () { await queuesAndStreams.clickOnSelectTableColumns() let table = await queuesAndStreams.getSelectableTableColumns() - console.log("table: " + JSON.stringify(table)) assert.equal(4, table.length) let overviewGroup = {