Improve how to look for elements and wait for them

This commit is contained in:
Marcial Rosales 2023-02-21 13:07:37 +01:00
parent fe1b7cb17a
commit 89ee77e5ec
11 changed files with 85 additions and 135 deletions

View File

@ -1,6 +1,6 @@
<form action="<%= url %>" method="POST"> <form action="<%= url %>" id="login_form" method="POST">
<input type="hidden" name="access_token" value="<%= access_token %>"> <input type="hidden" name="access_token" value="<%= access_token %>">
<input type="submit" value="<%= name %>"> <input type="submit" value="<%= name %>">
</form> </form>

View File

@ -52,12 +52,17 @@ kill_container_if_exist() {
docker stop $1 &> /dev/null || true && docker rm $1 &> /dev/null || true docker stop $1 &> /dev/null || true && docker rm $1 &> /dev/null || true
} }
wait_for_message() { wait_for_message() {
attemps_left=10
while ! docker logs $1 | grep -q "$2"; while ! docker logs $1 | grep -q "$2";
do do
sleep 5 sleep 5
echo "Waiting 5sec for $1 to start ..." echo "Waiting 5sec for $1 to start ($attemps_left attempts left )..."
((attemps_left--))
if [[ "$attemps_left" -lt 1 ]]; then
echo "Timed out waiting"
exit 1
fi
done done
} }
init_rabbitmq() { init_rabbitmq() {

View File

@ -20,10 +20,8 @@ describe('An internal user with administrator tag', function () {
}) })
it('can log in into the management ui', async function () { it('can log in into the management ui', async function () {
await login.login('guest', 'guest') await login.login('guest', 'guest')
if (!await overview.isLoaded()) { await overview.isLoaded()
throw new Error('Failed to login')
}
assert.equal(await overview.getUser(), 'User guest') assert.equal(await overview.getUser(), 'User guest')
}) })

View File

@ -0,0 +1,30 @@
[
{rabbit, [
{auth_backends, [rabbit_auth_backend_oauth2]}
]},
{rabbitmq_management, [
{login_session_timeout, 1}, %% in minutes
{oauth_enabled, true},
{oauth_initiated_logon_type, idp_initiated},
{oauth_provider_url, "http://localhost:3000"}
]},
{rabbitmq_auth_backend_oauth2, [
{resource_server_id, <<"rabbitmq">>},
{preferred_username_claims, [<<"user_name">>]},
{key_config, [
{default_key, <<"legacy-token-key">>},
{signing_keys,
#{<<"legacy-token-key">> => {pem, <<"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2dP+vRn+Kj+S/oGd49kq
6+CKNAduCC1raLfTH7B3qjmZYm45yDl+XmgK9CNmHXkho9qvmhdksdzDVsdeDlhK
IdcIWadhqDzdtn1hj/22iUwrhH0bd475hlKcsiZ+oy/sdgGgAzvmmTQmdMqEXqV2
B9q9KFBmo4Ahh/6+d4wM1rH9kxl0RvMAKLe+daoIHIjok8hCO4cKQQEw/ErBe4SF
2cr3wQwCfF1qVu4eAVNVfxfy/uEvG3Q7x005P3TcK+QcYgJxav3lictSi5dyWLgG
QAvkknWitpRK8KVLypEj5WKej6CF8nq30utn15FQg0JkHoqzwiCqqeen8GIPteI7
VwIDAQAB
-----END PUBLIC KEY-----">>}
}
}]
}
]}
].

View File

