Skip to content

Commit 20269bf

Browse files
Fix issue #7369
Depending on `disable_stats` value search for detailed exchange details or basic details
1 parent 89ee77e commit 20269bf

File tree

14 files changed

+254
-42
lines changed

14 files changed

+254
-42
lines changed

deps/rabbitmq_management/priv/www/js/tmpl/exchanges.ejs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<h1>Exchanges</h1>
2-
<div class="section">
2+
<div class="section" id="exchanges-paging-section">
33
<%= paginate_ui(exchanges, 'exchanges') %>
4-
</div>
5-
<div class="updatable">
4+
</div>
5+
<div class="updatable" id="exchanges-table-section">
66
<% if (exchanges.items.length > 0) { %>
77
<table class="list">
88
<thead>
@@ -84,7 +84,7 @@
8484
</div>
8585
</div>
8686

87-
<div class="section-hidden">
87+
<div class="section-hidden" id="add-new-exchange">
8888
<h2>Add a new exchange</h2>
8989
<div class="hider">
9090
<form action="#/exchanges" method="put">
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4+
5+
# Name of the suite used to generate log and screen folders
6+
SUITE=$( basename "${BASH_SOURCE[0]}" .sh)
7+
8+
# Path to the test cases this suite should run. It is relative to the selenium/test folder
9+
TEST_CASES_PATH=/exchanges
10+
# Path to the folder where all configuration file reside. It is relative to the selenim/test folder
11+
TEST_CONFIG_PATH=/basic-auth
12+
13+
source $SCRIPT/suite_template
14+
15+
_setup () {
16+
start_rabbitmq
17+
}
18+
_save_logs() {
19+
save_container_logs rabbitmq
20+
}
21+
_teardown() {
22+
kill_container_if_exist rabbitmq
23+
}
24+
run
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4+
5+
# Name of the suite used to generate log and screen folders
6+
SUITE=$( basename "${BASH_SOURCE[0]}" .sh)
7+
8+
# Path to the test cases this suite should run. It is relative to the selenium/test folder
9+
TEST_CASES_PATH=/exchanges
10+
# Path to the folder where all configuration file reside. It is relative to the selenim/test folder
11+
TEST_CONFIG_PATH=/mgt-only
12+
13+
source $SCRIPT/suite_template
14+
15+
_setup () {
16+
start_rabbitmq
17+
}
18+
_save_logs() {
19+
save_container_logs rabbitmq
20+
}
21+
_teardown() {
22+
kill_container_if_exist rabbitmq
23+
}
24+
run

deps/rabbitmq_management/selenium/test/basic-auth/happy-login.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe('An internal user with administrator tag', function () {
2020
})
2121

2222
it('can log in into the management ui', async function () {
23-
await login.login('guest', 'guest')
23+
await login.login('guest', 'guest')
2424
await overview.isLoaded()
2525
assert.equal(await overview.getUser(), 'User guest')
2626
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.ONESHELL:# single shell invocation for all lines in the recipe
2+
SHELL = bash# we depend on bash expansion for e.g. queue patterns
3+
4+
.DEFAULT_GOAL = help
5+
RABBITMQ_SERVER_ROOT = ../../../../../
6+
RABBITMQ_CONFIG_FILE ?= basic-auth/rabbitmq.config
7+
8+
### TARGETS ###
9+
10+
help:
11+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
12+
13+
start-rabbitmq: ## Start RabbitMQ
14+
@(docker kill rabbitmq >/dev/null 2>&1 && docker rm rabbitmq)
15+
@(gmake --directory=${RABBITMQ_SERVER_ROOT} run-broker \
16+
RABBITMQ_ENABLED_PLUGINS="rabbitmq_management" \
17+
RABBITMQ_CONFIG_FILE=deps/rabbitmq_management/selenium/test/${RABBITMQ_CONFIG_FILE})
18+
19+
test: ## Run tests interactively e.g. make test [TEST=landing.js]
20+
@(RABBITMQ_URL=http://localhost:15672 RUN_LOCAL=true SCREENSHOTS_DIR=${PWD}/../../screens npm test $(PWD)/$(TEST))
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const { By, Key, until, Builder } = require('selenium-webdriver')
2+
require('chromedriver')
3+
const assert = require('assert')
4+
const { buildDriver, goToHome, captureScreensFor, teardown, delay } = require('../utils')
5+
6+
const LoginPage = require('../pageobjects/LoginPage')
7+
const OverviewPage = require('../pageobjects/OverviewPage')
8+
const ExchangesPage = require('../pageobjects/ExchangesPage')
9+
const ExchangePage = require('../pageobjects/ExchangePage')
10+
11+
describe('Exchange management', function () {
12+
let login
13+
let exchanges
14+
let exchange
15+
let overview
16+
let captureScreen
17+
18+
before(async function () {
19+
driver = buildDriver()
20+
await goToHome(driver)
21+
login = new LoginPage(driver)
22+
overview = new OverviewPage(driver)
23+
exchanges = new ExchangesPage(driver)
24+
exchange = new ExchangePage(driver)
25+
captureScreen = captureScreensFor(driver, __filename)
26+
27+
await login.login('guest', 'guest')
28+
if (!await overview.isLoaded()) {
29+
throw new Error('Failed to login')
30+
}
31+
overview.clickOnExchangesTab()
32+
})
33+
34+
it('display summary of exchanges', async function () {
35+
assert.equal("All exchanges (7)", await exchanges.getPagingSectionHeaderText())
36+
})
37+
38+
it('list all default exchanges', async function () {
39+
actual_table = await exchanges.getExchangesTable(3)
40+
expected_table = [
41+
["(AMQP default)", "direct", "D"],
42+
["amq.direct", "direct", "D"],
43+
["amq.fanout", "fanout", "D"],
44+
["amq.headers", "headers", "D"],
45+
["amq.match", "headers", "D"],
46+
["amq.rabbitmq.trace", "topic", "D I"],
47+
["amq.topic", "topic", "D"]
48+
]
49+
assert.deepEqual(actual_table, expected_table)
50+
})
51+
52+
it('view one exchange', async function () {
53+
await exchanges.clickOnExchange("%2F", "amq.fanout")
54+
await exchange.isLoaded()
55+
assert.equal("amq.fanout", await exchange.getName())
56+
})
57+
58+
after(async function () {
59+
await teardown(driver, this, captureScreen)
60+
})
61+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[rabbitmq_management].
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[
2+
{rabbit, [
3+
{auth_backends, [rabbit_auth_backend_internal]}
4+
]},
5+
{rabbitmq_management, [
6+
{login_session_timeout, 150} %% in minutes
7+
]},
8+
{rabbitmq_management_agent, [
9+
{disable_metrics_collector, true}
10+
]}
11+
12+
].

deps/rabbitmq_management/selenium/test/pageobjects/BasePage.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
const { By, Key, until, Builder } = require('selenium-webdriver')
22

3+
const MENU_TABS = By.css('div#menu ul#tabs')
4+
const USER = By.css('li#logout')
5+
const LOGOUT_FORM = By.css('li#logout form')
6+
7+
const CONNECTION_TAB = By.css('div#menu ul#tabs li a[href="#/connections"]')
8+
const CHANNELS_TAB = By.css('div#menu ul#tabs li a[href="#/channels"]')
9+
const QUEUES_TAB = By.css('div#menu ul#tabs li a[href="#/queues"]')
10+
const EXCHANGES_TAB = By.css('div#menu ul#tabs li a[href="#/exchanges"]')
11+
const ADMIN_TAB = By.css('div#menu ul#tabs li a[href="#/users"]')
12+
313
module.exports = class BasePage {
414
driver
515
timeout
@@ -12,6 +22,53 @@ module.exports = class BasePage {
1222
this.polling = parseInt(process.env.POLLING) || 1000 // how frequent selenium searches for an element
1323
}
1424

25+
async isLoaded () {
26+
return this.waitForDisplayed(MENU_TABS)
27+
}
28+
29+
async logout () {
30+
await this.submit(LOGOUT_FORM)
31+
}
32+
33+
async getUser () {
34+
return this.getText(USER)
35+
}
36+
37+
async clickOnConnectionsTab () {
38+
return this.click(CONNECTION_TAB)
39+
}
40+
41+
async clickOnAdminTab () {
42+
return this.click(ADMIN_TAB)
43+
}
44+
45+
async clickOnChannelsTab () {
46+
return this.click(CHANNELS_TAB)
47+
}
48+
49+
async clickOnExchangesTab () {
50+
return this.click(EXCHANGES_TAB)
51+
}
52+
53+
async clickOnQueuesTab () {
54+
return this.click(QUEUES_TAB)
55+
}
56+
57+
async getTable(locator, firstNColumns) {
58+
let table = await this.waitForDisplayed(locator)
59+
let rows = await table.findElements(By.css('tbody tr'))
60+
let table_model = []
61+
for (let row of rows) {
62+
let columns = await row.findElements(By.css('td'))
63+
let table_row = []
64+
for (let column of columns) {
65+
if (table_row.length < firstNColumns) table_row.push(await column.getText())
66+
}
67+
table_model.push(table_row)
68+
}
69+
return table_model
70+
}
71+
1572
async waitForLocated (locator) {
1673
return this.driver.wait(until.elementLocated(locator), this.timeout, 'Timed out after 30 seconds', this.polling);
1774
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const { By, Key, until, Builder } = require('selenium-webdriver')
2+
3+
const BasePage = require('./BasePage')
4+
5+
6+
const EXCHANGE_NAME = By.css('div#main h1 b')
7+
8+
9+
module.exports = class ExchangePage extends BasePage {
10+
async isLoaded() {
11+
return this.waitForDisplayed(EXCHANGE_NAME)
12+
}
13+
async getName() {
14+
return this.getText(EXCHANGE_NAME)
15+
}
16+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const { By, Key, until, Builder } = require('selenium-webdriver')
2+
3+
const BasePage = require('./BasePage')
4+
5+
6+
const PAGING_SECTION = By.css('div#exchanges-paging-section')
7+
const PAGING_SECTION_HEADER = By.css('div#exchanges-paging-section h2')
8+
9+
const TABLE_SECTION = By.css('div#exchanges-table-section table')
10+
11+
module.exports = class ExchangesPage extends BasePage {
12+
async isLoaded () {
13+
return this.waitForDisplayed(PAGING_SECTION)
14+
}
15+
async getPagingSectionHeaderText() {
16+
return this.getText(PAGING_SECTION_HEADER)
17+
}
18+
async getExchangesTable(firstNColumns) {
19+
return this.getTable(TABLE_SECTION, firstNColumns)
20+
}
21+
async clickOnExchange(vhost, name) {
22+
return this.click(By.css(
23+
"div#exchanges-table-section table tbody tr td a[href='#/exchanges/" + vhost + "/" + name + "']"))
24+
}
25+
}

deps/rabbitmq_management/selenium/test/pageobjects/OverviewPage.js

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@ const { By, Key, until, Builder } = require('selenium-webdriver')
22

33
const BasePage = require('./BasePage')
44

5-
const MENU_TABS = By.css('div#menu ul#tabs')
6-
const USER = By.css('li#logout')
7-
const LOGOUT_FORM = By.css('li#logout form')
8-
9-
const CONNECTION_TAB = By.css('div#menu ul#tabs li a[href="#/connections"]')
10-
const CHANNELS_TAB = By.css('div#menu ul#tabs li a[href="#/channels"]')
11-
const QUEUES_TAB = By.css('div#menu ul#tabs li a[href="#/queues"]')
12-
const ADMIN_TAB = By.css('div#menu ul#tabs li a[href="#/users"]')
135

146
const UPLOAD_DEFINITIONS_SECTION = By.css('div#upload-definitions-section')
157
const CHOOSE_BROKER_UPLOAD_FILE = By.css('input[name="file"]')
@@ -21,33 +13,6 @@ const CHOOSE_BROKER_DOWNLOAD_FILE = By.css('input#download-filename')
2113
const DOWNLOAD_BROKER_FILE = By.css('button#upload-definitions')
2214

2315
module.exports = class OverviewPage extends BasePage {
24-
async isLoaded () {
25-
return this.waitForDisplayed(MENU_TABS)
26-
}
27-
28-
async logout () {
29-
await this.submit(LOGOUT_FORM)
30-
}
31-
32-
async getUser () {
33-
return this.getText(USER)
34-
}
35-
36-
async clickOnConnectionsTab () {
37-
return this.click(CONNECTION_TAB)
38-
}
39-
40-
async clickOnAdminTab () {
41-
return this.click(ADMIN_TAB)
42-
}
43-
44-
async clickOnChannelsTab () {
45-
return this.click(CHANNELS_TAB)
46-
}
47-
48-
async clickOnQueuesTab () {
49-
return this.click(QUEUES_TAB)
50-
}
5116

5217
async uploadBrokerDefinitions(file) {
5318
await this.click(UPLOAD_DEFINITIONS_SECTION)

deps/rabbitmq_management/selenium/test/utils.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,5 @@ module.exports = {
9292
}
9393
await driver.quit()
9494
}
95+
9596
}

deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange.erl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,15 @@ resource_exists(ReqData, Context) ->
4141

4242
to_json(ReqData, Context) ->
4343
try
44-
[X] = rabbit_mgmt_db:augment_exchanges(
44+
case rabbit_mgmt_util:disable_stats(ReqData) of
45+
false ->
46+
[X] = rabbit_mgmt_db:augment_exchanges(
4547
[exchange(ReqData)], rabbit_mgmt_util:range(ReqData), full),
46-
rabbit_mgmt_util:reply(rabbit_mgmt_format:strip_pids(X), ReqData, Context)
48+
rabbit_mgmt_util:reply(rabbit_mgmt_format:strip_pids(X), ReqData, Context);
49+
true ->
50+
rabbit_mgmt_util:reply(rabbit_mgmt_format:strip_pids(exchange(ReqData)),
51+
ReqData, Context)
52+
end
4753
catch
4854
{error, invalid_range_parameters, Reason} ->
4955
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)

0 commit comments

Comments
 (0)