wp-e2e-webdriver
Version:
Webdriver manager and helper for WP end-to-end tests
620 lines (564 loc) • 22.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.defaultWaitMs = undefined;
exports.waitTillPresentAndDisplayed = waitTillPresentAndDisplayed;
exports.isEventuallyPresentAndDisplayed = isEventuallyPresentAndDisplayed;
exports.waitTillNotPresent = waitTillNotPresent;
exports.clickWhenClickable = clickWhenClickable;
exports.setCheckbox = setCheckbox;
exports.unsetCheckbox = unsetCheckbox;
exports.waitForFieldClearable = waitForFieldClearable;
exports.setWhenSettable = setWhenSettable;
exports.selectOption = selectOption;
exports.clearCookiesAndDeleteLocalStorage = clearCookiesAndDeleteLocalStorage;
exports.deleteLocalStorage = deleteLocalStorage;
exports.scrollUp = scrollUp;
exports.mouseMoveTo = mouseMoveTo;
exports.scrollDown = scrollDown;
exports.writeImage = writeImage;
exports.writeText = writeText;
exports.getMediaWithFilename = getMediaWithFilename;
exports.takeScreenshot = takeScreenshot;
var _seleniumWebdriver = require('selenium-webdriver');
var _fsExtra = require('fs-extra');
var _fsExtra2 = _interopRequireDefault(_fsExtra);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _slugs = require('slugs');
var _slugs2 = _interopRequireDefault(_slugs);
var _temp = require('temp');
var _temp2 = _interopRequireDefault(_temp);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var defaultWaitMs = exports.defaultWaitMs = 10000; // 10s
/**
* WebDriver helper.
*
* @module WebDriverHelper
*/
/**
* External dependencies
*/
function returnFalse() {
return false;
}
function returnTrue() {
return true;
}
/**
* Wait for element, located by `selector`, until present and displayed. Timeout
* occurs after `waitMs` if element located by `selector` is not present and
* displayed.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( '#content' )`.
* @param {number} waitMs - How long to wait in millisecond. Defaults to 10000.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.waitTillPresentAndDisplayed( driver, By.css( '#content' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` value if element
* located `selector` is present and displayed, or rejected if
* times out waiting element to present and displayed.
*/
function waitTillPresentAndDisplayed(driver, selector) {
var waitMs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultWaitMs;
return driver.wait(function () {
return driver.findElement(selector).then(function (element) {
return element.isDisplayed().then(returnTrue, returnFalse);
}, returnFalse);
}, waitMs, 'Timed out waiting for element with ' + selector.using + ' of \'' + selector.value + '\' to be present and displayed');
}
/**
* Checks whether an element located by `selector` is eventually present and displayed.
* Timeout occurs after `waitMs` if element located by `selector` is not present and
* displayed.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( '#content' )`.
* @param {number} waitMs - How long to wait in millisecond. Defaults to 10000.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.isEventuallyPresentAndDisplayed( driver, By.css( '#content' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` value if element
* located `selector` is eventually present and displayed, or
* rejected if times out waiting the element to be present
* and displayed.
*/
function isEventuallyPresentAndDisplayed(driver, selector) {
var waitMs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultWaitMs;
return driver.wait(function () {
return driver.findElement(selector).then(function (element) {
return element.isDisplayed().then(returnTrue, returnFalse);
}, returnFalse);
}, waitMs).then(function (shown) {
return shown;
}, returnFalse);
}
/**
* Wait for element, located by `selector`, until not present. Timeout occurs
* after `waitMs` if element located by `selector` still present.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( '#content' )`.
* @param {number} waitMs - How long to wait in millisecond. Defaults to 10000.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.waitTillNotPresent( driver, By.css( '#content' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` value if element
* located `selector` is eventually not present, or rejected
* if times out waiting the element to be not present.
*/
function waitTillNotPresent(driver, selector) {
var waitMs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultWaitMs;
return driver.wait(function () {
return driver.findElement(selector).then(function (element) {
return element.isDisplayed().then(returnFalse, returnTrue);
}, returnTrue);
}, waitMs, 'Timed out waiting for element with ' + selector.using + ' of \'' + selector.value + '\' to be not present');
}
/**
* Wait for the clickable element then click it. Timeout occurs after `waitMs`
* if clickable element located by `selector` is not present.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( '#submit' )`.
* @param {number} waitMs - How long to wait in millisecond. Defaults to 10000.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.clickWhenClickable( driver, By.css( 'a.button' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` if element
* located by `selector` is successfully clicked, `false` if
* element is not clickable, or rejected if times out waiting
* clickable element to present and displayed.
*/
function clickWhenClickable(driver, selector) {
var waitMs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultWaitMs;
return driver.wait(function () {
return driver.findElement(selector).then(function (element) {
return element.click().then(returnTrue, returnFalse);
}, returnFalse);
}, waitMs, 'Timed out waiting for element with ' + selector.using + ' of \'' + selector.value + '\' to be clickable');
}
/**
* Check the checkbox element located by `selector`.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( 'input[type="checkbox"]' )`.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.setCheckbox( driver, By.css( 'input[type="checkbox"]' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` if checkbox
* element located by `selector` is checked.
*/
function setCheckbox(driver, selector) {
var _this = this;
return driver.findElement(selector).then(function (checkbox) {
return checkbox.getAttribute('checked').then(function (checked) {
if (checked !== 'true') {
return _this.clickWhenClickable(driver, selector);
}
return true;
});
});
}
/**
* Uncheck the checkbox element located by `selector`.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( 'input[type="checkbox"]' )`.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.unsetCheckbox( driver, By.css( 'input[type="checkbox"]' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` if checkbox
* element located by `selector` is unchecked.
*/
function unsetCheckbox(driver, selector) {
var _this2 = this;
return driver.findElement(selector).then(function (checkbox) {
checkbox.getAttribute('checked').then(function (checked) {
if (checked === 'true') {
return _this2.clickWhenClickable(driver, selector);
}
});
});
}
/**
* Wait for the element value is cleared. Timeout occurs after `waitMs` if
* the element located by `selector` is not present and displayed.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( 'input[name="username"]' )`.
* @param {number} waitMs - How long to wait in millisecond. Defaults to 10000.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.waitForFieldClearable( driver, By.css( 'input[name="username"]' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` if element's value,
* located by `selector`, is successfully cleared, `false` if
* element's value is not cleared, or rejected if times out waiting
* the element to present and displayed.
*/
function waitForFieldClearable(driver, selector) {
var waitMs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultWaitMs;
return driver.wait(function () {
return driver.findElement(selector).then(function (element) {
return element.clear().then(function () {
return element.getAttribute('value').then(function (value) {
return value === '';
});
}, returnFalse);
}, returnFalse);
}, waitMs, 'Timed out waiting for element with ' + selector.using + ' of \'' + selector.value + '\' to be clearable');
}
/**
* Set the element's value, located by `selector`, with `value`. Timeout occurs
* after `waitMs` if the element located by `selector` is not present and displayed.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( 'input[name="username"]' )`.
* @param {string} value - Value to set to the element.
* @param {object} options - Optional object where `secureValue` is a boolea
* indicating the element's value shouldn't be exposed
* in the log ( e.g input[type="password"] ), `waitMs`
* is time in millisecond to wait for the element
* to be settable.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.setWhenSettable( driver, By.css( 'input[name="username"]' ) )
* .then( ... );
*
* @return {Promise} A promise that will be resolved with `true` if element's value,
* located by `selector`, is successfully set, `false` if
* element's value is not set, or rejected if times out waiting
* the element to present and displayed.
*/
function setWhenSettable(driver, selector, value) {
var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
_ref$secureValue = _ref.secureValue,
secureValue = _ref$secureValue === undefined ? false : _ref$secureValue,
_ref$waitMs = _ref.waitMs,
waitMs = _ref$waitMs === undefined ? defaultWaitMs : _ref$waitMs;
var logValue = secureValue === true ? '*********' : value;
var self = this;
return driver.wait(function () {
return driver.findElement(selector).then(function (element) {
self.waitForFieldClearable(driver, selector);
return element.sendKeys(value).then(function () {
return element.getAttribute('value').then(function (actualValue) {
return actualValue === value;
});
}, returnFalse);
}, returnFalse);
}, waitMs, 'Timed out waiting for element with ' + selector.using + ' of \'' + selector.value + '\' to be settable to: \'' + logValue + '\'');
}
/**
* Select option with text `optionText` in select element lcoated by `dropdownSelector`.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} dropdownSelector - Instance of locator, mechanism for locating
* an element on the page. For example
* `By.css( 'select[name="country"]' )`.
* @param {string} optionText - Option text.
*
* @return {Promise} A promise that will be resolved to `true` if option can
* be selected, or `false` if not.
*/
function selectOption(driver, dropdownSelector, optionText) {
var dropdown = driver.findElement(dropdownSelector);
return dropdown.then(function (select) {
return select.click().then(function () {
var option = select.findElement(_seleniumWebdriver.By.xpath('.//option[contains(text(),"' + optionText + '")]'));
return option.then(function (opt) {
return opt.click().then(returnTrue, returnFalse);
}, returnFalse);
}, returnFalse);
}, returnFalse);
}
/**
* Clear cookies and delete localStorage.
*
* @param {object} driver - Instance of WebDriver.
*
* @return {boolean} Returns true once localStorage is cleared.
*/
function clearCookiesAndDeleteLocalStorage(driver) {
driver.manage().deleteAllCookies();
return this.deleteLocalStorage(driver);
}
/**
* Empty all keys out of the `localStorage`.
*
* Under the hood invoke `window.localStorage.clear()`.
*
* @param {object} driver - Instance of WebDriver.
*/
function deleteLocalStorage(driver) {
driver.getCurrentUrl().then(function (url) {
if (url.startsWith('data:') === false && url !== 'about:blank') {
return driver.executeScript('window.localStorage.clear();');
}
});
}
/**
* Scroll up once by pressing page up key.
*
* @param {object} driver - Instance of WebDriver.
* @param {number} waitMs - Sleep for `waitMs` after pressing page up.
*/
function scrollUp(driver) {
var waitMs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2000;
driver.actions().sendKeys(_seleniumWebdriver.Key.PAGE_UP).perform();
driver.sleep(waitMs);
}
/**
* Mouse move into element located by `selector`.
*
* @param {object} driver - Instance of WebDriver.
* @param {object} selector - Instance of locator, mechanism for locating an element
* on the page. For example `By.css( 'input[name="username"]' )`.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
* const selector = By.css( '#submit' );
*
* helper.mouseMoveTo( driver, selector ).then( () => {
* helper.clickWhenClickable( driver, selector );
* } );
*
* @return {Promise} A promise that will be resolved to `true` if mouse can
* be moved to the element located by `selector`, `false`
* if can not be moved.
*/
function mouseMoveTo(driver, selector) {
return driver.actions().mouseMove(driver.findElement(selector)).perform().then(function () {
return true;
}, function () {
return false;
});
}
/**
* Scroll down once by pressing page down key.
*
* @param {object} driver - Instance of WebDriver.
* @param {number} waitMs - Sleep for `waitMs` after pressing page down.
*/
function scrollDown(driver) {
var waitMs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2000;
driver.actions().sendKeys(_seleniumWebdriver.Key.PAGE_DOWN).perform();
driver.sleep(waitMs);
}
/**
* Write image `data` to `dst`.
*
* @param {string|Buffer|Uint8Array} data - Date to write.
* @param {string} dst - Path of the file where data being
* written into.
*
* @example
*
* import path from 'path';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* driver.takeScreenshot().then( data => {
* const dst = path.resolve( manager.config.screenshotsDir, 'screenshot.png' );
* helper.writeImage( data, dst );
* } );
*
* @return {undefined} Returns value from `fs.writeFileSync` which is `undefined`.
*/
function writeImage(data, dst) {
_fsExtra2.default.ensureFileSync(dst);
return _fsExtra2.default.writeFileSync(dst, data, 'base64');
}
/**
* Write text `data` to `dst`.
*
* @param {string|Buffer|Uint8Array} content - Date to write.
* @param {string} dst - Path of the file where data being
* written into.
*
* @example
*
* import path from 'path';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
* const dst = path.resolve( process.cwd(), 'browser-log.txt' );
*
* driver.manage().logs().get( 'browser' ).then( logs => {
* logs.forEach( log => {
* helper.writeText( log.message, dst );
* } );
* } );
*
* @return {undefined} Returns value from `fs.writeFileSync` which is `undefined`.
*/
function writeText(content, dst) {
_fsExtra2.default.ensureFileSync(dst);
return _fsExtra2.default.writeFileSync(dst, content);
}
/**
* Get path of example media where filename is `filename` and media type is `type`.
*
* This function can be used for testing file upload of various where various
* media types is allowed to be uploaded. Under the hood it copies pre-defined
* media in this package into `filename` and returns the file details.
*
* @param {string} filename - Full path of filename where new media is going
* to be created.
* @param {string} type - Media type.
*
* @example
*
* import { By } from 'selenium-webdriver';
* import path from 'path';
* import { WebDriverManager, WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* const manager = new WebDriverManager( 'chrome' );
* const driver = manager.getDriver();
*
* helper.getMediaWithFilename( 'test-upload-image.jpg', 'jpg' ).then( data => {
* driver.findElement( By.css( 'input[type="file"]' ) ).sendKeys( data.file );
* helper.clickWhenClickable( driver, By.css( '#submit' ) );
* } );
*
* @returns {Promise} Promise of file details.
*/
function getMediaWithFilename(filename) {
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'jpg';
var src = _path2.default.resolve(__dirname, '../media/media.' + type);
if (!_fsExtra2.default.existsSync(src)) {
throw new Error('Source media ' + src + ' does not exist');
}
var dst = _path2.default.resolve(_temp2.default.mkdirSync('media'), filename);
var d = _seleniumWebdriver.promise.defer();
_fsExtra2.default.copySync(src, dst);
d.fulfill({
imageName: filename,
fileName: filename,
file: dst
});
return d.promise;
}
/**
* Take a screenshot from `currentTest`.
*
* The best place to use this is in `test.afterEach` hook where all tests
* are captured.
*
* @param {object} manager - Instance of `WebDriverManager`.
* @param {object} currentTest - Current test.
*
* @example
*
* import test from 'selenium-webdriver/testing';
* import { WebDriverHelper as helper } from 'wp-e2e-webdriver';
*
* test.afterEach( 'Take screenshot', function() {
* return helper.takeScreenshot( global.__MANAGER__, this.currentTest );
* } );
*
* @return {Promise} A promise that will be resolved with `undefined` once
* screenshot is written to `manager.config.screenshotsDir`.
*/
function takeScreenshot(manager, currentTest) {
if (!currentTest) {
return;
}
var driver = manager.getDriver();
var title = (0, _slugs2.default)(currentTest.title);
var state = currentTest.state;
var screenSize = manager.getConfigScreenSize();
var filename = state + '-' + screenSize + '-' + title + '.png';
return driver.takeScreenshot().then(function (data) {
var dst = _path2.default.resolve(manager.config.screenshotsDir, filename);
return writeImage(data, dst);
});
}