From 3579eacf7b361b76499e5454d760052e0fb321c4 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 25 Apr 2025 14:14:34 +0200 Subject: [PATCH] Add queues and streams page and test suite (cherry picked from commit 0cb63bb54437fd84fb3952df33f37976f7cc767d) --- .../priv/www/js/tmpl/queue.ejs | 2 +- .../priv/www/js/tmpl/queues.ejs | 6 +- selenium/full-suite-management-ui | 1 + selenium/short-suite-management-ui | 1 + selenium/suites/mgt/queuesAndStreams.sh | 9 +++ selenium/test/pageobjects/BasePage.js | 16 +++++ selenium/test/pageobjects/QueuePage.js | 26 +++++++ .../test/pageobjects/QueuesAndStreamsPage.js | 50 ++++++++++++++ selenium/test/pageobjects/StreamPage.js | 26 +++++++ selenium/test/queuesAndStreams/add-classic.js | 67 +++++++++++++++++++ selenium/test/queuesAndStreams/add-quorum.js | 64 ++++++++++++++++++ selenium/test/queuesAndStreams/add-stream.js | 65 ++++++++++++++++++ selenium/test/queuesAndStreams/list.js | 47 +++++++++++++ selenium/test/utils.js | 6 +- 14 files changed, 381 insertions(+), 5 deletions(-) create mode 100755 selenium/suites/mgt/queuesAndStreams.sh create mode 100644 selenium/test/pageobjects/QueuePage.js create mode 100644 selenium/test/pageobjects/QueuesAndStreamsPage.js create mode 100644 selenium/test/pageobjects/StreamPage.js create mode 100644 selenium/test/queuesAndStreams/add-classic.js create mode 100644 selenium/test/queuesAndStreams/add-quorum.js create mode 100644 selenium/test/queuesAndStreams/add-stream.js create mode 100644 selenium/test/queuesAndStreams/list.js diff --git a/deps/rabbitmq_management/priv/www/js/tmpl/queue.ejs b/deps/rabbitmq_management/priv/www/js/tmpl/queue.ejs index c605b8b68019..c4bed04b9c9b 100644 --- a/deps/rabbitmq_management/priv/www/js/tmpl/queue.ejs +++ b/deps/rabbitmq_management/priv/www/js/tmpl/queue.ejs @@ -395,7 +395,7 @@ <% } %> -
+

Delete

diff --git a/deps/rabbitmq_management/priv/www/js/tmpl/queues.ejs b/deps/rabbitmq_management/priv/www/js/tmpl/queues.ejs index ccf9bc12cd30..8d2201295fcb 100644 --- a/deps/rabbitmq_management/priv/www/js/tmpl/queues.ejs +++ b/deps/rabbitmq_management/priv/www/js/tmpl/queues.ejs @@ -1,9 +1,9 @@

Queues

