Merge pull request #13968 from rabbitmq/mergify/bp/v4.1.x/pr-13950
Trigger a 4.1.x alpha release build / trigger_alpha_build (push) Waiting to run
Details
Test (make) / Build and Xref (1.17, 26) (push) Waiting to run
Details
Test (make) / Build and Xref (1.17, 27) (push) Waiting to run
Details
Test (make) / Test (1.17, 27, khepri) (push) Waiting to run
Details
Test (make) / Test (1.17, 27, mnesia) (push) Waiting to run
Details
Test (make) / Test mixed clusters (1.17, 27, khepri) (push) Waiting to run
Details
Test (make) / Test mixed clusters (1.17, 27, mnesia) (push) Waiting to run
Details
Test (make) / Type check (1.17, 27) (push) Waiting to run
Details
Test Management UI with Selenium / selenium (chrome, 1.17.3, 27.3) (push) Waiting to run
Details
Trigger a 4.1.x alpha release build / trigger_alpha_build (push) Waiting to run
Details
Test (make) / Build and Xref (1.17, 26) (push) Waiting to run
Details
Test (make) / Build and Xref (1.17, 27) (push) Waiting to run
Details
Test (make) / Test (1.17, 27, khepri) (push) Waiting to run
Details
Test (make) / Test (1.17, 27, mnesia) (push) Waiting to run
Details
Test (make) / Test mixed clusters (1.17, 27, khepri) (push) Waiting to run
Details
Test (make) / Test mixed clusters (1.17, 27, mnesia) (push) Waiting to run
Details
Test (make) / Type check (1.17, 27) (push) Waiting to run
Details
Test Management UI with Selenium / selenium (chrome, 1.17.3, 27.3) (push) Waiting to run
Details
Selenium: Verify consumer state when using SAC (backport #13950)
This commit is contained in:
commit
938a2f5f96
|
@ -1529,9 +1529,12 @@ activate_next_consumer(#?STATE{consumers = Cons0,
|
|||
State = State0#?STATE{consumers = Cons,
|
||||
service_queue = ServiceQueue1,
|
||||
waiting_consumers = Waiting},
|
||||
Effects1 = consumer_update_active_effects(State, Active,
|
||||
false, waiting,
|
||||
Effects0),
|
||||
Effects = consumer_update_active_effects(State, Consumer,
|
||||
true, single_active,
|
||||
Effects0),
|
||||
Effects1),
|
||||
{State, Effects};
|
||||
{{ActiveCKey, ?CONSUMER_PRIORITY(ActivePriority) = Active},
|
||||
{_NextCKey, ?CONSUMER_PRIORITY(WaitingPriority)}}
|
||||
|
@ -1829,8 +1832,22 @@ complete_and_checkout(#{} = Meta, MsgIds, ConsumerKey,
|
|||
Effects0, State0) ->
|
||||
State1 = complete(Meta, ConsumerKey, MsgIds, Con0, State0),
|
||||
%% a completion could have removed the active/quiescing consumer
|
||||
{State2, Effects1} = activate_next_consumer(State1, Effects0),
|
||||
checkout(Meta, State0, State2, Effects1).
|
||||
Effects1 = add_active_effect(Con0, State1, Effects0),
|
||||
{State2, Effects2} = activate_next_consumer(State1, Effects1),
|
||||
checkout(Meta, State0, State2, Effects2).
|
||||
|
||||
add_active_effect(#consumer{status = quiescing} = Consumer,
|
||||
#?STATE{cfg = #cfg{consumer_strategy = single_active},
|
||||
consumers = Consumers} = State,
|
||||
Effects) ->
|
||||
case active_consumer(Consumers) of
|
||||
undefined ->
|
||||
consumer_update_active_effects(State, Consumer, false, waiting, Effects);
|
||||
_ ->
|
||||
Effects
|
||||
end;
|
||||
add_active_effect(_, _, Effects) ->
|
||||
Effects.
|
||||
|
||||
cancel_consumer_effects(ConsumerId,
|
||||
#?STATE{cfg = #cfg{resource = QName}},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<% if (consumers.length > 0) { %>
|
||||
<table class="list">
|
||||
<table class="list" id="consumers">
|
||||
<thead>
|
||||
<tr>
|
||||
<% if (mode == 'queue') { %>
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
<% } %>
|
||||
|
||||
<h3>Details</h3>
|
||||
<table class="facts facts-l">
|
||||
<table class="facts facts-l" id="details-queue-table">
|
||||
<tr>
|
||||
<th>Features</th>
|
||||
<td><%= fmt_features(queue) %></td>
|
||||
<td id="details-queue-features"><%= fmt_features(queue) %></td>
|
||||
</tr>
|
||||
<% if(!disable_stats) { %>
|
||||
<tr>
|
||||
|
@ -76,7 +76,7 @@
|
|||
</table>
|
||||
|
||||
<% if(!disable_stats) { %>
|
||||
<table class="facts facts-l">
|
||||
<table class="facts facts-l" id="details-queue-stats-table">
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<td><%= fmt_object_state(queue) %></td>
|
||||
|
@ -84,12 +84,12 @@
|
|||
<% if(queue.consumers) { %>
|
||||
<tr>
|
||||
<th>Consumers</th>
|
||||
<td><%= fmt_string(queue.consumers) %></td>
|
||||
<td id="consumers"><%= fmt_string(queue.consumers) %></td>
|
||||
</tr>
|
||||
<% } else if(queue.hasOwnProperty('consumer_details')) { %>
|
||||
<tr>
|
||||
<th>Consumers</th>
|
||||
<td><%= fmt_string(queue.consumer_details.length) %></td>
|
||||
<td id="consumers"><%= fmt_string(queue.consumer_details.length) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% if (is_classic(queue)) { %>
|
||||
|
@ -277,7 +277,7 @@
|
|||
<% } %>
|
||||
|
||||
<% if(!disable_stats) { %>
|
||||
<div class="section-hidden">
|
||||
<div class="section-hidden" id="queue-consumers-section">
|
||||
<h2 class="updatable">Consumers (<%=(queue.consumer_details.length)%>) </h2>
|
||||
<div class="hider updatable">
|
||||
<%= format('consumers', {'mode': 'queue', 'consumers': queue.consumer_details}) %>
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
<table class="facts facts-l" id="details-queue-stats-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<td><%= fmt_object_state(queue) %></td>
|
||||
</tr>
|
||||
<% if(queue.consumers) { %>
|
||||
<tr>
|
||||
<th>Consumers</th>
|
||||
<td id="consumers"><%= fmt_string(queue.consumers) %></td>
|
||||
</tr>
|
||||
<% } else if(queue.hasOwnProperty('consumer_details')) { %>
|
||||
<tr>
|
||||
<th>Consumers</th>
|
||||
<td id="consumers"><%= fmt_string(queue.consumer_details.length) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<% if(queue.hasOwnProperty('publishers')) { %>
|
||||
<tr>
|
||||
<th>Publishers</th>
|
||||
<td id="publishers"><%= fmt_string(queue.publishers) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<tr>
|
||||
<th>Open files</th>
|
||||
<td><%= fmt_table_short(queue.open_files) %></td>
|
||||
</tr>
|
||||
<% if (queue.hasOwnProperty('delivery_limit')) { %>
|
||||
<tr>
|
||||
<th>Delivery limit <span class="help" id="queue-delivery-limit"></th>
|
||||
<td><%= fmt_string(queue.delivery_limit) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="facts">
|
||||
<tr>
|
||||
<td></td>
|
||||
<th class="horizontal">Total</th>
|
||||
<th class="horizontal">Ready</th>
|
||||
<th class="horizontal">Unacked</th>
|
||||
<th class="horizontal">High priority</th>
|
||||
<th class="horizontal">Normal priority</th>
|
||||
<th class="horizontal">Returned</th>
|
||||
<th class="horizontal">Dead-lettered
|
||||
<span class="help" id="queue-dead-lettered"></span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Messages
|
||||
<span class="help" id="queue-messages"></span>
|
||||
</th>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages_ready) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages_unacknowledged) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages_ready_high) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages_ready_normal) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages_ready_returned) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_num_thousands(queue.messages_dlx) %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Message body bytes
|
||||
<span class="help" id="queue-message-body-bytes"></span>
|
||||
</th>
|
||||
<td class="r">
|
||||
<%= fmt_bytes(queue.message_bytes) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_bytes(queue.message_bytes_ready) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_bytes(queue.message_bytes_unacknowledged) %>
|
||||
</td>
|
||||
<td class="r">
|
||||
</td>
|
||||
<td class="r">
|
||||
</td>
|
||||
<td class="r">
|
||||
</td>
|
||||
<td class="r">
|
||||
<%= fmt_bytes(queue.message_bytes_dlx) %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Process memory
|
||||
<span class="help" id="queue-process-memory"></span>
|
||||
</th>
|
||||
<td class="r"><%= fmt_bytes(queue.memory) %></td>
|
||||
</tr>
|
||||
</table>
|
|
@ -1,5 +1,4 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
FROM atools/jdk-maven-node:mvn3-jdk11-node16 as base
|
||||
FROM node:18 as base
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
"proxy": "^1.0.2",
|
||||
"rhea": "^3.0.3",
|
||||
"selenium-webdriver": "^4.26.0",
|
||||
"xmlhttprequest": "^1.8.0"
|
||||
"xmlhttprequest": "^1.8.0",
|
||||
"amqplib": "0.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.3.6",
|
||||
|
|
|
@ -7,6 +7,7 @@ var connectionOptions = getConnectionOptions()
|
|||
|
||||
function getAmqpConnectionOptions() {
|
||||
return {
|
||||
'scheme': process.env.RABBITMQ_AMQP_SCHEME || 'amqp',
|
||||
'host': process.env.RABBITMQ_HOSTNAME || 'rabbitmq',
|
||||
'port': process.env.RABBITMQ_AMQP_PORT || 5672,
|
||||
'username' : process.env.RABBITMQ_AMQP_USERNAME || 'guest',
|
||||
|
@ -39,21 +40,28 @@ function getConnectionOptions() {
|
|||
}
|
||||
}
|
||||
module.exports = {
|
||||
|
||||
open: () => {
|
||||
getAmqpConnectionOptions: () => { return connectionOptions },
|
||||
getAmqpUrl: () => {
|
||||
return connectionOptions.scheme + '://' +
|
||||
connectionOptions.username + ":" + connectionOptions.password + "@" +
|
||||
connectionOptions.host + ":" + connectionOptions.port
|
||||
},
|
||||
open: (queueName = "my-queue") => {
|
||||
let promise = new Promise((resolve, reject) => {
|
||||
container.on('connection_open', function(context) {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
console.log("Opening amqp connection using " + JSON.stringify(connectionOptions))
|
||||
|
||||
let connection = container.connect(connectionOptions)
|
||||
let receiver = connection.open_receiver({
|
||||
source: 'my-queue',
|
||||
source: queueName,
|
||||
target: 'receiver-target',
|
||||
name: 'receiver-link'
|
||||
})
|
||||
let sender = connection.open_sender({
|
||||
target: 'my-queue',
|
||||
target: queueName,
|
||||
source: 'sender-source',
|
||||
name: 'sender-link'
|
||||
})
|
||||
|
@ -64,6 +72,13 @@ module.exports = {
|
|||
'sender' : sender
|
||||
}
|
||||
},
|
||||
openReceiver: (handler, queueName = "my-queue") => {
|
||||
return handler.connection.open_receiver({
|
||||
source: queueName,
|
||||
target: 'receiver-target',
|
||||
name: 'receiver-link'
|
||||
})
|
||||
},
|
||||
close: (connection) => {
|
||||
if (connection != null) {
|
||||
connection.close()
|
||||
|
|
|
@ -30,7 +30,8 @@ describe('Exchange management', function () {
|
|||
if (!await overview.isLoaded()) {
|
||||
throw new Error('Failed to login')
|
||||
}
|
||||
overview.clickOnExchangesTab()
|
||||
await overview.selectRefreshOption("Do not refresh")
|
||||
await overview.clickOnExchangesTab()
|
||||
})
|
||||
|
||||
it('display summary of exchanges', async function () {
|
||||
|
|
|
@ -114,7 +114,7 @@ module.exports = {
|
|||
throw new Error(req.responseText)
|
||||
}
|
||||
},
|
||||
createVhost: (url, name, description = "", tags = []) => {
|
||||
createVhost: (url, authorization, name, description = "", tags = []) => {
|
||||
let vhost = {
|
||||
"description": description,
|
||||
"tags": tags
|
||||
|
@ -122,10 +122,9 @@ module.exports = {
|
|||
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("Authorization", authorization)
|
||||
req.setRequestHeader('Content-Type', 'application/json')
|
||||
|
||||
req.send(JSON.stringify(vhost))
|
||||
|
@ -158,13 +157,12 @@ module.exports = {
|
|||
throw new Error(req.responseText)
|
||||
}
|
||||
},
|
||||
deleteVhost: (url, vhost) => {
|
||||
deleteVhost: (url, authorization, 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.setRequestHeader("Authorization", authorization)
|
||||
|
||||
req.send()
|
||||
if (req.status == 200 || req.status == 204) {
|
||||
|
@ -194,21 +192,18 @@ module.exports = {
|
|||
throw new Error(req.responseText)
|
||||
}
|
||||
},
|
||||
createQueue: (url, name, vhost, queueType = "quorum") => {
|
||||
createQueue: (url, authorization, vhost, name, arguments = {}) => {
|
||||
log("Create queue " + JSON.stringify(name)
|
||||
+ " in vhost " + vhost + " on " + url)
|
||||
const req = new XMLHttpRequest()
|
||||
let base64Credentials = btoa('administrator-only' + ":" + 'guest')
|
||||
let finalUrl = url + "/api/queues/" + encodeURIComponent(vhost) + "/"
|
||||
+ encodeURIComponent(name)
|
||||
req.open('PUT', finalUrl, false)
|
||||
req.setRequestHeader("Authorization", "Basic " + base64Credentials)
|
||||
req.setRequestHeader("Authorization", authorization)
|
||||
req.setRequestHeader('Content-Type', 'application/json')
|
||||
let payload = {
|
||||
"durable": true,
|
||||
"arguments":{
|
||||
"x-queue-type" : queueType
|
||||
}
|
||||
"arguments": arguments
|
||||
}
|
||||
req.send(JSON.stringify(payload))
|
||||
if (req.status == 200 || req.status == 204 || req.status == 201) {
|
||||
|
@ -219,14 +214,13 @@ module.exports = {
|
|||
throw new Error(req.responseText)
|
||||
}
|
||||
},
|
||||
deleteQueue: (url, name, vhost) => {
|
||||
deleteQueue: (url, authorization, vhost, name) => {
|
||||
log("Deleting queue " + name + " on vhost " + vhost)
|
||||
const req = new XMLHttpRequest()
|
||||
let base64Credentials = btoa('administrator-only' + ":" + 'guest')
|
||||
let finalUrl = url + "/api/queues/" + encodeURIComponent(vhost) + "/"
|
||||
+ encodeURIComponent(name)
|
||||
req.open('DELETE', finalUrl, false)
|
||||
req.setRequestHeader("Authorization", "Basic " + base64Credentials)
|
||||
req.setRequestHeader("Authorization", authorization)
|
||||
|
||||
req.send()
|
||||
if (req.status == 200 || req.status == 204) {
|
||||
|
|
|
@ -34,7 +34,12 @@ module.exports = class BasePage {
|
|||
this.interactionDelay = parseInt(process.env.SELENIUM_INTERACTION_DELAY) || 0 // slow down interactions (when rabbit is behind a http proxy)
|
||||
}
|
||||
|
||||
|
||||
async goTo(path) {
|
||||
return driver.get(d.baseUrl + path)
|
||||
}
|
||||
async refresh() {
|
||||
return this.driver.navigate().refresh()
|
||||
}
|
||||
async isLoaded () {
|
||||
return this.waitForDisplayed(MENU_TABS)
|
||||
}
|
||||
|
@ -147,11 +152,63 @@ module.exports = class BasePage {
|
|||
const select = await new Select(selectable)
|
||||
return select.selectByValue(vhost)
|
||||
}
|
||||
async getTableMini(tableLocator) {
|
||||
const table = await this.waitForDisplayed(tableLocator)
|
||||
return this.getTableMiniUsingTableElement(table)
|
||||
}
|
||||
async getTableMiniUsingTableElement(table) {
|
||||
let tbody = await table.findElement(By.css('tbody'))
|
||||
let rows = await tbody.findElements(By.xpath("./child::*"))
|
||||
|
||||
let table_model = []
|
||||
for (let row of rows) {
|
||||
let columnName = await row.findElement(By.css('th')).getText()
|
||||
|
||||
let columnValue = await row.findElement(By.css('td'))
|
||||
let columnContent = await columnValue.findElement(By.xpath("./child::*"))
|
||||
|
||||
let columnType = await columnContent.getTagName()
|
||||
|
||||
switch (columnType) {
|
||||
case "table":
|
||||
table_model.push({
|
||||
"name": columnName,
|
||||
"value" : await this.getTableMiniUsingTableElement(columnValue)
|
||||
})
|
||||
break
|
||||
default:
|
||||
table_model.push({
|
||||
"name" : columnName,
|
||||
"value" : await columnContent.getText()
|
||||
})
|
||||
}
|
||||
}
|
||||
return table_model
|
||||
}
|
||||
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))
|
||||
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'))
|
||||
let table_row = []
|
||||
for (let column of columns) {
|
||||
if (firstNColumns == undefined || table_row.length < firstNColumns) {
|
||||
table_row.push(await column.getText())
|
||||
}
|
||||
}
|
||||
table_model.push(table_row)
|
||||
}
|
||||
return table_model
|
||||
}
|
||||
async getPlainTable(tableLocator, firstNColumns) {
|
||||
const table = await this.waitForDisplayed(tableLocator)
|
||||
let tbody = await table.findElement(By.css('tbody'))
|
||||
let rows = await tbody.findElements(By.xpath("./child::*"))
|
||||
let table_model = []
|
||||
|
||||
for (let row of rows) {
|
||||
let columns = await row.findElements(By.css('td'))
|
||||
let table_row = []
|
||||
|
|
|
@ -7,14 +7,36 @@ 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]')
|
||||
const FEATURES_TABLE = By.css('table#details-queue-table td#details-queue-features table.mini')
|
||||
const STATS_CONSUMER_COUNT = By.css('table#details-queue-stats-table td#consumers')
|
||||
|
||||
const CONSUMERS_SECTION = By.css('div#queue-consumers-section')
|
||||
const CONSUMERS_SECTION_TITLE = By.css('div#queue-consumers-section h2')
|
||||
const CONSUMERS_TABLE = By.css('div#queue-consumers-section table.list#consumers')
|
||||
|
||||
module.exports = class QueuePage extends BasePage {
|
||||
async isLoaded() {
|
||||
return this.waitForDisplayed(QUEUE_NAME)
|
||||
}
|
||||
|
||||
async getName() {
|
||||
return this.getText(QUEUE_NAME)
|
||||
}
|
||||
async getConsumerCount() {
|
||||
return this.getText(STATS_CONSUMER_COUNT)
|
||||
}
|
||||
async getFeatures() {
|
||||
return this.getTableMini(FEATURES_TABLE)
|
||||
}
|
||||
async getConsumersSectionTitle() {
|
||||
return this.getText(CONSUMERS_SECTION_TITLE)
|
||||
}
|
||||
async clickOnConsumerSection() {
|
||||
return this.click(CONSUMERS_SECTION)
|
||||
}
|
||||
async getConsumersTable() {
|
||||
return this.getPlainTable(CONSUMERS_TABLE)
|
||||
}
|
||||
async ensureDeleteQueueSectionIsVisible() {
|
||||
await this.click(DELETE_SECTION)
|
||||
return this.driver.findElement(DELETE_SECTION).isDisplayed()
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
const { By, Key, until, Builder } = require('selenium-webdriver')
|
||||
require('chromedriver')
|
||||
const assert = require('assert')
|
||||
const { buildDriver, goToHome, captureScreensFor, teardown, doWhile, goToQueue,delay } = require('../utils')
|
||||
const { createQueue, deleteQueue, getManagementUrl, basicAuthorization } = require('../mgt-api')
|
||||
const { getAmqpUrl : getAmqpUrl } = require('../amqp')
|
||||
const amqplib = require('amqplib');
|
||||
|
||||
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('Given a quorum queue configured with SAC', function () {
|
||||
let login
|
||||
let queuesAndStreams
|
||||
let queuePage
|
||||
let queueName
|
||||
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)
|
||||
queuePage = 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")
|
||||
queueName = "test_" + Math.floor(Math.random() * 1000)
|
||||
|
||||
createQueue(getManagementUrl(), basicAuthorization("management", "guest"),
|
||||
"/", queueName, {
|
||||
"x-queue-type": "quorum",
|
||||
"x-single-active-consumer": true
|
||||
})
|
||||
|
||||
await goToQueue(driver, "/", queueName)
|
||||
await queuePage.isLoaded()
|
||||
assert.equal(queueName, await queuePage.getName())
|
||||
|
||||
})
|
||||
|
||||
it('it must display its queue-type and durability', async function () {
|
||||
let table = await queuePage.getFeatures()
|
||||
assert.equal(table[0].name, "arguments:")
|
||||
let expectedArguments = [
|
||||
{"name":"x-queue-type:", "value":"quorum"}
|
||||
]
|
||||
assert.equal(JSON.stringify(table[0].value), JSON.stringify(expectedArguments))
|
||||
assert.equal(table[1].name, "x-single-active-consumer:")
|
||||
assert.equal(table[1].value, "true")
|
||||
assert.equal(table[2].name, "durable:")
|
||||
assert.equal(table[2].value, "true")
|
||||
})
|
||||
|
||||
it('it should not have any consumers', async function() {
|
||||
assert.equal("0", await queuePage.getConsumerCount())
|
||||
assert.equal("Consumers (0)", await queuePage.getConsumersSectionTitle())
|
||||
})
|
||||
|
||||
describe("given there is a consumer (without priority) attached to the queue", function () {
|
||||
let amqp091conn
|
||||
let ch1
|
||||
let ch1Consumer
|
||||
let ch2
|
||||
let ch2Consumer
|
||||
|
||||
before(async function() {
|
||||
let amqpUrl = getAmqpUrl() + "?frameMax=0"
|
||||
amqp091conn = await amqplib.connect(amqpUrl)
|
||||
ch1 = await amqp091conn.createChannel()
|
||||
ch1Consumer = ch1.consume(queueName, (msg) => {}, {consumerTag: "one"})
|
||||
})
|
||||
|
||||
it('it should have one consumer as active', async function() {
|
||||
await doWhile(async function() {
|
||||
await queuePage.refresh()
|
||||
await queuePage.isLoaded()
|
||||
return queuePage.getConsumerCount()
|
||||
}, function(count) {
|
||||
return count.localeCompare("0") == 1
|
||||
}, 5000)
|
||||
assert.equal("1", await queuePage.getConsumerCount())
|
||||
assert.equal("Consumers (1)", await queuePage.getConsumersSectionTitle())
|
||||
await queuePage.clickOnConsumerSection()
|
||||
let consumerTable = await doWhile(async function() {
|
||||
return queuePage.getConsumersTable()
|
||||
}, function(table) {
|
||||
return table[0][6].localeCompare("single active") == 0 &&
|
||||
table[0][1].localeCompare("one") == 0
|
||||
})
|
||||
assert.equal("single active", consumerTable[0][6])
|
||||
assert.equal("one", consumerTable[0][1])
|
||||
|
||||
})
|
||||
|
||||
describe("given another consumer is added with priority", function () {
|
||||
before(async function() {
|
||||
ch2 = await amqp091conn.createChannel()
|
||||
ch2Consumer = ch2.consume(queueName, (msg) => {}, {consumerTag: "two", priority: 10})
|
||||
})
|
||||
|
||||
it('the latter consumer should be active and the former waiting', async function() {
|
||||
|
||||
await doWhile(async function() {
|
||||
await queuePage.refresh()
|
||||
await queuePage.isLoaded()
|
||||
return queuePage.getConsumerCount()
|
||||
}, function(count) {
|
||||
return count.localeCompare("2") == 0
|
||||
}, 5000)
|
||||
|
||||
assert.equal("2", await queuePage.getConsumerCount())
|
||||
assert.equal("Consumers (2)", await queuePage.getConsumersSectionTitle())
|
||||
await queuePage.clickOnConsumerSection()
|
||||
let consumerTable = await doWhile(async function() {
|
||||
return queuePage.getConsumersTable()
|
||||
}, function(table) {
|
||||
return table.length == 2 && table[0][1] != "" && table[1][1] != ""
|
||||
}, 5000)
|
||||
|
||||
let activeConsumer = consumerTable[1][6].localeCompare("single active") == 0 ?
|
||||
1 : 0
|
||||
let nonActiveConsumer = activeConsumer == 1 ? 0 : 1
|
||||
|
||||
assert.equal("waiting", consumerTable[nonActiveConsumer][6])
|
||||
assert.equal("one", consumerTable[nonActiveConsumer][1])
|
||||
assert.equal("single active", consumerTable[activeConsumer][6])
|
||||
assert.equal("two", consumerTable[activeConsumer][1])
|
||||
await delay(5000)
|
||||
})
|
||||
})
|
||||
|
||||
after(async function() {
|
||||
try {
|
||||
if (amqp091conn != null) {
|
||||
amqp091conn.close()
|
||||
}
|
||||
} catch (error) {
|
||||
error("Failed to close amqp091 connection due to " + error);
|
||||
}
|
||||
// ensure there are no more consumers
|
||||
await doWhile(async function() {
|
||||
await queuePage.refresh()
|
||||
await queuePage.isLoaded()
|
||||
return queuePage.getConsumerCount()
|
||||
}, function(count) {
|
||||
return count.localeCompare("0") == 0
|
||||
}, 5000)
|
||||
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe("given there is a consumer (with priority) attached to the queue", function () {
|
||||
let amqp091conn
|
||||
let ch1
|
||||
let ch1Consumer
|
||||
let ch2
|
||||
let ch2Consumer
|
||||
|
||||
before(async function() {
|
||||
let amqpUrl = getAmqpUrl() + "?frameMax=0"
|
||||
amqp091conn = await amqplib.connect(amqpUrl)
|
||||
ch1 = await amqp091conn.createChannel()
|
||||
ch1Consumer = ch1.consume(queueName, (msg) => {}, {consumerTag: "one", priority: 10})
|
||||
})
|
||||
|
||||
it('it should have one consumer as active', async function() {
|
||||
await doWhile(async function() {
|
||||
await queuePage.refresh()
|
||||
await queuePage.isLoaded()
|
||||
return queuePage.getConsumerCount()
|
||||
}, function(count) {
|
||||
return count.localeCompare("0") == 1
|
||||
}, 5000)
|
||||
assert.equal("1", await queuePage.getConsumerCount())
|
||||
assert.equal("Consumers (1)", await queuePage.getConsumersSectionTitle())
|
||||
await queuePage.clickOnConsumerSection()
|
||||
let consumerTable = await doWhile(async function() {
|
||||
return queuePage.getConsumersTable()
|
||||
}, function(table) {
|
||||
return table[0][6].localeCompare("single active") == 0 &&
|
||||
table[0][1].localeCompare("one") == 0
|
||||
})
|
||||
assert.equal("single active", consumerTable[0][6])
|
||||
assert.equal("one", consumerTable[0][1])
|
||||
|
||||
})
|
||||
|
||||
describe("given another consumer is added without priority", function () {
|
||||
before(async function() {
|
||||
ch2 = await amqp091conn.createChannel()
|
||||
ch2Consumer = ch2.consume(queueName, (msg) => {}, {consumerTag: "two"})
|
||||
})
|
||||
|
||||
it('the former consumer should still be active and the latter be waiting', async function() {
|
||||
|
||||
await doWhile(async function() {
|
||||
await queuePage.refresh()
|
||||
await queuePage.isLoaded()
|
||||
return queuePage.getConsumerCount()
|
||||
}, function(count) {
|
||||
return count.localeCompare("2") == 0
|
||||
}, 5000)
|
||||
|
||||
assert.equal("2", await queuePage.getConsumerCount())
|
||||
assert.equal("Consumers (2)", await queuePage.getConsumersSectionTitle())
|
||||
await queuePage.clickOnConsumerSection()
|
||||
let consumerTable = await doWhile(async function() {
|
||||
return queuePage.getConsumersTable()
|
||||
}, function(table) {
|
||||
return table.length == 2 && table[0][1] != "" && table[1][1] != ""
|
||||
}, 5000)
|
||||
|
||||
let activeConsumer = consumerTable[1][6].localeCompare("single active") == 0 ?
|
||||
1 : 0
|
||||
let nonActiveConsumer = activeConsumer == 1 ? 0 : 1
|
||||
|
||||
assert.equal("waiting", consumerTable[nonActiveConsumer][6])
|
||||
assert.equal("two", consumerTable[nonActiveConsumer][1])
|
||||
assert.equal("single active", consumerTable[activeConsumer][6])
|
||||
assert.equal("one", consumerTable[activeConsumer][1])
|
||||
await delay(5000)
|
||||
})
|
||||
})
|
||||
|
||||
after(function() {
|
||||
try {
|
||||
if (amqp091conn != null) {
|
||||
amqp091conn.close()
|
||||
}
|
||||
} catch (error) {
|
||||
error("Failed to close amqp091 connection due to " + error);
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await teardown(driver, this, captureScreen)
|
||||
deleteQueue(getManagementUrl(), basicAuthorization("management", "guest"),
|
||||
"/", queueName)
|
||||
})
|
||||
})
|
|
@ -129,9 +129,9 @@ module.exports = {
|
|||
goToExchanges: (d) => {
|
||||
return d.driver.get(d.baseUrl + '#/exchanges')
|
||||
},
|
||||
|
||||
goTo: (d, address) => {
|
||||
return d.get(address)
|
||||
|
||||
goToQueue(d, vhost, queue) {
|
||||
return d.driver.get(d.baseUrl + '#/queues/' + encodeURIComponent(vhost) + '/' + encodeURIComponent(queue))
|
||||
},
|
||||
|
||||
delay: async (msec, ref) => {
|
||||
|
|
|
@ -2,7 +2,7 @@ const { By, Key, until, Builder } = require('selenium-webdriver')
|
|||
require('chromedriver')
|
||||
const assert = require('assert')
|
||||
const { buildDriver, goToHome, captureScreensFor, teardown, doWhile, log, delay } = require('../utils')
|
||||
const { getManagementUrl, createVhost, deleteVhost } = require('../mgt-api')
|
||||
const { getManagementUrl, basicAuthorization, createVhost, deleteVhost } = require('../mgt-api')
|
||||
|
||||
const LoginPage = require('../pageobjects/LoginPage')
|
||||
const OverviewPage = require('../pageobjects/OverviewPage')
|
||||
|
@ -107,7 +107,8 @@ describe('Virtual Hosts in Admin tab', function () {
|
|||
let vhost = "test_" + Math.floor(Math.random() * 1000)
|
||||
before(async function() {
|
||||
log("Creating vhost")
|
||||
createVhost(getManagementUrl(), vhost, "selenium", "selenium-tag")
|
||||
createVhost(getManagementUrl(), basicAuthorization('administrator-only', 'guest'),
|
||||
vhost, "selenium", "selenium-tag")
|
||||
// await overview.clickOnOverviewTab()
|
||||
await overview.clickOnAdminTab()
|
||||
await adminTab.clickOnVhosts()
|
||||
|
@ -131,7 +132,8 @@ describe('Virtual Hosts in Admin tab', function () {
|
|||
})
|
||||
after(async function () {
|
||||
log("Deleting vhost")
|
||||
deleteVhost(getManagementUrl(), vhost)
|
||||
deleteVhost(getManagementUrl(), basicAuthorization("administrator-only", "guest"),
|
||||
vhost)
|
||||
})
|
||||
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue