281 lines
8.5 KiB
JavaScript
281 lines
8.5 KiB
JavaScript
const fs = require('fs')
|
|
const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
|
|
const fsp = fs.promises
|
|
const path = require('path')
|
|
const { By, Key, until, Builder, logging, Capabilities } = require('selenium-webdriver')
|
|
const proxy = require('selenium-webdriver/proxy')
|
|
require('chromedriver')
|
|
var chrome = require("selenium-webdriver/chrome");
|
|
const UAALoginPage = require('./pageobjects/UAALoginPage')
|
|
const KeycloakLoginPage = require('./pageobjects/KeycloakLoginPage')
|
|
const assert = require('assert')
|
|
|
|
const runLocal = String(process.env.RUN_LOCAL).toLowerCase() != 'false'
|
|
const uaaUrl = process.env.UAA_URL || 'http://localhost:8080'
|
|
const baseUrl = randomly_pick_baseurl(process.env.RABBITMQ_URL) || 'http://localhost:15672/'
|
|
const hostname = process.env.RABBITMQ_HOSTNAME || 'localhost'
|
|
const seleniumUrl = process.env.SELENIUM_URL || 'http://selenium:4444'
|
|
const screenshotsDir = process.env.SCREENSHOTS_DIR || '/screens'
|
|
const profiles = process.env.PROFILES || ''
|
|
const debug = process.env.SELENIUM_DEBUG || false
|
|
|
|
function randomly_pick_baseurl(baseUrl) {
|
|
urls = baseUrl.split(",")
|
|
return urls[getRandomInt(urls.length)]
|
|
}
|
|
function getRandomInt(max) {
|
|
return Math.floor(Math.random() * max);
|
|
}
|
|
class CaptureScreenshot {
|
|
driver
|
|
test
|
|
constructor (webdriver, test) {
|
|
this.driver = webdriver
|
|
this.test = test
|
|
}
|
|
|
|
async shot (name) {
|
|
const image = await this.driver.takeScreenshot()
|
|
const screenshotsSubDir = path.join(screenshotsDir, this.test)
|
|
if (!fs.existsSync(screenshotsSubDir)) {
|
|
await fsp.mkdir(screenshotsSubDir)
|
|
}
|
|
const dest = path.join(screenshotsSubDir, name + '.png')
|
|
await fsp.writeFile(dest, image, 'base64')
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
log: (message) => {
|
|
if (debug) console.log(new Date() + " " + message)
|
|
},
|
|
error: (message) => {
|
|
console.error(new Date() + " " + message)
|
|
},
|
|
hasProfile: (profile) => {
|
|
return profiles.includes(profile)
|
|
},
|
|
|
|
buildDriver: (url = baseUrl) => {
|
|
builder = new Builder()
|
|
if (!runLocal) {
|
|
builder = builder.usingServer(seleniumUrl)
|
|
}
|
|
let chromeCapabilities = Capabilities.chrome();
|
|
const options = new chrome.Options()
|
|
chromeCapabilities.setAcceptInsecureCerts(true);
|
|
chromeCapabilities.set('goog:chromeOptions', {
|
|
excludeSwitches: [ // disable info bar
|
|
'enable-automation',
|
|
],
|
|
prefs: {
|
|
'profile.password_manager_enabled' : false
|
|
},
|
|
args: [
|
|
"--enable-automation",
|
|
"guest",
|
|
"disable-infobars",
|
|
"--disable-notifications",
|
|
"--lang=en",
|
|
"--disable-search-engine-choice-screen",
|
|
"disable-popup-blocking",
|
|
"--credentials_enable_service=false",
|
|
"profile.password_manager_enabled=false",
|
|
"profile.reduce-security-for-testing",
|
|
"profile.managed_default_content_settings.popups=1",
|
|
"profile.managed_default_content_settings.notifications.popups=1",
|
|
"profile.password_manager_leak_detection=false"
|
|
]
|
|
});
|
|
let driver = builder
|
|
.forBrowser('chrome')
|
|
//.setChromeOptions(options.excludeSwitches("disable-popup-blocking", "enable-automation"))
|
|
.withCapabilities(chromeCapabilities)
|
|
.build()
|
|
driver.manage().setTimeouts( { pageLoad: 35000 } )
|
|
return {
|
|
"driver": driver,
|
|
"baseUrl": url
|
|
}
|
|
},
|
|
updateDriver: (d, url) => {
|
|
return {
|
|
"driver" : d.driver,
|
|
"baseUrl" : url
|
|
}
|
|
},
|
|
getURLForProtocol: (protocol) => {
|
|
|
|
switch(protocol) {
|
|
case "amqp": return "amqp://" + hostname
|
|
default: throw new Error("Unknown prootocol " + protocol)
|
|
}
|
|
},
|
|
|
|
goToHome: (d) => {
|
|
module.exports.log("goToHome on " + d.baseUrl)
|
|
return d.driver.get(d.baseUrl)
|
|
},
|
|
|
|
goToLogin: (d, token) => {
|
|
return d.driver.get(d.baseUrl + '#/login?access_token=' + token)
|
|
},
|
|
|
|
goToExchanges: (d) => {
|
|
return d.driver.get(d.baseUrl + '#/exchanges')
|
|
},
|
|
|
|
goTo: (d, address) => {
|
|
return d.get(address)
|
|
},
|
|
|
|
delay: async (msec, ref) => {
|
|
return new Promise(resolve => {
|
|
setTimeout(resolve, msec, ref)
|
|
})
|
|
},
|
|
|
|
captureScreensFor: (d, test) => {
|
|
return new CaptureScreenshot(d.driver, require('path').basename(test))
|
|
},
|
|
|
|
doWhile: async (doCallback, booleanCallback, delayMs = 1000, message = "doWhile failed") => {
|
|
let done = false
|
|
let attempts = 10
|
|
let ret
|
|
do {
|
|
try {
|
|
module.exports.log("Calling doCallback (attempts:" + attempts + ") ... ")
|
|
ret = await doCallback()
|
|
module.exports.log("Calling booleanCallback (attempts:" + attempts
|
|
+ ") with arg " + JSON.stringify(ret) + " ... ")
|
|
done = booleanCallback(ret)
|
|
}catch(error) {
|
|
module.exports.error("Caught " + error + " on doWhile callback...")
|
|
|
|
}finally {
|
|
if (!done) {
|
|
module.exports.log("Waiting until next attempt")
|
|
await module.exports.delay(delayMs)
|
|
}
|
|
}
|
|
attempts--
|
|
} while (attempts > 0 && !done)
|
|
if (!done) {
|
|
throw new Error(message)
|
|
}else {
|
|
return ret
|
|
}
|
|
},
|
|
retry: async (doCallback, booleanCallback, delayMs = 1000, message = "retry failed") => {
|
|
let done = false
|
|
let attempts = 10
|
|
let ret
|
|
do {
|
|
try {
|
|
module.exports.log("Calling doCallback (attempts:" + attempts + ") ... ")
|
|
ret = doCallback()
|
|
module.exports.log("Calling booleanCallback (attempts:" + attempts
|
|
+ ") with arg " + JSON.stringify(ret) + " ... ")
|
|
done = booleanCallback(ret)
|
|
}catch(error) {
|
|
module.exports.error("Caught " + error + " on doWhile callback...")
|
|
|
|
}finally {
|
|
if (!done) {
|
|
module.exports.log("Waiting until next attempt")
|
|
await module.exports.delay(delayMs)
|
|
}
|
|
}
|
|
attempts--
|
|
} while (attempts > 0 && !done)
|
|
if (!done) {
|
|
throw new Error(message)
|
|
}else {
|
|
return ret
|
|
}
|
|
},
|
|
|
|
idpLoginPage: (d, preferredIdp) => {
|
|
if (!preferredIdp) {
|
|
if (process.env.PROFILES.includes("uaa")) {
|
|
preferredIdp = "uaa"
|
|
} else if (process.env.PROFILES.includes("keycloak")) {
|
|
preferredIdp = "keycloak"
|
|
} else {
|
|
throw new Error("Missing uaa or keycloak profiles")
|
|
}
|
|
}
|
|
switch(preferredIdp) {
|
|
case "uaa": return new UAALoginPage(d)
|
|
case "keycloak": return new KeycloakLoginPage(d)
|
|
default: new Error("Unsupported ipd " + preferredIdp)
|
|
}
|
|
},
|
|
openIdConfiguration: (url) => {
|
|
const req = new XMLHttpRequest()
|
|
req.open('GET', url + "/.well-known/openid-configuration", false)
|
|
req.send()
|
|
if (req.status == 200) return JSON.parse(req.responseText)
|
|
else {
|
|
module.exports.error(req.responseText)
|
|
throw new Error(req.responseText)
|
|
}
|
|
},
|
|
|
|
tokenFor: (client_id, client_secret, url = uaaUrl) => {
|
|
const req = new XMLHttpRequest()
|
|
const params = 'client_id=' + client_id +
|
|
'&client_secret=' + client_secret +
|
|
'&grant_type=client_credentials' +
|
|
'&token_format=jwt' +
|
|
'&response_type=token'
|
|
|
|
req.open('POST', url, false)
|
|
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
|
|
req.setRequestHeader('Accept', 'application/json')
|
|
req.send(params)
|
|
if (req.status == 200) return JSON.parse(req.responseText).access_token
|
|
else {
|
|
module.exports.error(req.responseText)
|
|
throw new Error(req.responseText)
|
|
}
|
|
},
|
|
|
|
assertAllOptions: (expectedOptions, actualOptions) => {
|
|
assert.equal(expectedOptions.length, actualOptions.length)
|
|
for (let i = 0; i < expectedOptions.length; i++) {
|
|
assert.ok(actualOptions.find((actualOption) =>
|
|
actualOption.value == expectedOptions[i].value
|
|
&& actualOption.text == expectedOptions[i].text))
|
|
}
|
|
},
|
|
|
|
teardown: async (d, test, captureScreen = null) => {
|
|
driver = d.driver
|
|
driver.manage().logs().get(logging.Type.BROWSER).then(function(entries) {
|
|
entries.forEach(function(entry) {
|
|
module.exports.log('[%s] %s', entry.level.name, entry.message);
|
|
})
|
|
})
|
|
if (test.currentTest) {
|
|
if (test.currentTest.isPassed()) {
|
|
driver.executeScript('lambda-status=passed')
|
|
} else {
|
|
if (captureScreen != null) await captureScreen.shot('after-failed')
|
|
driver.executeScript('lambda-status=failed')
|
|
}
|
|
}
|
|
await driver.quit()
|
|
},
|
|
|
|
findTableRow: (table, booleanCallback) => {
|
|
if (!table) return false
|
|
|
|
let i = 0
|
|
while (i < table.length && !booleanCallback(table[i])) i++;
|
|
return i < table.length ? table[i] : undefined
|
|
}
|
|
|
|
}
|