-
+
<%= paginate_ui(queues, 'queues') %>
-
+
<% if (queues.items.length > 0) { %> @@ -222,7 +222,7 @@ <% if (ac.canAccessVhosts()) { %> -
+

Add a new queue

diff --git a/selenium/full-suite-management-ui b/selenium/full-suite-management-ui index 16ae3233eb31..be885cc675d6 100644 --- a/selenium/full-suite-management-ui +++ b/selenium/full-suite-management-ui @@ -19,3 +19,4 @@ mgt/definitions.sh mgt/exchanges.sh mgt/limits.sh mgt/mgt-only-exchanges.sh +mgt/queuesAndStreams.sh diff --git a/selenium/short-suite-management-ui b/selenium/short-suite-management-ui index 065216c9a447..8662975472b1 100644 --- a/selenium/short-suite-management-ui +++ b/selenium/short-suite-management-ui @@ -5,5 +5,6 @@ authnz-mgt/oauth-with-uaa.sh authnz-mgt/oauth-idp-initiated-with-uaa-and-prefix.sh mgt/vhosts.sh mgt/exchanges.sh +mgt/queuesAndStreams.sh mgt/limits.sh mgt/amqp10-connections.sh diff --git a/selenium/suites/mgt/queuesAndStreams.sh b/selenium/suites/mgt/queuesAndStreams.sh new file mode 100755 index 000000000000..fa063a55f60c --- /dev/null +++ b/selenium/suites/mgt/queuesAndStreams.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +TEST_CASES_PATH=/queuesAndStreams +TEST_CONFIG_PATH=/basic-auth + +source $SCRIPT/../../bin/suite_template $@ +run diff --git a/selenium/test/pageobjects/BasePage.js b/selenium/test/pageobjects/BasePage.js index dc855f740de3..989460b6072f 100644 --- a/selenium/test/pageobjects/BasePage.js +++ b/selenium/test/pageobjects/BasePage.js @@ -44,6 +44,7 @@ module.exports = class BasePage { async selectRefreshOption(option) { return this.selectOption(SELECT_REFRESH, option) } + async waitForOverviewTab() { await this.driver.sleep(250) return this.waitForDisplayed(OVERVIEW_TAB) @@ -119,6 +120,11 @@ module.exports = class BasePage { const select = await new Select(selectable) return select.selectByVisibleText(text) } + async selectOptionByValue(locator, value) { + let selectable = await this.waitForDisplayed(locator) + const select = await new Select(selectable) + return select.selectByValue(value) + } async getSelectableVhosts() { const table_model = await this.getSelectableOptions(SELECT_VHOSTS) @@ -152,6 +158,16 @@ module.exports = class BasePage { } catch(e) { return Promise.resolve(false) } + /* + let element = await driver.findElement(FORM_POPUP) + return this.driver.wait(until.elementIsVisible(element), this.timeout / 2, + 'Timed out after [timeout=' + this.timeout + ';polling=' + this.polling + '] awaiting till visible ' + element, + this.polling / 2).then(function onWarningVisible(e) { + return Promise.resolve(true) + }, function onError(e) { + return Promise.resolve(false) + }) + */ } async isPopupWarningNotDisplayed() { diff --git a/selenium/test/pageobjects/QueuePage.js b/selenium/test/pageobjects/QueuePage.js new file mode 100644 index 000000000000..e160e969fb38 --- /dev/null +++ b/selenium/test/pageobjects/QueuePage.js @@ -0,0 +1,26 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') + +const BasePage = require('./BasePage') + + +const QUEUE_NAME = By.css('div#main h1 b') + +const DELETE_SECTION = By.css('div#main div#delete') +const DELETE_BUTTON = By.css('div#main div#delete input[type=submit]') + +module.exports = class QueuePage extends BasePage { + async isLoaded() { + return this.waitForDisplayed(QUEUE_NAME) + } + async getName() { + return this.getText(QUEUE_NAME) + } + async ensureDeleteQueueSectionIsVisible() { + await this.click(DELETE_SECTION) + return driver.findElement(DELETE_SECTION).isDisplayed() + } + async deleteQueue() { + await this.click(DELETE_BUTTON) + return this.acceptAlert() + } +} diff --git a/selenium/test/pageobjects/QueuesAndStreamsPage.js b/selenium/test/pageobjects/QueuesAndStreamsPage.js new file mode 100644 index 000000000000..a326e8056cef --- /dev/null +++ b/selenium/test/pageobjects/QueuesAndStreamsPage.js @@ -0,0 +1,50 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') + +const { delay } = require('../utils') + +const BasePage = require('./BasePage') + + +const PAGING_SECTION = By.css('div#queues-paging-section') +const PAGING_SECTION_HEADER = By.css('div#queues-paging-section h2') +const ADD_NEW_QUEUE_SECTION = By.css('div#add-new-queue') +const FILTER_BY_QUEUE_NAME = By.css('div.filter input#queues-name') + +const TABLE_SECTION = By.css('div#queues-table-section table') +const FORM_QUEUE_NAME = By.css('div#add-new-queue form input[name="name"]') +const FORM_QUEUE_TYPE = By.css('div#add-new-queue form select[name="queuetype"]') +const ADD_BUTTON = By.css('div#add-new-queue form input[type=submit]') + +module.exports = class QueuesAndStreamsPage extends BasePage { + async isLoaded () { + return this.waitForDisplayed(PAGING_SECTION) + } + async getPagingSectionHeaderText() { + return this.getText(PAGING_SECTION_HEADER) + } + async getQueuesTable(firstNColumns) { + return this.getTable(TABLE_SECTION, firstNColumns) + } + async clickOnQueue(vhost, name) { + return this.click(By.css( + "div#queues-table-section table.list tbody tr td a[href='#/queues/" + vhost + "/" + name + "']")) + } + async ensureAddQueueSectionIsVisible() { + await this.click(ADD_NEW_QUEUE_SECTION) + return driver.findElement(ADD_NEW_QUEUE_SECTION).isDisplayed() + } + async ensureAllQueuesSectionIsVisible() { + await this.click(PAGING_SECTION) + return driver.findElement(PAGING_SECTION).isDisplayed() + } + async fillInAddNewQueue(queueDetails) { + await this.selectOptionByValue(FORM_QUEUE_TYPE, queueDetails.type) + await delay(1000) + await this.sendKeys(FORM_QUEUE_NAME, queueDetails.name) + return this.click(ADD_BUTTON) + } + async filterQueues(filterValue) { + await this.waitForDisplayed(FILTER_BY_QUEUE_NAME) + return this.sendKeys(FILTER_BY_QUEUE_NAME, filterValue + Key.RETURN) + } +} diff --git a/selenium/test/pageobjects/StreamPage.js b/selenium/test/pageobjects/StreamPage.js new file mode 100644 index 000000000000..506c0b5c50e5 --- /dev/null +++ b/selenium/test/pageobjects/StreamPage.js @@ -0,0 +1,26 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') + +const BasePage = require('./BasePage') + + +const STREAM_NAME = By.css('div#main h1 b') +const DELETE_SECTION = By.css('div#main div#delete') +const DELETE_BUTTON = By.css('div#main div#delete input[type=submit]') + + +module.exports = class StreamPage extends BasePage { + async isLoaded() { + return this.waitForDisplayed(STREAM_NAME) + } + async getName() { + return this.getText(STREAM_NAME) + } + async ensureDeleteQueueSectionIsVisible() { + await this.click(DELETE_SECTION) + return driver.findElement(DELETE_SECTION).isDisplayed() + } + async deleteStream() { + await this.click(DELETE_BUTTON) + return this.acceptAlert() + } +} diff --git a/selenium/test/queuesAndStreams/add-classic.js b/selenium/test/queuesAndStreams/add-classic.js new file mode 100644 index 000000000000..3b585dd96c4c --- /dev/null +++ b/selenium/test/queuesAndStreams/add-classic.js @@ -0,0 +1,67 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') +require('chromedriver') +const assert = require('assert') +const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') + +const LoginPage = require('../pageobjects/LoginPage') +const OverviewPage = require('../pageobjects/OverviewPage') +const QueuesAndStreamsPage = require('../pageobjects/QueuesAndStreamsPage') +const QueuePage = require('../pageobjects/QueuePage') +const StreamPage = require('../pageobjects/StreamPage') + +describe('Classic queues', function () { + let login + let queuesAndStreams + let queue + let stream + let overview + let captureScreen + let queueName + + before(async function () { + driver = buildDriver() + await goToHome(driver) + login = new LoginPage(driver) + overview = new OverviewPage(driver) + queuesAndStreams = new QueuesAndStreamsPage(driver) + queue = new QueuePage(driver) + stream = new StreamPage(driver) + captureScreen = captureScreensFor(driver, __filename) + + await login.login('management', 'guest') + if (!await overview.isLoaded()) { + throw new Error('Failed to login') + } + await overview.selectRefreshOption("Do not refresh") + await overview.clickOnQueuesTab() + + queueName = "test_" + Math.floor(Math.random() * 1000) + }) + + it('add classic queue and view it', async function () { + await queuesAndStreams.ensureAddQueueSectionIsVisible() + + await queuesAndStreams.fillInAddNewQueue({"name" : queueName, "type" : "classic"}) + await delay(5000) + await queuesAndStreams.filterQueues(queueName) + await delay(2000) + let table = await queuesAndStreams.getQueuesTable(5) + assert.equal(1, table.length) + assert.equal(table[0][0], '/') + assert.equal(table[0][1], queueName) + assert.equal(table[0][2], 'classic') + assert.equal(table[0][4], 'running') + + await queuesAndStreams.clickOnQueue("%2F", queueName) + await queue.isLoaded() + assert.equal(queueName, await queue.getName()) + + }) + + after(async function () { + await queue.ensureDeleteQueueSectionIsVisible() + await queue.deleteQueue() + + await teardown(driver, this, captureScreen) + }) +}) diff --git a/selenium/test/queuesAndStreams/add-quorum.js b/selenium/test/queuesAndStreams/add-quorum.js new file mode 100644 index 000000000000..ecbd25f71192 --- /dev/null +++ b/selenium/test/queuesAndStreams/add-quorum.js @@ -0,0 +1,64 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') +require('chromedriver') +const assert = require('assert') +const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') + +const LoginPage = require('../pageobjects/LoginPage') +const OverviewPage = require('../pageobjects/OverviewPage') +const QueuesAndStreamsPage = require('../pageobjects/QueuesAndStreamsPage') +const QueuePage = require('../pageobjects/QueuePage') +const StreamPage = require('../pageobjects/StreamPage') + +describe('Quorum queues', function () { + let login + let queuesAndStreams + let queue + let stream + let overview + let captureScreen + + before(async function () { + driver = buildDriver() + await goToHome(driver) + login = new LoginPage(driver) + overview = new OverviewPage(driver) + queuesAndStreams = new QueuesAndStreamsPage(driver) + queue = new QueuePage(driver) + stream = new StreamPage(driver) + captureScreen = captureScreensFor(driver, __filename) + + await login.login('management', 'guest') + if (!await overview.isLoaded()) { + throw new Error('Failed to login') + } + await overview.selectRefreshOption("Do not refresh") + await overview.clickOnQueuesTab() + + }) + it('add quorum queue and view it', async function () { + await queuesAndStreams.ensureAddQueueSectionIsVisible() + let queueName = "test_" + Math.floor(Math.random() * 1000) + await queuesAndStreams.fillInAddNewQueue({"name" : queueName, "type" : "quorum"}) + await delay(5000) + await queuesAndStreams.filterQueues(queueName) + await delay(2000) + let table = await queuesAndStreams.getQueuesTable(5) + assert.equal(1, table.length) + assert.equal(table[0][0], '/') + assert.equal(table[0][1], queueName) + assert.equal(table[0][2], 'quorum') + assert.equal(table[0][4], 'running') + + await queuesAndStreams.clickOnQueue("%2F", queueName) + await queue.isLoaded() + assert.equal(queueName, await queue.getName()) + + }) + + after(async function () { + await queue.ensureDeleteQueueSectionIsVisible() + await queue.deleteQueue() + + await teardown(driver, this, captureScreen) + }) +}) diff --git a/selenium/test/queuesAndStreams/add-stream.js b/selenium/test/queuesAndStreams/add-stream.js new file mode 100644 index 000000000000..79099ea5f330 --- /dev/null +++ b/selenium/test/queuesAndStreams/add-stream.js @@ -0,0 +1,65 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') +require('chromedriver') +const assert = require('assert') +const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') + +const LoginPage = require('../pageobjects/LoginPage') +const OverviewPage = require('../pageobjects/OverviewPage') +const QueuesAndStreamsPage = require('../pageobjects/QueuesAndStreamsPage') +const QueuePage = require('../pageobjects/QueuePage') +const StreamPage = require('../pageobjects/StreamPage') + +describe('Streams', function () { + let login + let queuesAndStreams + let queue + let stream + let overview + let captureScreen + + before(async function () { + driver = buildDriver() + await goToHome(driver) + login = new LoginPage(driver) + overview = new OverviewPage(driver) + queuesAndStreams = new QueuesAndStreamsPage(driver) + queue = new QueuePage(driver) + stream = new StreamPage(driver) + captureScreen = captureScreensFor(driver, __filename) + + await login.login('management', 'guest') + if (!await overview.isLoaded()) { + throw new Error('Failed to login') + } + await overview.selectRefreshOption("Do not refresh") + await overview.clickOnQueuesTab() + + }) + it('add stream and view it', async function () { + await queuesAndStreams.ensureAddQueueSectionIsVisible() + let queueName = "test_" + Math.floor(Math.random() * 1000) + await queuesAndStreams.fillInAddNewQueue({"name" : queueName, "type" : "stream"}) + await delay(5000) + await queuesAndStreams.filterQueues(queueName) + await delay(2000) + let table = await queuesAndStreams.getQueuesTable(5) + assert.equal(1, table.length) + assert.equal(table[0][0], '/') + assert.equal(table[0][1], queueName) + assert.equal(table[0][2], 'stream') + assert.equal(table[0][4], 'running') + + await queuesAndStreams.clickOnQueue("%2F", queueName) + await stream.isLoaded() + assert.equal(queueName, await stream.getName()) + + }) + + + after(async function () { + await stream.ensureDeleteQueueSectionIsVisible() + await stream.deleteStream() + + await teardown(driver, this, captureScreen) + }) +}) diff --git a/selenium/test/queuesAndStreams/list.js b/selenium/test/queuesAndStreams/list.js new file mode 100644 index 000000000000..094d8beb1195 --- /dev/null +++ b/selenium/test/queuesAndStreams/list.js @@ -0,0 +1,47 @@ +const { By, Key, until, Builder } = require('selenium-webdriver') +require('chromedriver') +const assert = require('assert') +const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils') + +const LoginPage = require('../pageobjects/LoginPage') +const OverviewPage = require('../pageobjects/OverviewPage') +const QueuesAndStreamsPage = require('../pageobjects/QueuesAndStreamsPage') +const QueuePage = require('../pageobjects/QueuePage') +const StreamPage = require('../pageobjects/StreamPage') + +describe('Queues and Streams management', function () { + let login + let queuesAndStreams + let queue + let stream + let overview + let captureScreen + + before(async function () { + driver = buildDriver() + await goToHome(driver) + login = new LoginPage(driver) + overview = new OverviewPage(driver) + queuesAndStreams = new QueuesAndStreamsPage(driver) + queue = new QueuePage(driver) + stream = new StreamPage(driver) + captureScreen = captureScreensFor(driver, __filename) + + await login.login('management', 'guest') + if (!await overview.isLoaded()) { + throw new Error('Failed to login') + } + await overview.selectRefreshOption("Do not refresh") + await overview.clickOnQueuesTab() + + }) + + it('display summary of queues and streams', async function () { + let text = await queuesAndStreams.getPagingSectionHeaderText() + assert.equal(true, text.startsWith('All queues') ) + }) + + after(async function () { + await teardown(driver, this, captureScreen) + }) +}) diff --git a/selenium/test/utils.js b/selenium/test/utils.js index 1edbbbf85636..b7db51d25341 100644 --- a/selenium/test/utils.js +++ b/selenium/test/utils.js @@ -62,7 +62,11 @@ module.exports = { chromeCapabilities.set('goog:chromeOptions', { args: [ "--lang=en", - "--disable-search-engine-choice-screen" + "--disable-search-engine-choice-screen", + "--disable-popup-blocking", + "--credentials_enable_service=false", + "--profile.password_manager_enabled=false", + "--profile.password_manager_leak_detection=false" ] }); driver = builder