UNPKG

wp-e2e-webdriver

Version:

Webdriver manager and helper for WP end-to-end tests

324 lines (281 loc) 8.67 kB
/** * WebDriver helper. * * @module WebDriverManager */ /** * External dependencies */ import urljoin from 'url-join'; import webdriver from 'selenium-webdriver'; import chromedriver from 'chromedriver'; // eslint-disable-line no-unused-vars import proxy from 'selenium-webdriver/proxy'; import firefox from 'selenium-webdriver/firefox'; import chrome from 'selenium-webdriver/chrome'; import SauceLabs from 'saucelabs'; import path from 'path'; const implicitWait = 2000; const pageLoadWaitMs = 60000; const chromeUA = 'Mozilla/5.0 (wp-e2e-tests) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36'; const firefoxUA = 'Mozilla/5.0 (wp-e2e-tests) Gecko/20100101 Firefox/46.0'; const saucePreRunScriptURL = 'https://raw.githubusercontent.com/Automattic/wp-e2e-tests/master/fix-saucelabs-etc-hosts.sh'; const saucePreRunWinScriptURL = 'https://raw.githubusercontent.com/Automattic/wp-e2e-tests/master/fix-saucelabs-etc-hosts.bat'; const defaultArgs = { baseUrl: 'https://automattic.com', resizeBrowserWindow: true, useCustomUA: true, proxy: 'direct', screenshotsDir: path.resolve( process.cwd(), 'screenshots' ), headless: false, }; /** * Class representing WebDriver manager. */ export default class Manager { /** * Creates a manager. * * @param {string} browser - Browser to use. Valid value includes `chrome` * and 'firefox'. * @param {object} config - Manager configuration. */ constructor( browser = 'chrome', config = {} ) { this.browser = browser; this.config = Object.assign( defaultArgs, config ); this.setupDriver(); } /** * Returns instance of WebDriver. * * @example * * import { WebDriverManager } from 'wp-e2e-webdriver'; * * const manager = new WebDriverManager( 'chrome' ); * const driver = manager.getDriver(); * * @return {object} Instance of WebDriver. */ getDriver() { return this.driver; } setupDriver() { if ( this.config.useSauce ) { this.driver = this.buildSauceDriver(); } else { const browserName = this.browser.toLowerCase(); switch ( browserName ) { case 'chrome': this.driver = this.buildChromeDriver(); break; case 'firefox': this.driver = this.buildFirefoxDriver(); break; default: throw new Error( `The specified browser: '${ browserName }' in the config` + 'is not supported. Supported browsers are "chrome" and "firefox"' ); } this.browserName = browserName; } this.driver.manage().timeouts().implicitlyWait( implicitWait ); this.driver.manage().timeouts().pageLoadTimeout( pageLoadWaitMs ); if ( this.config.resizeBrowserWindow ) { this.resizeBrowser( this.getConfigScreenSize() ); } } buildSauceDriver() { const caps = this.config.sauceConfig; caps.username = this.config.sauceCreds.sauceUsername; caps.accessKey = this.config.sauceCreds.sauceAccessKey; caps.name = caps.browserName + ' - [' + this.getConfigScreenSize() + ']'; caps.maxDuration = 2700; // 45 minutes let preRunScript = saucePreRunScriptURL; if ( caps.platform.match( /Windows/ ) ) { preRunScript = saucePreRunWinScriptURL; } caps.prerun = { executable: preRunScript }; if ( process.env.CIRCLE_BUILD_NUM ) { caps.name += ' - CircleCI Build #' + process.env.CIRCLE_BUILD_NUM; } global._sauceLabs = new SauceLabs( { username: caps.username, password: caps.accessKey, } ); const builder = new webdriver.Builder(); this.browserName = caps.browserName; const driver = builder.usingServer( 'http://ondemand.saucelabs.com:80/wd/hub' ). withCapabilities( caps ). build(); driver.getSession().then( function( sessionid ) { driver.allPassed = true; driver.sessionID = sessionid.id_; } ); this.driver = driver; return this.driver; } buildChromeDriver() { const builder = new webdriver.Builder(); builder.setChromeOptions( this.createChromeOptions() ); return builder.forBrowser( 'chrome' ). setLoggingPrefs( this.createLoggingPreference() ). build(); } createChromeOptions() { const options = new chrome.Options(); options.setProxy( this.getProxyType() ); options.addArguments( '--no-sandbox' ); if ( process.env.HEADLESS || this.config.headless ) { options.addArguments( '--headless' ); } if ( this.config.useCustomUA ) { options.addArguments( 'user-agent=' + chromeUA ); } if ( this.config.allowRunningInsecureContent ) { options.addArguments( '--allow-running-insecure-content' ); } return options; } buildFirefoxDriver() { const builder = new webdriver.Builder(); builder.setFirefoxOptions( this.createFirefoxOptions() ); return builder.forBrowser( 'firefox' ). setLoggingPrefs( this.createLoggingPreference() ). build(); } createFirefoxProfile() { const profile = new firefox.Profile(); profile.setNativeEventsEnabled( true ); profile.setPreference( 'browser.startup.homepage_override.mstone', 'ignore' ); profile.setPreference( 'browser.startup.homepage', 'about:blank' ); profile.setPreference( 'startup.homepage_welcome_url.additional', 'about:blank' ); if ( this.config.useCustomUA ) { profile.setPreference( 'general.useragent.override', firefoxUA ); } return profile; } createFirefoxOptions() { const options = new firefox.Options().setProfile( this.createFirefoxProfile() ); options.setProxy( this.getProxyType() ); return options; } createLoggingPreference() { const pref = new webdriver.logging.Preferences(); pref.setLevel( 'browser', webdriver.logging.Level.SEVERE ); return pref; } /** * Get screen size from manager's configuration. * * @return {string} Screen size like 'desktop' or 'mobile'. */ getConfigScreenSize() { let screenSize = this.config.screenSize || process.env.BROWSERSIZE; if ( screenSize === undefined || screenSize === '' ) { screenSize = 'desktop'; } return screenSize.toLowerCase(); } /** * Get object representation of `screenSize`. * * @param {string} screenSize - Screen size like 'desktop' or 'mobile'. * * @return {object} Object representation of screen size. */ getScreenSizeAsObject( screenSize ) { switch ( screenSize ) { case 'mobile': return { width: 500, height: 1000 }; case 'tablet': return { width: 1024, height: 1000 }; case 'desktop': return { width: 1440, height: 1000 }; case 'laptop': return { width: 1400, height: 790 }; default: throw new Error( 'Unsupported screen size specified (' + screenSize + '). ' + 'Supported values are desktop, tablet and mobile.' ); } } /** * Resize the browser to `screenSize`. * * @param {string} screenSize - Screen size like 'desktop' or 'mobile'. */ resizeBrowser( screenSize ) { if ( typeof ( screenSize ) === 'string' ) { switch ( screenSize.toLowerCase() ) { case 'mobile': this.driver.manage().window().setSize( 500, 1000 ); break; case 'tablet': this.driver.manage().window().setSize( 1024, 1000 ); break; case 'desktop': this.driver.manage().window().setSize( 1440, 1000 ); break; case 'laptop': this.driver.manage().window().setSize( 1400, 790 ); break; default: throw new Error( 'Unsupported screen size specified (' + screenSize + '). ' + 'Supported values are desktop, tablet and mobile.' ); } } else { throw new Error( 'Unsupported screen size specified (' + screenSize + '). ' + 'Supported values are desktop, tablet and mobile.' ); } } /** * Quit currently running browser. * * @param {number} waitForMs - Wait time in millisecond before quit. * * @return {Promise} A promise that will be resolved once browser quitted. */ quitBrowser( waitForMs = 0 ) { const driver = this.driver; return driver.sleep( waitForMs ).then( () => { return driver.quit(); } ); } getProxyType() { const proxyType = this.config.proxy; switch ( proxyType.toLowerCase() ) { case 'direct': return proxy.direct(); case 'system': return proxy.system(); default: throw new Error( `Unknown proxy type specified of: '${ proxyType }'. Supported` + 'values are "direct" or "system"' ); } } /** * Get base URL from manager's configuration. * * @return {string} Base URL from manager's configuration. */ getBaseUrl() { return this.config.baseUrl; } /** * Get page url given a `pagePath` without the hostname. * * @param {string} pagePath - Page path. * * @return {string} Full URL. Joined base URL with `pagePath`. */ getPageUrl( pagePath = '/' ) { return urljoin( this.getBaseUrl(), pagePath ); } }