2018-07-05 14:16:36 -04:00
|
|
|
const webdriver = require('selenium-webdriver');
|
2018-06-27 10:11:12 -04:00
|
|
|
const bindAll = require('lodash.bindall');
|
2018-11-27 11:36:16 -05:00
|
|
|
require('chromedriver');
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-05-31 11:52:57 -04:00
|
|
|
const headless = process.env.SMOKE_HEADLESS || false;
|
2018-06-25 15:17:15 -04:00
|
|
|
const remote = process.env.SMOKE_REMOTE || false;
|
2018-07-11 14:50:04 -04:00
|
|
|
const ci = process.env.CI || false;
|
2018-07-11 13:21:57 -04:00
|
|
|
const buildID = process.env.TRAVIS_BUILD_NUMBER;
|
2018-06-25 15:17:15 -04:00
|
|
|
const {SAUCE_USERNAME, SAUCE_ACCESS_KEY} = process.env;
|
2019-05-13 15:02:56 -04:00
|
|
|
const {By, Key, until} = webdriver;
|
2020-09-14 15:25:01 -04:00
|
|
|
const pkg = require('../../package.json');
|
2018-05-31 11:52:57 -04:00
|
|
|
|
2019-06-03 16:23:01 -04:00
|
|
|
const DEFAULT_TIMEOUT_MILLISECONDS = 20 * 1000;
|
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
class SeleniumHelper {
|
|
|
|
constructor () {
|
|
|
|
bindAll(this, [
|
|
|
|
'buildDriver',
|
2019-05-20 17:16:34 -04:00
|
|
|
'clickButton',
|
|
|
|
'clickCss',
|
|
|
|
'clickText',
|
2018-06-27 10:11:12 -04:00
|
|
|
'clickXpath',
|
2019-05-20 17:16:34 -04:00
|
|
|
'dragFromXpathToXpath',
|
|
|
|
'findByCss',
|
2018-06-27 10:11:12 -04:00
|
|
|
'findByXpath',
|
|
|
|
'findText',
|
2019-05-20 17:16:34 -04:00
|
|
|
'getKey',
|
|
|
|
'getDriver',
|
|
|
|
'getLogs',
|
|
|
|
'getSauceDriver',
|
2019-06-03 16:24:56 -04:00
|
|
|
'urlMatches',
|
|
|
|
'waitUntilGone'
|
2018-06-27 10:11:12 -04:00
|
|
|
]);
|
|
|
|
}
|
|
|
|
buildDriver (name) {
|
|
|
|
if (remote === 'true'){
|
2018-07-11 11:17:49 -04:00
|
|
|
let nameToUse;
|
2018-07-11 14:50:04 -04:00
|
|
|
if (ci === 'true'){
|
2018-07-11 12:07:28 -04:00
|
|
|
nameToUse = 'travis ' + buildID + ' : ' + name;
|
2018-07-11 11:17:49 -04:00
|
|
|
} else {
|
|
|
|
nameToUse = name;
|
|
|
|
}
|
|
|
|
this.driver = this.getSauceDriver(SAUCE_USERNAME, SAUCE_ACCESS_KEY, nameToUse);
|
2018-06-27 10:11:12 -04:00
|
|
|
} else {
|
|
|
|
this.driver = this.getDriver();
|
|
|
|
}
|
|
|
|
return this.driver;
|
2018-05-31 11:52:57 -04:00
|
|
|
}
|
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
getDriver () {
|
|
|
|
const chromeCapabilities = webdriver.Capabilities.chrome();
|
|
|
|
let args = [];
|
|
|
|
if (headless) {
|
|
|
|
args.push('--headless');
|
|
|
|
args.push('window-size=1024,1680');
|
|
|
|
args.push('--no-sandbox');
|
|
|
|
}
|
|
|
|
chromeCapabilities.set('chromeOptions', {args});
|
|
|
|
let driver = new webdriver.Builder()
|
|
|
|
.forBrowser('chrome')
|
|
|
|
.withCapabilities(chromeCapabilities)
|
|
|
|
.build();
|
|
|
|
return driver;
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2020-09-14 15:25:01 -04:00
|
|
|
getChromeVersionNumber () {
|
|
|
|
let chromedriverVersion = pkg.devDependencies.chromedriver;
|
|
|
|
let versionFinder = /\d+\.\d+/;
|
|
|
|
let versionArray = versionFinder.exec(chromedriverVersion);
|
|
|
|
return versionArray[0];
|
|
|
|
}
|
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
getSauceDriver (username, accessKey, name) {
|
2020-09-14 15:25:01 -04:00
|
|
|
let chromeVersion = this.getChromeVersionNumber();
|
2018-06-27 10:11:12 -04:00
|
|
|
// Driver configs can be generated with the Sauce Platform Configurator
|
|
|
|
// https://wiki.saucelabs.com/display/DOCS/Platform+Configurator
|
|
|
|
let driverConfig = {
|
|
|
|
browserName: 'chrome',
|
2019-08-05 13:34:30 -04:00
|
|
|
platform: 'macOS 10.14',
|
2020-09-14 15:25:01 -04:00
|
|
|
version: chromeVersion
|
2018-06-27 10:11:12 -04:00
|
|
|
};
|
|
|
|
var driver = new webdriver.Builder()
|
|
|
|
.withCapabilities({
|
|
|
|
browserName: driverConfig.browserName,
|
|
|
|
platform: driverConfig.platform,
|
|
|
|
version: driverConfig.version,
|
|
|
|
username: username,
|
|
|
|
accessKey: accessKey,
|
|
|
|
name: name
|
|
|
|
})
|
|
|
|
.usingServer(`http://${username}:${accessKey
|
|
|
|
}@ondemand.saucelabs.com:80/wd/hub`)
|
|
|
|
.build();
|
|
|
|
return driver;
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2019-05-13 15:02:56 -04:00
|
|
|
getKey (keyName) {
|
|
|
|
return Key[keyName];
|
|
|
|
}
|
|
|
|
|
2019-06-03 16:23:01 -04:00
|
|
|
findByXpath (xpath, timeoutMessage = `findByXpath timed out for path: ${xpath}`) {
|
|
|
|
return this.driver.wait(until.elementLocated(By.xpath(xpath)), DEFAULT_TIMEOUT_MILLISECONDS, timeoutMessage)
|
|
|
|
.then(el => (
|
|
|
|
this.driver.wait(el.isDisplayed(), DEFAULT_TIMEOUT_MILLISECONDS, `${xpath} is not visible`)
|
|
|
|
.then(() => el)
|
|
|
|
));
|
|
|
|
}
|
2019-06-03 16:24:56 -04:00
|
|
|
|
2019-06-03 17:12:59 -04:00
|
|
|
waitUntilGone (element) {
|
2019-06-03 16:24:56 -04:00
|
|
|
return this.driver.wait(until.stalenessOf(element));
|
2018-06-27 10:11:12 -04:00
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
clickXpath (xpath) {
|
|
|
|
return this.findByXpath(xpath).then(el => el.click());
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
clickText (text) {
|
|
|
|
return this.clickXpath(`//*[contains(text(), '${text}')]`);
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
findText (text) {
|
|
|
|
return this.driver.wait(until.elementLocated(By.xpath(`//*[contains(text(), '${text}')]`), 5 * 1000));
|
|
|
|
}
|
2017-10-23 21:17:55 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
clickButton (text) {
|
|
|
|
return this.clickXpath(`//button[contains(text(), '${text}')]`);
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
findByCss (css) {
|
|
|
|
return this.driver.wait(until.elementLocated(By.css(css), 1000 * 5));
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
clickCss (css) {
|
|
|
|
return this.findByCss(css).then(el => el.click());
|
|
|
|
}
|
2018-05-17 11:33:21 -04:00
|
|
|
|
2019-05-20 17:16:34 -04:00
|
|
|
dragFromXpathToXpath (startXpath, endXpath) {
|
|
|
|
return this.findByXpath(startXpath).then(startEl => {
|
|
|
|
return this.findByXpath(endXpath).then(endEl => {
|
|
|
|
return this.driver.actions()
|
|
|
|
.dragAndDrop(startEl, endEl)
|
|
|
|
.perform();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-05-13 15:02:56 -04:00
|
|
|
urlMatches (regex) {
|
|
|
|
return this.driver.wait(until.urlMatches(regex), 1000 * 5);
|
|
|
|
}
|
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
getLogs (whitelist) {
|
|
|
|
return this.driver.manage()
|
|
|
|
.logs()
|
|
|
|
.get('browser')
|
|
|
|
.then((entries) => {
|
|
|
|
return entries.filter((entry) => {
|
|
|
|
const message = entry.message;
|
|
|
|
for (let i = 0; i < whitelist.length; i++) {
|
|
|
|
if (message.indexOf(whitelist[i]) !== -1) {
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
// console.warn('Ignoring whitelisted error: ' + whitelist[i]);
|
|
|
|
return false;
|
|
|
|
} else if (entry.level !== 'SEVERE') {
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
// console.warn('Ignoring non-SEVERE entry: ' + message);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2017-08-11 16:13:52 -04:00
|
|
|
}
|
|
|
|
return true;
|
2018-06-27 10:11:12 -04:00
|
|
|
});
|
2017-08-11 16:13:52 -04:00
|
|
|
});
|
2018-06-27 10:11:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-08-11 16:13:52 -04:00
|
|
|
|
2018-06-27 10:11:12 -04:00
|
|
|
module.exports = SeleniumHelper;
|