UNPKG

@web/test-runner-chrome

Version:
106 lines (90 loc) 3.36 kB
import { Page, JSCoverageEntry } from 'puppeteer-core'; import { TestRunnerCoreConfig } from '@web/test-runner-core'; import { v8ToIstanbul } from '@web/test-runner-coverage-v8'; import { SessionResult } from '@web/test-runner-core'; declare global { interface Window { __bringTabToFront: (id: string) => void; __releaseLock: (id: string) => void; } } export class ChromeLauncherPage { private config: TestRunnerCoreConfig; private testFiles: string[]; private browser: string; public puppeteerPage: Page; private nativeInstrumentationEnabledOnPage = false; private patchAdded = false; private resolvers: Record<string, () => void> = {}; constructor( config: TestRunnerCoreConfig, testFiles: string[], product: string, puppeteerPage: Page, ) { this.config = config; this.testFiles = testFiles; this.browser = product; this.puppeteerPage = puppeteerPage; } async runSession(url: string, coverage: boolean) { if ( coverage && this.config.coverageConfig?.nativeInstrumentation !== false && this.browser === 'chromium' ) { if (this.nativeInstrumentationEnabledOnPage) { await this.puppeteerPage.coverage.stopJSCoverage(); } this.nativeInstrumentationEnabledOnPage = true; await this.puppeteerPage.coverage.startJSCoverage({ includeRawScriptCoverage: true, }); } await this.puppeteerPage.setViewport({ height: 600, width: 800 }); await this.puppeteerPage.goto(url); } async stopSession(): Promise<SessionResult> { const testCoverage = await this.collectTestCoverage(this.config, this.testFiles); // navigate to an empty page to kill any running code on the page, stopping timers and // breaking a potential endless reload loop await this.puppeteerPage.goto('about:blank'); return { testCoverage }; } private async collectTestCoverage(config: TestRunnerCoreConfig, testFiles: string[]) { const userAgentPromise = this.puppeteerPage .browser() .userAgent() .catch(() => undefined); try { const coverageFromBrowser = await this.puppeteerPage.evaluate( () => (window as any).__coverage__, ); if (coverageFromBrowser) { // coverage was generated by JS, return that return coverageFromBrowser; } } catch (error) { // evaluate throws when the test navigates in the browser } if (config.coverageConfig?.nativeInstrumentation === false) { throw new Error( 'Coverage is enabled with nativeInstrumentation disabled. ' + 'Expected coverage provided in the browser as a global __coverage__ variable.' + 'Use a plugin like babel-plugin-istanbul to generate the coverage, or enable native instrumentation.', ); } if (!this.nativeInstrumentationEnabledOnPage) { return undefined; } const [userAgent, coverageResult] = await Promise.all([ userAgentPromise, this.puppeteerPage.coverage?.stopJSCoverage(), ]); const v8Coverage = coverageResult ?.map(entry => entry.rawScriptCoverage) .filter((cov): cov is Required<JSCoverageEntry>['rawScriptCoverage'] => cov !== undefined); this.nativeInstrumentationEnabledOnPage = false; return v8ToIstanbul(config, testFiles, v8Coverage, userAgent); } }