@ -2,148 +2,67 @@ const { By, Key, until, Builder } = require('selenium-webdriver')
module.exports = class BasePage { module.exports = class BasePage {
driver driver
timeout
polling
constructor (webdriver) { constructor (webdriver) {
this.driver = webdriver this.driver = webdriver
// this is another timeout (--timeout 10000) which is the maximum test execution time
this.timeout = parseInt(process.env.TIMEOUT) || 5000 // max time waiting to locate an element. Should be less that test timeout
this.polling = parseInt(process.env.POLLING) || 1000 // how frequent selenium searches for an element
} }
async waitForLocated (locator, retries = 3) { async waitForLocated (locator) {
try { return this.driver.wait(until.elementLocated(locator), this.timeout, 'Timed out after 30 seconds', this.polling);
await this.driver.wait(until.elementLocated(locator), 2000)
} catch (err) {
if (retries === 0) {
throw new Error(`Still not able to locate element ${locator.toString()} after maximum retries, Error message: ${err.message.toString()}`)
}
await this.driver.sleep(250)
return this.waitForLocated(driver, locator, retries - 1)
}
} }
async waitForVisible (locator, retries = 3) { async waitForVisible (element) {
try { return this.driver.wait(until.elementIsVisible(element), this.timeout, 'Timed out after 30 seconds', this.polling);
const element = await this.driver.findElement(locator)
await this.driver.wait(until.elementIsVisible(element), 2000)
} catch (err) {
if (retries === 0) {
throw new Error(`Element ${locator.toString()} still not visible after maximum retries, Error message: ${err.message.toString()}`)
}
await this.driver.sleep(250)
return this.waitForVisible(driver, locator, retries - 1)
}
} }
async waitForDisplayed (locator, retries = 3) { async waitForDisplayed (locator) {
await this.waitForLocated(locator, retries) return this.waitForVisible(await this.waitForLocated(locator))
await this.waitForVisible(locator, retries)
return this.driver.findElement(locator)
} }
async hasElement (locator) { async getText (locator) {
const count = await this.driver.findElements(locator).size() const element = await this.waitForDisplayed(locator)
throw new Error('there are ' + count + ' warnings') return element.getText()
return count > 0
} }
async getText (locator, retries = 1) { async getValue (locator) {
try { const element = await this.waitForDisplayed(locator)
const element = await this.driver.findElement(locator) return element.getAttribute('value')
const text = element.getText()
return text
} catch (err) {
if (retries === 0) {
throw new Error(`Unable to get ${locator.toString()} text after maximum retries, error : ${err.message}`)
}
await this.driver.sleep(250)
return this.getText(locator, retries - 1)
}
} }
async getValue (locator, retries = 1) { async click (locator) {
try { const element = await this.waitForDisplayed(locator)
const element = await this.driver.findElement(locator) return element.click()
const value = element.getAttribute('value')
return value
} catch (err) {
if (retries === 0) {
throw new Error(`Unable to get ${locator.toString()} text after maximum retries, error : ${err.message}`)
}
await this.driver.sleep(250)
return this.getValue(locator, retries - 1)
}
} }
async click (locator, retries = 1) { async submit (locator) {
try { const element = await this.waitForDisplayed(locator)
const element = await this.driver.findElement(locator) return element.submit()
return element.click()
} catch (err) {
if (retries === 0) {
throw new Error(`Still not able to click ${locator.toString()} after maximum retries, Error message: ${err.message.toString()}`)
}
await this.driver.sleep(250)
return this.click(locator, retries - 1)
}
} }
async submit (locator, retries = 1) { async sendKeys (locator, keys) {
try { const element = await this.waitForDisplayed(locator)
const element = await this.driver.findElement(locator) await element.click()
return element.submit() await element.clear()
} catch (err) { return element.sendKeys(keys)
if (retries === 0) {
throw new Error(`Still not able to submit ${locator.toString()} after maximum retries, Error message: ${err.message.toString()}`)
}
await this.driver.sleep(250)
return this.submit(locator, retries - 1)
}
} }
async sendKeys (locator, keys, retries = 1) { async chooseFile (locator, file) {
try { const element = await this.waitForDisplayed(locator)
const element = await this.driver.findElement(locator) var remote = require('selenium-webdriver/remote');
await element.click() driver.setFileDetector(new remote.FileDetector);
await element.clear() return element.sendKeys(file)
return element.sendKeys(keys)
} catch (err) {
console.log(err)
if (retries === 0) {
throw new Error(`Unable to send keys to ${locator.toString()} after maximum retries, error : ${err.message}`)
}
await this.driver.sleep(250)
return this.sendKeys(locator, keys, retries - 1)
}
} }
async acceptAlert () {
async chooseFile (locator, file, retries = 1) { await this.driver.wait(until.alertIsPresent(), this.timeout);
try { await this.driver.sleep(250)
const element = await this.driver.findElement(locator) let alert = await this.driver.switchTo().alert();
var remote = require('selenium-webdriver/remote'); await this.driver.sleep(250)
driver.setFileDetector(new remote.FileDetector); return alert.accept();
return element.sendKeys(file)
} catch (err) {
console.log(err)
if (retries === 0) {
throw new Error(`Unable to send keys to ${locator.toString()} after maximum retries, error : ${err.message}`)
}
await this.driver.sleep(250)
return this.chooseFile(locator, file, retries - 1)
}
}
async acceptAlert (retries = 3) {
try {
await this.driver.wait(until.alertIsPresent());
await this.driver.sleep(250)
let alert = await this.driver.switchTo().alert();
await this.driver.sleep(250)
return alert.accept();
} catch (err) {
console.log(err)
if (retries === 0) {
throw new Error(`Unable to send keys to ${locator.toString()} after maximum retries, error : ${err.message}`)
}
await this.driver.sleep(250)
return this.alertAccept(retries - 1)
}
} }
capture () { capture () {

View File

@ -2,7 +2,7 @@ const { By, Key, until, Builder } = require('selenium-webdriver')
const BasePage = require('./BasePage') const BasePage = require('./BasePage')
const FORM = By.css('form') const FORM = By.css('form#login_form')
const FAKE_PORTAL_URL = process.env.FAKE_PORTAL_URL || 'http://localhost:3000' const FAKE_PORTAL_URL = process.env.FAKE_PORTAL_URL || 'http://localhost:3000'
module.exports = class FakePortalPage extends BasePage { module.exports = class FakePortalPage extends BasePage {

View File

@ -2,7 +2,7 @@ const { By, Key, until, Builder } = require('selenium-webdriver')
const BasePage = require('./BasePage') const BasePage = require('./BasePage')
const FORM = By.css('form') const FORM = By.css('div#login form')
const USERNAME = By.css('input[name="username"]') const USERNAME = By.css('input[name="username"]')
const PASSWORD = By.css('input[name="password"]') const PASSWORD = By.css('input[name="password"]')
const LOGIN_BUTTON = By.css('div#outer div#login form input[type=submit]') const LOGIN_BUTTON = By.css('div#outer div#login form input[type=submit]')
@ -14,7 +14,6 @@ module.exports = class LoginPage extends BasePage {
async login (username, password) { async login (username, password) {
await this.isLoaded() await this.isLoaded()
await this.sendKeys(USERNAME, username) await this.sendKeys(USERNAME, username)
await this.sendKeys(PASSWORD, password) await this.sendKeys(PASSWORD, password)
return this.submit(FORM) return this.submit(FORM)

View File

@ -22,7 +22,7 @@ const DOWNLOAD_BROKER_FILE = By.css('button#upload-definitions')
module.exports = class OverviewPage extends BasePage { module.exports = class OverviewPage extends BasePage {
async isLoaded () { async isLoaded () {
return await this.waitForDisplayed(MENU_TABS) return this.waitForDisplayed(MENU_TABS)
} }
async logout () { async logout () {

View File

@ -10,7 +10,7 @@ module.exports = class SSOHomePage extends BasePage {
return this.waitForDisplayed(LOGIN_BUTTON) return this.waitForDisplayed(LOGIN_BUTTON)
} }
async clickToLogin (username, password) { async clickToLogin () {
await this.isLoaded() await this.isLoaded()
if (!await this.isWarningVisible()) { if (!await this.isWarningVisible()) {
return this.click(LOGIN_BUTTON) return this.click(LOGIN_BUTTON)

View File

@ -13,7 +13,7 @@ module.exports = class VhostAdminTab extends AdminTab {
await this.waitForDisplayed(VHOST_NAME) await this.waitForDisplayed(VHOST_NAME)
await this.waitForDisplayed(OVERVIEW_SECTION) await this.waitForDisplayed(OVERVIEW_SECTION)
await this.waitForDisplayed(PERMISSIONS_SECTION) await this.waitForDisplayed(PERMISSIONS_SECTION)
return await this.waitForDisplayed(TOPIC_PERMISSIONS_SECTION) return this.waitForDisplayed(TOPIC_PERMISSIONS_SECTION)
} }
async getName() { async getName() {

View File

@ -19,8 +19,7 @@ module.exports = class VhostsAdminTab extends AdminTab {
await this.click(CHECKBOX_REGEX) await this.click(CHECKBOX_REGEX)
} }
await this.driver.sleep(250) await this.driver.sleep(250)
await this.waitForDisplayed(VHOSTS_TABLE_ROWS) return this.waitForDisplayed(VHOSTS_TABLE_ROWS)
return this.driver.findElement(VHOSTS_TABLE_ROWS)
} }
async hasVhosts(vhost, regex = false) { async hasVhosts(vhost, regex = false) {
return await this.searchForVhosts(vhost, regex) != undefined return await this.searchForVhosts(vhost, regex) != undefined