UNPKG

@wdio/devtools-service

Version:

A WebdriverIO service that allows you to run Chrome DevTools commands in your tests

159 lines (158 loc) 6.47 kB
import CommandHandler from './commands.js'; import { setUnsupportedCommand, getLighthouseDriver } from './utils.js'; import { DEFAULT_THROTTLE_STATE, NETWORK_STATES } from './constants.js'; export default class DevToolsService { _options; _command = []; _browser; constructor(_options) { this._options = _options; } async before(caps, specs, browser) { this._browser = browser; return await this._setupHandler(); } async onReload() { if (!this._browser) { return; } return this._setupHandler(); } async beforeCommand(commandName, params) { return Promise.all(this._command.map(async (c) => await c._beforeCmd(commandName, params))); } async afterCommand(commandName) { if (commandName === 'switchToWindow') { await this._setupHandler(); } return Promise.all(this._command.map(async (c) => await c._afterCmd(commandName))); } async after() { for (const c of this._command) { await c._logCoverage(); } } /** * set flag to run performance audits for page transitions */ _enablePerformanceAudits({ networkThrottling, cpuThrottling, cacheEnabled, formFactor } = DEFAULT_THROTTLE_STATE) { if (!NETWORK_STATES[networkThrottling]) { throw new Error(`Network throttling profile "${networkThrottling}" is unknown, choose between ${Object.keys(NETWORK_STATES).join(', ')}`); } if (typeof cpuThrottling !== 'number') { throw new Error(`CPU throttling rate needs to be typeof number but was "${typeof cpuThrottling}"`); } if (this._command.length === 1) { this._command[0].enablePerformanceAudits({ networkThrottling, cpuThrottling, cacheEnabled, formFactor }); } else { for (const c of this._command) { c.enablePerformanceAudits({ networkThrottling, cpuThrottling, cacheEnabled, formFactor }); } } } /** * custom command to disable performance audits */ _disablePerformanceAudits() { if (this._command.length === 1) { this._command[0].disablePerformanceAudits(); } else { for (const c of this._command) { c.disablePerformanceAudits(); } } } /** * set device emulation */ async _emulateDevice(device, deviceOptions) { if (this._command.length === 1) { return await this._command[0].emulateDevice(device, deviceOptions); } return Promise.all(this._command.map(async (c) => await c.emulateDevice(device, deviceOptions))); } async _setThrottlingProfile(networkThrottling = DEFAULT_THROTTLE_STATE.networkThrottling, cpuThrottling = DEFAULT_THROTTLE_STATE.cpuThrottling, cacheEnabled = DEFAULT_THROTTLE_STATE.cacheEnabled) { if (this._command.length === 1) { this._command[0].setThrottlingProfile(networkThrottling, cpuThrottling, cacheEnabled); } else { for (const c of this._command) { c.setThrottlingProfile(networkThrottling, cpuThrottling, cacheEnabled); } } } async _checkPWA(auditsToBeRun) { if (this._command.length === 1) { return await this._command[0].checkPWA(auditsToBeRun); } return Promise.all(this._command.map(async (c) => await c.checkPWA(auditsToBeRun))); } async _getCoverageReport() { if (this._command.length === 1) { return this._command[0].getCoverageReport(); } return await Promise.all(this._command.map(c => c.getCoverageReport())); } _cdp(domain, command, args = {}) { if (this._command.length === 1) { return this._command[0].cdp(domain, command, args); } return Promise.all(this._command.map(async (c) => await c.cdp(domain, command, args))); } async _setupHandler() { if (!this._browser) { return; } /** * In case of switchToWindow, needs to not add more commands to the array */ this._command.length = 0; /** * To avoid if-else, gather all browser instances into an array */ const browsers = Object.keys(this._browser).includes('sessionId') ? [this._browser] : this._browser.instances.map(i => this._browser.getInstance(i)); for (const browser of browsers) { const puppeteer = await browser.getPuppeteer().catch(() => undefined); if (!puppeteer) { return setUnsupportedCommand(browser); } /* istanbul ignore next */ if (!puppeteer) { throw new Error('Could not initiate Puppeteer instance'); } const url = await browser.getUrl(); const target = url !== 'data:,' ? await puppeteer.waitForTarget( /* istanbul ignore next */ (t) => t.url().includes(url)) : await puppeteer.waitForTarget( /* istanbul ignore next */ (t) => t.type() === 'page' || Boolean(t.browserContext().id)); /* istanbul ignore next */ if (!target) { throw new Error('No page target found'); } const page = await target.page() || null; /* istanbul ignore next */ if (!page) { throw new Error('No page found'); } const session = await target.createCDPSession(); const driver = await getLighthouseDriver(session, target); const cmd = new CommandHandler(session, page, driver, this._options, browser); await cmd._initCommand(); this._command.push(cmd); } this._browser.addCommand('enablePerformanceAudits', this._enablePerformanceAudits.bind(this)); this._browser.addCommand('disablePerformanceAudits', this._disablePerformanceAudits.bind(this)); this._browser.addCommand('emulateDevice', this._emulateDevice.bind(this)); this._browser.addCommand('checkPWA', this._checkPWA.bind(this)); this._browser.addCommand('getCoverageReport', this._getCoverageReport.bind(this)); this._browser.addCommand('cdp', this._cdp.bind(this)); } } export * from './types.js';