Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for selenium webdriver #1520

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions capture/backstopToolsSelenium.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
'use strict';
module.exports = (driver) => {
return driver.executeScript(() => {
if (window._backstopTools) {
return false;
}

window._backstopTools = {
hasLogged: function (str) {
return new RegExp(str).test(window._backstopTools._consoleLogger);
},
startConsoleLogger: function () {
if (typeof window._backstopTools._consoleLogger !== 'string') {
window._backstopTools._consoleLogger = '';
}
const log = window.console.log.bind(console);
window.console.log = function () {
window._backstopTools._consoleLogger += Array.from(arguments).join('\n');
log.apply(this, arguments);
};
},
/**
* Take an array of selector names and return and array of *all* matching selectors.
* For each selector name, If more than 1 selector is matched, proceeding matches are
* tagged with an additional `__n` class.
*
* @return {[string]} [array of expanded selectors]
* @param selectors
*/
expandSelectors: function (selectors) {
if (!Array.isArray(selectors)) {
selectors = selectors.split(',');
}
return selectors.reduce(function (acc, selector) {
if (selector === 'body' || selector === 'viewport') {
return acc.concat([selector]);
}
if (selector === 'document') {
return acc.concat(['document']);
}
const qResult = document.querySelectorAll(selector);

// pass-through any selectors that don't match any DOM elements
if (!qResult.length) {
return acc.concat(selector);
}

const expandedSelector = [].slice.call(qResult)
.map(function (element, expandedIndex) {
if (element.classList.contains('__86d')) {
return '';
}
if (!expandedIndex) {
// only first element is used for screenshots -- even if multiple instances exist.
// therefore index 0 does not need extended qualification.
return selector;
}
// create index partial
const indexPartial = '__n' + expandedIndex;
// update all matching selectors with additional indexPartial class
element.classList.add(indexPartial);
// return array of fully-qualified classnames
return selector + '.' + indexPartial;
});
// concat arrays of fully-qualified classnames
return acc.concat(expandedSelector);
}, []).filter(function (selector) {
return selector !== '';
});
},
/**
* is the selector element visible?
* @param {[type]} selector [a css selector str]
* @return {Boolean} [is it visible? true or false]
*/
isVisible: function (selector) {
if (selector === 'body' || selector === 'document' || selector === 'viewport') {
return true;
} else if (window._backstopTools.exists(selector)) {
const element = document.querySelector(selector);
const style = window.getComputedStyle(element);
return (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0');
}
return false;
},
/**
* does the selector element exist?
* @param {[type]} selector [a css selector str]
* @return {[type]} [returns count of found matches -- 0 for no matches]
*/
exists: function (selector) {
if (selector === 'body' || selector === 'document' || selector === 'viewport') {
return 1;
}
return document.querySelectorAll(selector).length;
}
};

window._backstopTools.startConsoleLogger();
console.info('BackstopTools have been installed.');
return true;
});
};
44 changes: 44 additions & 0 deletions capture/engine_scripts/selenium/clickAndHoverHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { until, By, Actions } = require('selenium-webdriver');

module.exports = async (driver, scenario) => {
const hoverSelector = scenario.hoverSelectors || scenario.hoverSelector;
const clickSelector = scenario.clickSelectors || scenario.clickSelector;
const keyPressSelector = scenario.keyPressSelectors || scenario.keyPressSelector;
const scrollToSelector = scenario.scrollToSelector;
const postInteractionWait = scenario.postInteractionWait; // selector [str] | ms [int]

if (keyPressSelector) {
for (const keyPressSelectorItem of [].concat(keyPressSelector)) {
await driver.wait(until.elementLocated(By.css(keyPressSelectorItem.selector)));
const element = await driver.findElement(By.css(keyPressSelectorItem.selector));
await element.sendKeys(keyPressSelectorItem.keyPress);
}
}

if (hoverSelector) {
for (const hoverSelectorIndex of [].concat(hoverSelector)) {
await driver.wait(until.elementLocated(By.css(hoverSelectorIndex)));
const hoverElement = await driver.findElement(By.css(hoverSelectorIndex));
await new Actions(driver).move({ origin: hoverElement }).perform();
}
}

if (clickSelector) {
for (const clickSelectorIndex of [].concat(clickSelector)) {
await driver.wait(until.elementLocated(By.css(clickSelectorIndex)));
const clickElement = await driver.findElement(By.css(clickSelectorIndex));
await clickElement.click();
}
}

if (postInteractionWait) {
await driver.sleep(postInteractionWait);
}

if (scrollToSelector) {
await driver.wait(until.elementLocated(By.css(scrollToSelector)));
await driver.executeScript(scrollToSelector => {
document.querySelector(scrollToSelector).scrollIntoView();
}, scrollToSelector);
}
};
34 changes: 34 additions & 0 deletions capture/engine_scripts/selenium/loadCookies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const fs = require('fs');

module.exports = async (driver, scenario) => {
let cookies = [];
const cookiePath = scenario.cookiePath;

// READ COOKIES FROM FILE IF EXISTS
if (fs.existsSync(cookiePath)) {
cookies = JSON.parse(fs.readFileSync(cookiePath));
}

// MUNGE COOKIE DOMAIN
cookies = cookies.map(cookie => {
if (cookie.domain.startsWith('http://') || cookie.domain.startsWith('https://')) {
cookie.url = cookie.domain;
} else {
cookie.url = 'https://' + cookie.domain;
}
delete cookie.domain;
return cookie;
});

// SET COOKIES
const setCookies = async () => {
return Promise.all(
cookies.map(async (cookie) => {
await driver.manage().addCookie(cookie);
})
);
};
await setCookies();
await driver.navigate().refresh();
console.log('Cookie state restored with:', JSON.stringify(cookies, null, 2));
};
3 changes: 3 additions & 0 deletions capture/engine_scripts/selenium/onBefore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = async (driver, scenario, vp) => {
await require('./loadCookies')(driver, scenario);
};
6 changes: 6 additions & 0 deletions capture/engine_scripts/selenium/onReady.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = async (driver, scenario, vp) => {
console.log('SCENARIO > ' + scenario.label);
await require('./clickAndHoverHelper')(driver, scenario);

// add more ready handlers here...
};
3 changes: 3 additions & 0 deletions core/util/createBitmaps.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const _ = require('lodash');
const pMap = require('p-map');

const runPuppet = require('./runPuppet');
const runSelenium = require('./runSelenium');
const { createPlaywrightBrowser, runPlaywright, disposePlaywrightBrowser } = require('./runPlaywright');

const ensureDirectoryPath = require('./ensureDirectoryPath');
Expand Down Expand Up @@ -147,6 +148,8 @@ function delegateScenarios (config) {
});
}, e => reject(e));
});
} else if (config.engine === 'selenium') {
return pMap(scenarioViews, runSelenium, { concurrency: asyncCaptureLimit });
} else if (/chrom./i.test(config.engine)) {
logger.error('Chromy is no longer supported in version 5+. Please use version 4.x.x for chromy support.');
} else {
Expand Down
Loading