-
+ |
Incoming Links (<%=(session.incoming_links.length)%>)
-
+
Link handle |
@@ -50,7 +50,7 @@
for (var j = 0; j < session.incoming_links.length; j++) {
var in_link = session.incoming_links[j];
%>
-
+
<%= fmt_string(in_link.handle) %> |
<%= fmt_string(in_link.link_name) %> |
<%= fmt_string(in_link.target_address) %> |
@@ -68,9 +68,9 @@
<% } %>
<% if (session.outgoing_links.length > 0) { %>
-
+ |
Outgoing Links (<%=(session.outgoing_links.length)%>)
-
+
Link handle |
@@ -88,7 +88,7 @@
for (var k = 0; k < session.outgoing_links.length; k++) {
var out_link = session.outgoing_links[k];
%>
-
+
<%= fmt_string(out_link.handle) %> |
<%= fmt_string(out_link.link_name) %> |
<%= fmt_string(out_link.source_address) %> |
diff --git a/selenium/amqp10-roundtriptest/src/main/java/com/rabbitmq/amqp1_0/RoundTripTest.java b/selenium/amqp10-roundtriptest/src/main/java/com/rabbitmq/amqp1_0/RoundTripTest.java
index 461f43722cbf..ee3609771657 100644
--- a/selenium/amqp10-roundtriptest/src/main/java/com/rabbitmq/amqp1_0/RoundTripTest.java
+++ b/selenium/amqp10-roundtriptest/src/main/java/com/rabbitmq/amqp1_0/RoundTripTest.java
@@ -30,11 +30,11 @@ public static void main(String args[]) throws Exception {
String username = args.length > 0 ? args[0] : getEnv("RABBITMQ_AMQP_USERNAME", "guest");
String password = args.length > 1 ? args[1] : getEnv("RABBITMQ_AMQP_PASSWORD", "guest");
- boolean usemtls = Boolean.parseBoolean(getEnv("AMQP_USE_MTLS", "false"));
- String certsLocation = getEnv("RABBITMQ_CERTS");
+ boolean usemtls = Boolean.parseBoolean(getEnv("AMQP_USE_MTLS", "false"));
if ("amqps".equals(scheme)) {
List connectionParams = new ArrayList();
+ String certsLocation = getEnv("RABBITMQ_CERTS");
connectionParams.add("transport.trustStoreLocation=" + certsLocation + "/truststore.jks");
connectionParams.add("transport.trustStorePassword=foobar");
@@ -84,6 +84,8 @@ public static void main(String args[]) throws Exception {
TextMessage receivedMessage = (TextMessage) messageConsumer.receive(2000L);
assertEquals(message.getText(), receivedMessage.getText());
+
+ Thread.sleep(60000);
}
}
private static Connection createConnection(ConnectionFactory factory,
diff --git a/selenium/package.json b/selenium/package.json
index 5021dc3ef122..0087e95d2fd3 100644
--- a/selenium/package.json
+++ b/selenium/package.json
@@ -13,7 +13,7 @@
"author": "",
"license": "ISC",
"dependencies": {
- "chromedriver": "^128.0.0",
+ "chromedriver": "^130.0.4",
"ejs": "^3.1.8",
"express": "^4.18.2",
"geckodriver": "^3.0.2",
@@ -21,7 +21,8 @@
"mqtt": "^5.3.3",
"path": "^0.12.7",
"proxy": "^1.0.2",
- "selenium-webdriver": "^4.19.0",
+ "rhea": "^3.0.3",
+ "selenium-webdriver": "^4.26.0",
"xmlhttprequest": "^1.8.0"
},
"devDependencies": {
diff --git a/selenium/short-suite-management-ui b/selenium/short-suite-management-ui
index 30f2e1e803dc..dbc82b3120c4 100644
--- a/selenium/short-suite-management-ui
+++ b/selenium/short-suite-management-ui
@@ -4,3 +4,4 @@ authnz-mgt/oauth-with-uaa.sh
mgt/vhosts.sh
mgt/exchanges.sh
mgt/limits.sh
+mgt/amqp10-connections.sh
diff --git a/selenium/suites/mgt/amqp10-connections.sh b/selenium/suites/mgt/amqp10-connections.sh
new file mode 100755
index 000000000000..91be8686f385
--- /dev/null
+++ b/selenium/suites/mgt/amqp10-connections.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+SCRIPT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+TEST_CASES_PATH=/connections/amqp10
+TEST_CONFIG_PATH=/basic-auth
+
+source $SCRIPT/../../bin/suite_template $@
+run
diff --git a/selenium/test/basic-auth/imports/users.json b/selenium/test/basic-auth/imports/users.json
index e6b99e3b2b4d..db893c83de9e 100644
--- a/selenium/test/basic-auth/imports/users.json
+++ b/selenium/test/basic-auth/imports/users.json
@@ -56,6 +56,9 @@
"vhosts": [
{
"name": "/"
+ },
+ {
+ "name": "other"
}
],
"permissions": [
@@ -79,6 +82,20 @@
"configure": ".*",
"write": ".*",
"read": ".*"
+ },
+ {
+ "user": "rabbit_no_management",
+ "vhost": "other",
+ "configure": ".*",
+ "write": ".*",
+ "read": ".*"
+ },
+ {
+ "user": "monitoring-only",
+ "vhost": "other",
+ "configure": ".*",
+ "write": ".*",
+ "read": ".*"
}
]
diff --git a/selenium/test/connections/amqp10/sessions-for-monitoring-user.js b/selenium/test/connections/amqp10/sessions-for-monitoring-user.js
new file mode 100644
index 000000000000..9a2817c3cb2f
--- /dev/null
+++ b/selenium/test/connections/amqp10/sessions-for-monitoring-user.js
@@ -0,0 +1,140 @@
+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 ConnectionsPage = require('../../pageobjects/ConnectionsPage')
+const ConnectionPage = require('../../pageobjects/ConnectionPage')
+
+var container = require('rhea') // https://github.com/amqp/rhea
+var receivedAmqpMessageCount = 0
+var untilConnectionEstablished = new Promise((resolve, reject) => {
+ container.on('connection_open', function(context) {
+ resolve()
+ })
+})
+
+container.on('message', function (context) {
+ receivedAmqpMessageCount++
+})
+container.once('sendable', function (context) {
+ context.sender.send({body:'first message'})
+})
+
+
+describe('Given an amqp10 connection opened, listed and clicked on it', function () {
+ let captureScreen
+ let connectionsPage
+ let connectionPage
+ let connection
+
+ before(async function () {
+ driver = buildDriver()
+ await goToHome(driver)
+ login = new LoginPage(driver)
+ overview = new OverviewPage(driver)
+ connectionsPage = new ConnectionsPage(driver)
+ connectionPage = new ConnectionPage(driver)
+ captureScreen = captureScreensFor(driver, __filename)
+ await login.login('monitoring-only', 'guest')
+ await overview.isLoaded()
+
+ connection = container.connect(
+ {'host': process.env.RABBITMQ_HOSTNAME || 'rabbitmq',
+ 'port': process.env.RABBITMQ_AMQP_PORT || 5672,
+ 'username' : process.env.RABBITMQ_AMQP_USERNAME || 'guest',
+ 'password' : process.env.RABBITMQ_AMQP_PASSWORD || 'guest',
+ 'id': "selenium-connection-id",
+ 'container_id': "selenium-container-id"
+ })
+ connection.open_receiver({
+ source: 'examples',
+ target: 'receiver-target',
+ name: 'receiver-link'
+ })
+ sender = connection.open_sender({
+ target: 'examples',
+ source: 'sender-source',
+ name: 'sender-link'
+ })
+ await untilConnectionEstablished
+ await overview.clickOnConnectionsTab()
+ await connectionsPage.isLoaded()
+
+ connections_table = await connectionsPage.getConnectionsTable(20)
+ assert.equal(1, connections_table.length)
+ await connectionsPage.clickOnConnection(2)
+ await connectionPage.isLoaded()
+ })
+
+
+ it('can list session information', async function () {
+ let sessions = await connectionPage.getSessions()
+ assert.equal(1, sessions.sessions.length)
+ let session = connectionPage.getSessionInfo(sessions.sessions, 0)
+ //console.log("session: " + JSON.stringify(session))
+ assert.equal(0, session.channelNumber)
+ assert.equal(1, session.nextIncomingId)
+ assert.equal(0, session.outgoingUnsettledDeliveries)
+ })
+
+ it('can list link information', async function () {
+ let sessions = await connectionPage.getSessions()
+ assert.equal(1, sessions.incoming_links.length)
+ assert.equal(1, sessions.outgoing_links.length)
+
+ let incomingLink = connectionPage.getIncomingLinkInfo(sessions.incoming_links, 0)
+ //console.log("incomingLink: " + JSON.stringify(incomingLink))
+ assert.equal(1, incomingLink.handle)
+ assert.equal("sender-link", incomingLink.name)
+ assert.equal("examples", incomingLink.targetAddress)
+ assert.equal("mixed", incomingLink.sndSettleMode)
+ assert.equal("0", incomingLink.unconfirmedMessages)
+ assert.equal(1, incomingLink.deliveryCount)
+
+ let outgoingLink = connectionPage.getOutgoingLinkInfo(sessions.outgoing_links, 0)
+ //console.log("outgoingLink: " + JSON.stringify(outgoingLink))
+ assert.equal(0, outgoingLink.handle)
+ assert.equal("receiver-link", outgoingLink.name)
+ assert.equal("examples", outgoingLink.sourceAddress)
+ assert.equal("examples", outgoingLink.queueName)
+
+ assert.equal(false, outgoingLink.sendSettled)
+ assert.equal("unlimited", outgoingLink.maxMessageSize)
+
+ })
+
+ it('display live link information', async function () {
+ var untilMessageReceived = new Promise((resolve, reject) => {
+ container.on('message', function(context) {
+ resolve()
+ })
+ })
+ sender.send({body:'second message'})
+ await untilMessageReceived
+ assert.equal(2, receivedAmqpMessageCount)
+
+ await delay(5*1000) // wait until page refreshes
+ let sessions = await connectionPage.getSessions()
+ let incomingLink = connectionPage.getIncomingLinkInfo(sessions.incoming_links, 0)
+ assert.equal(2, incomingLink.deliveryCount)
+
+ //console.log("incomingLink: " + JSON.stringify(incomingLink))
+ //console.log("outgoingLink: " + JSON.stringify(outgoingLink))
+ })
+
+
+ after(async function () {
+ await teardown(driver, this, captureScreen)
+ try {
+ if (connection != null) {
+ connection.close()
+ }
+ } catch (error) {
+ console.error("Failed to close amqp10 connection due to " + error);
+ }
+ })
+
+})
diff --git a/selenium/test/exchanges/management.js b/selenium/test/exchanges/management.js
index e63edc1f464a..78517c349454 100644
--- a/selenium/test/exchanges/management.js
+++ b/selenium/test/exchanges/management.js
@@ -32,13 +32,13 @@ describe('Exchange management', function () {
})
it('display summary of exchanges', async function () {
- assert.equal("All exchanges (8)", await exchanges.getPagingSectionHeaderText())
+ assert.equal("All exchanges (15)", await exchanges.getPagingSectionHeaderText())
})
it('list all default exchanges', async function () {
- actual_table = await exchanges.getExchangesTable(3)
- console.log("a :" + actual_table)
- expected_table = [
+ let actual_table = await exchanges.getExchangesTable(3)
+
+ let expected_table = [
["/", "(AMQP default)", "direct"],
["/", "amq.direct", "direct"],
["/", "amq.fanout", "fanout"],
@@ -46,8 +46,17 @@ describe('Exchange management', function () {
["/", "amq.match", "headers"],
["/", "amq.rabbitmq.event", "topic"],
["/", "amq.rabbitmq.trace", "topic"],
- ["/", "amq.topic", "topic"]
+ ["/", "amq.topic", "topic"],
+
+ ["other", "(AMQP default)", "direct"],
+ ["other", "amq.direct", "direct"],
+ ["other", "amq.fanout", "fanout"],
+ ["other", "amq.headers", "headers"],
+ ["other", "amq.match", "headers"],
+ ["other", "amq.rabbitmq.trace", "topic"],
+ ["other", "amq.topic", "topic"]
]
+
console.log("e :" + actual_table)
assert.deepEqual(actual_table, expected_table)
})
diff --git a/selenium/test/pageobjects/BasePage.js b/selenium/test/pageobjects/BasePage.js
index 2f00a5e67d71..b226501730ee 100644
--- a/selenium/test/pageobjects/BasePage.js
+++ b/selenium/test/pageobjects/BasePage.js
@@ -125,9 +125,10 @@ module.exports = class BasePage {
}
- async getTable(locator, firstNColumns) {
- const table = await this.waitForDisplayed(locator)
- const rows = await table.findElements(By.css('tbody tr'))
+ async getTable(tableLocator, firstNColumns, rowClass) {
+ const table = await this.waitForDisplayed(tableLocator)
+ const rows = await table.findElements(rowClass == undefined ?
+ By.css('tbody tr') : By.css('tbody tr.' + rowClass))
let table_model = []
for (let row of rows) {
let columns = await row.findElements(By.css('td'))
diff --git a/selenium/test/pageobjects/ConnectionPage.js b/selenium/test/pageobjects/ConnectionPage.js
new file mode 100644
index 000000000000..66e396afbc86
--- /dev/null
+++ b/selenium/test/pageobjects/ConnectionPage.js
@@ -0,0 +1,65 @@
+const { By, Key, until, Builder } = require('selenium-webdriver')
+
+const BasePage = require('./BasePage')
+
+
+const OVERVIEW_SECTION = By.css('div#main div.section#connection-overview-section')
+const SESSIONS_SECTION = By.css('div#main div.section#connection-sessions-section')
+const SESSIONS_TABLE = By.css('div.section#connection-sessions-section table.list#sessions')
+const INCOMING_LINKS_TABLE = By.css('div.section#connection-sessions-section table.list#incoming-links')
+const OUTCOMING_LINKS_TABLE = By.css('div.section#connection-sessions-section table.list#outgoing-links')
+const CONNECTION_NAME = By.css('div#main h2')
+
+
+module.exports = class ConnectionPage extends BasePage {
+ async isLoaded() {
+ return this.waitForDisplayed(CONNECTION_NAME)
+ }
+ async getName() {
+ return this.getText(CONNECTION_NAME)
+ }
+ async getSessions() {
+ await this.waitForDisplayed(SESSIONS_SECTION)
+ return {
+ sessions : await this.getTable(SESSIONS_TABLE, 100, "session"),
+ incoming_links : await this.getTable(INCOMING_LINKS_TABLE, 100, "link"),
+ outgoing_links : await this.getTable(OUTCOMING_LINKS_TABLE, 100, "link")
+ }
+ }
+ getSessionInfo(sessions, index) {
+ return {
+ channelNumber: sessions[index][0],
+ handleMax: sessions[index][1],
+ nextIncomingId: sessions[index][2],
+ incomingWindow: sessions[index][3],
+ nextOutgoingId: sessions[index][4],
+ remoteIncomingWindow: sessions[index][5],
+ remoteOutgoingWindow: sessions[index][6],
+ outgoingUnsettledDeliveries: sessions[index][7]
+ }
+ }
+ getIncomingLinkInfo(links, index) {
+ return {
+ handle: links[index][0],
+ name: links[index][1],
+ targetAddress: links[index][2],
+ sndSettleMode: links[index][3],
+ maxMessageSize: Number(links[index][4]),
+ deliveryCount: Number(links[index][5]),
+ linkCredit: Number(links[index][6]),
+ unconfirmedMessages: Number(links[index][7])
+ }
+ }
+ getOutgoingLinkInfo(links, index) {
+ return {
+ handle: links[index][0],
+ name: links[index][1],
+ sourceAddress: links[index][2],
+ queueName: links[index][3],
+ sendSettled: links[index][4] == "●" ? true : false,
+ maxMessageSize: links[index][5],
+ deliveryCount: Number(links[index][6]),
+ linkCredit: Number(links[index][7])
+ }
+ }
+}
diff --git a/selenium/test/pageobjects/ConnectionsPage.js b/selenium/test/pageobjects/ConnectionsPage.js
new file mode 100644
index 000000000000..0ef6a0b82c48
--- /dev/null
+++ b/selenium/test/pageobjects/ConnectionsPage.js
@@ -0,0 +1,25 @@
+const { By, Key, until, Builder } = require('selenium-webdriver')
+
+const BasePage = require('./BasePage')
+
+
+const PAGING_SECTION = By.css('div#connections-paging-section')
+const PAGING_SECTION_HEADER = By.css('div#connections-paging-section h2')
+
+const TABLE_SECTION = By.css('div#connections-table-section table')
+
+module.exports = class ConnectionsPage extends BasePage {
+ async isLoaded () {
+ return this.waitForDisplayed(PAGING_SECTION)
+ }
+ async getPagingSectionHeaderText() {
+ return this.getText(PAGING_SECTION_HEADER)
+ }
+ async getConnectionsTable(firstNColumns) {
+ return this.getTable(TABLE_SECTION, firstNColumns)
+ }
+ async clickOnConnection(index) {
+ return this.click(By.css(
+ "div#connections-table-section table tbody tr td:nth-child(" + index + ")"))
+ }
+}
diff --git a/selenium/test/pageobjects/OverviewPage.js b/selenium/test/pageobjects/OverviewPage.js
index 59eb0758a255..ed07cc21a94f 100644
--- a/selenium/test/pageobjects/OverviewPage.js
+++ b/selenium/test/pageobjects/OverviewPage.js
@@ -26,12 +26,5 @@ module.exports = class OverviewPage extends BasePage {
}
async downloadBrokerDefinitions(filename) {
return this.click(DOWNLOAD_DEFINITIONS_SECTION)
-
- /*
- await this.driver.sleep(1000)
- await this.sendKeys(CHOOSE_BROKER_DOWNLOAD_FILE, filename)
- await this.click(DOWNLOAD_BROKER_FILE)
- return driver.sleep(5000);
- */
}
}
| |