From 481b26f35d7dae5d6abf24a616e67df2ba4e45b8 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 21 Apr 2021 19:43:55 -0700 Subject: [PATCH] test: roll to folio@0.4.0-alpha3 --- package-lock.json | 24 +- package.json | 2 +- tests/android/browser.spec.ts | 2 +- tests/android/device.spec.ts | 4 +- tests/android/webview.spec.ts | 2 +- tests/beforeunload.spec.ts | 2 +- tests/browser.spec.ts | 2 +- tests/browsercontext-add-cookies.spec.ts | 5 +- tests/browsercontext-add-init-script.spec.ts | 2 +- tests/browsercontext-basic.spec.ts | 2 +- tests/browsercontext-clearcookies.spec.ts | 2 +- tests/browsercontext-cookies.spec.ts | 2 +- tests/browsercontext-credentials.spec.ts | 2 +- tests/browsercontext-csp.spec.ts | 2 +- tests/browsercontext-device.spec.ts | 2 +- tests/browsercontext-dsf.spec.ts | 2 +- tests/browsercontext-expose-function.spec.ts | 2 +- tests/browsercontext-locale.spec.ts | 2 +- tests/browsercontext-page-event.spec.ts | 2 +- tests/browsercontext-proxy.spec.ts | 2 +- tests/browsercontext-route.spec.ts | 2 +- ...wsercontext-set-extra-http-headers.spec.ts | 2 +- tests/browsercontext-storage-state.spec.ts | 2 +- tests/browsercontext-timezone-id.spec.ts | 2 +- tests/browsercontext-user-agent.spec.ts | 2 +- tests/browsercontext-viewport-mobile.spec.ts | 2 +- tests/browsercontext-viewport.spec.ts | 2 +- tests/browsertype-basic.spec.ts | 2 +- tests/browsertype-connect.spec.ts | 2 +- tests/browsertype-launch-server.spec.ts | 4 +- tests/browsertype-launch.spec.ts | 2 +- tests/capabilities.spec.ts | 2 +- tests/channels.spec.ts | 2 +- tests/chromium/chromium.spec.ts | 2 +- tests/chromium/launcher.spec.ts | 2 +- tests/chromium/oopif.spec.ts | 2 +- tests/chromium/session.spec.ts | 4 +- tests/chromium/tracing.spec.ts | 2 +- tests/cli/cli-codegen-1.spec.ts | 2 +- tests/cli/cli-codegen-2.spec.ts | 2 +- tests/cli/cli-codegen-csharp.spec.ts | 2 +- tests/cli/cli-codegen-java.spec.ts | 2 +- tests/cli/cli-codegen-javascript.spec.ts | 2 +- tests/cli/cli-codegen-python-async.spec.ts | 2 +- tests/cli/cli-codegen-python.spec.ts | 2 +- tests/config/android.config.ts | 39 ++- tests/config/androidEnv.ts | 103 ------ tests/config/androidTest.ts | 42 ++- tests/config/baseTest.ts | 295 ++++++++++++++++++ tests/config/browserEnv.ts | 286 ----------------- tests/config/browserTest.ts | 198 +++++++++++- tests/config/cliEnv.ts | 83 ----- tests/config/cliTest.ts | 69 +++- tests/config/contextTest.ts | 28 -- tests/config/coverage.js | 29 -- tests/config/default.config.ts | 84 +++-- tests/config/electron.config.ts | 32 +- tests/config/electronEnv.ts | 93 ------ tests/config/electronTest.ts | 62 +++- tests/config/pageTest.ts | 28 +- tests/config/playwrightTest.ts | 33 -- tests/config/serverEnv.ts | 85 ----- tests/config/serverTest.ts | 24 -- tests/css-parser.spec.ts | 2 +- tests/defaultbrowsercontext-1.spec.ts | 2 +- tests/defaultbrowsercontext-2.spec.ts | 6 +- tests/download.spec.ts | 2 +- tests/downloads-path.spec.ts | 2 +- tests/electron/electron-app.spec.ts | 2 +- tests/electron/electron-window.spec.ts | 2 +- tests/elementhandle-bounding-box.spec.ts | 2 +- tests/elementhandle-screenshot.spec.ts | 2 +- tests/emulation-focus.spec.ts | 2 +- tests/favicon.spec.ts | 2 +- tests/firefox/launcher.spec.ts | 2 +- tests/frame-hierarchy.spec.ts | 2 +- tests/geolocation.spec.ts | 2 +- tests/har.spec.ts | 2 +- tests/headful.spec.ts | 2 +- tests/ignorehttpserrors.spec.ts | 2 +- tests/interception.spec.ts | 8 +- tests/launcher.spec.ts | 2 +- tests/logger.spec.ts | 2 +- tests/page-emulate-media.spec.ts | 2 +- tests/page-event-crash.spec.ts | 4 +- tests/page-goto.spec.ts | 2 +- tests/page-in-context.spec.ts | 2 +- tests/page-mouse.spec.ts | 2 +- tests/page-request-fulfill.spec.ts | 2 +- tests/page-screenshot.spec.ts | 2 +- tests/pause.spec.ts | 2 +- tests/pdf.spec.ts | 2 +- tests/permissions.spec.ts | 2 +- tests/popup.spec.ts | 2 +- tests/proxy.spec.ts | 2 +- tests/resource-timing.spec.ts | 2 +- tests/screencast.spec.ts | 2 +- tests/selector-generator.spec.ts | 2 +- tests/selectors-register.spec.ts | 2 +- tests/signals.spec.ts | 2 +- tests/snapshotter.spec.ts | 2 +- tests/stack-trace.spec.ts | 2 +- tests/tap.spec.ts | 2 +- tests/workers.spec.ts | 2 +- 104 files changed, 863 insertions(+), 965 deletions(-) delete mode 100644 tests/config/androidEnv.ts create mode 100644 tests/config/baseTest.ts delete mode 100644 tests/config/browserEnv.ts delete mode 100644 tests/config/cliEnv.ts delete mode 100644 tests/config/contextTest.ts delete mode 100644 tests/config/electronEnv.ts delete mode 100644 tests/config/playwrightTest.ts delete mode 100644 tests/config/serverEnv.ts delete mode 100644 tests/config/serverTest.ts diff --git a/package-lock.json b/package-lock.json index 2c15b09dddc236..fb0e4288bc05e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8140,9 +8140,9 @@ } }, "folio": { - "version": "0.3.21-alpha", - "resolved": "https://registry.npmjs.org/folio/-/folio-0.3.21-alpha.tgz", - "integrity": "sha512-gCP36QBOAfVWOWydY2vJi32mV+7mUYr+o0c+Jw25edAfZCZndkztIMpvB9dXAKct1g5f7wY5n1bTBH0ZunMWXg==", + "version": "0.4.0-alpha4", + "resolved": "https://registry.npmjs.org/folio/-/folio-0.4.0-alpha4.tgz", + "integrity": "sha512-/M8DQEPg2H6HuBgcCN8A5xa/s7wS5Dsu9F0jUHXv6dft+qvgMQY9TWi998EWZ7jn7SxakBnpLRUPbrLFiyIK0g==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", @@ -10034,9 +10034,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10125,9 +10125,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -10193,9 +10193,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", diff --git a/package.json b/package.json index ae635d25ab311f..fa135481a1184d 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "eslint-plugin-notice": "^0.9.10", "eslint-plugin-react-hooks": "^4.2.0", "file-loader": "^6.1.0", - "folio": "=0.3.21-alpha", + "folio": "=0.4.0-alpha4", "formidable": "^1.2.2", "html-webpack-plugin": "^4.4.1", "ncp": "^2.0.0", diff --git a/tests/android/browser.spec.ts b/tests/android/browser.spec.ts index 855dc0bec1412a..5e2f5854d1fd9f 100644 --- a/tests/android/browser.spec.ts +++ b/tests/android/browser.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect } from '../config/androidTest'; +import { androidTest as test, expect } from '../config/androidTest'; test('androidDevice.model', async function({ androidDevice }) { expect(androidDevice.model()).toBe('sdk_gphone_x86_arm'); diff --git a/tests/android/device.spec.ts b/tests/android/device.spec.ts index 7e9752df036e4e..62e597752796e4 100644 --- a/tests/android/device.spec.ts +++ b/tests/android/device.spec.ts @@ -16,7 +16,7 @@ import fs from 'fs'; import { PNG } from 'pngjs'; -import { test, expect } from '../config/androidTest'; +import { androidTest as test, expect } from '../config/androidTest'; test('androidDevice.shell', async function({ androidDevice }) { const output = await androidDevice.shell('echo 123'); @@ -28,7 +28,7 @@ test('androidDevice.open', async function({ androidDevice }) { await socket.write(Buffer.from('321\n')); const output = await new Promise(resolve => socket.on('data', resolve)); expect(output.toString()).toBe('321\n'); - const closedPromise = new Promise(resolve => socket.on('close', resolve)); + const closedPromise = new Promise(resolve => socket.on('close', resolve)); await socket.close(); await closedPromise; }); diff --git a/tests/android/webview.spec.ts b/tests/android/webview.spec.ts index 0c651bef89cd71..e56eac34e7d930 100644 --- a/tests/android/webview.spec.ts +++ b/tests/android/webview.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect } from '../config/androidTest'; +import { androidTest as test, expect } from '../config/androidTest'; test('androidDevice.webView', async function({ androidDevice }) { expect(androidDevice.webViews().length).toBe(0); diff --git a/tests/beforeunload.spec.ts b/tests/beforeunload.spec.ts index f66247001adc45..b303e33b7bfc1b 100644 --- a/tests/beforeunload.spec.ts +++ b/tests/beforeunload.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; it('should close browser with beforeunload page', async ({server, browserType, browserOptions }) => { const browser = await browserType.launch(browserOptions); diff --git a/tests/browser.spec.ts b/tests/browser.spec.ts index 7a4ae2e2e694f4..1b48d9710cb41c 100644 --- a/tests/browser.spec.ts +++ b/tests/browser.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect } from './config/browserTest'; +import { browserTest as test, expect } from './config/browserTest'; test('should create new page', async function({browser}) { const page1 = await browser.newPage(); diff --git a/tests/browsercontext-add-cookies.spec.ts b/tests/browsercontext-add-cookies.spec.ts index 6d940ac5ad897f..7048e7520e2e30 100644 --- a/tests/browsercontext-add-cookies.spec.ts +++ b/tests/browsercontext-add-cookies.spec.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; -import { slowTest as playwrightTest } from './config/playwrightTest'; +import { contextTest as it, slowPlaywrightTest, expect } from './config/browserTest'; it('should work', async ({context, page, server}) => { await page.goto(server.EMPTY_PAGE); @@ -158,7 +157,7 @@ it('should isolate send cookie header', async ({server, context, browser}) => { } }); -playwrightTest('should isolate cookies between launches', async ({browserType, server, browserOptions}) => { +slowPlaywrightTest('should isolate cookies between launches', async ({browserType, server, browserOptions}) => { const browser1 = await browserType.launch(browserOptions); const context1 = await browser1.newContext(); await context1.addCookies([{url: server.EMPTY_PAGE, name: 'cookie-in-context-1', value: 'value', expires: Date.now() / 1000 + 10000}]); diff --git a/tests/browsercontext-add-init-script.spec.ts b/tests/browsercontext-add-init-script.spec.ts index e8cea134c81288..86c5705ddc4b54 100644 --- a/tests/browsercontext-add-init-script.spec.ts +++ b/tests/browsercontext-add-init-script.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; it('should work with browser context scripts', async ({ context, server }) => { await context.addInitScript(() => window['temp'] = 123); diff --git a/tests/browsercontext-basic.spec.ts b/tests/browsercontext-basic.spec.ts index 20551af0d2a2d2..81daecb6cda31b 100644 --- a/tests/browsercontext-basic.spec.ts +++ b/tests/browsercontext-basic.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import { verifyViewport } from './config/utils'; it('should create new context', async function({browser}) { diff --git a/tests/browsercontext-clearcookies.spec.ts b/tests/browsercontext-clearcookies.spec.ts index ec172824bff4d2..78427795c6d287 100644 --- a/tests/browsercontext-clearcookies.spec.ts +++ b/tests/browsercontext-clearcookies.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; it('should clear cookies', async ({context, page, server}) => { await page.goto(server.EMPTY_PAGE); diff --git a/tests/browsercontext-cookies.spec.ts b/tests/browsercontext-cookies.spec.ts index 03011988588fba..c2443e4e30adc4 100644 --- a/tests/browsercontext-cookies.spec.ts +++ b/tests/browsercontext-cookies.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; it('should return no cookies in pristine browser context', async ({context, page, server}) => { expect(await context.cookies()).toEqual([]); diff --git a/tests/browsercontext-credentials.spec.ts b/tests/browsercontext-credentials.spec.ts index 2d2b3a76d2e723..43583f33bf650e 100644 --- a/tests/browsercontext-credentials.spec.ts +++ b/tests/browsercontext-credentials.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should fail without credentials', async ({browser, server, browserName, headful}) => { it.fail(browserName === 'chromium' && headful); diff --git a/tests/browsercontext-csp.spec.ts b/tests/browsercontext-csp.spec.ts index 6f7b474c8ff3d2..1118637137b49d 100644 --- a/tests/browsercontext-csp.spec.ts +++ b/tests/browsercontext-csp.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import { attachFrame } from './config/utils'; it('should bypass CSP meta tag', async ({browser, server}) => { diff --git a/tests/browsercontext-device.spec.ts b/tests/browsercontext-device.spec.ts index 3608445ae50da1..ef7fcc59387830 100644 --- a/tests/browsercontext-device.spec.ts +++ b/tests/browsercontext-device.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it.describe('device', () => { it.beforeEach(async ({browserName}) => { diff --git a/tests/browsercontext-dsf.spec.ts b/tests/browsercontext-dsf.spec.ts index 7deeb97ff68c53..2e123b71ac532c 100644 --- a/tests/browsercontext-dsf.spec.ts +++ b/tests/browsercontext-dsf.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should fetch lodpi assets', async ({ contextFactory, server}) => { const context = await contextFactory({ diff --git a/tests/browsercontext-expose-function.spec.ts b/tests/browsercontext-expose-function.spec.ts index 0c10c278d73814..0823a2fb9fc23f 100644 --- a/tests/browsercontext-expose-function.spec.ts +++ b/tests/browsercontext-expose-function.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; it('expose binding should work', async ({context}) => { let bindingSource; diff --git a/tests/browsercontext-locale.spec.ts b/tests/browsercontext-locale.spec.ts index 5b1c3465c00094..c349ceb7591621 100644 --- a/tests/browsercontext-locale.spec.ts +++ b/tests/browsercontext-locale.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should affect accept-language header', async ({browser, server}) => { const context = await browser.newContext({ locale: 'fr-CH' }); diff --git a/tests/browsercontext-page-event.spec.ts b/tests/browsercontext-page-event.spec.ts index 21666175a7abaf..9876d1d7dcce95 100644 --- a/tests/browsercontext-page-event.spec.ts +++ b/tests/browsercontext-page-event.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should have url', async ({browser, server}) => { const context = await browser.newContext(); diff --git a/tests/browsercontext-proxy.spec.ts b/tests/browsercontext-proxy.spec.ts index a7319f4e0c8f5d..8db7198de3698e 100644 --- a/tests/browsercontext-proxy.spec.ts +++ b/tests/browsercontext-proxy.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import type { Browser } from '../index'; let browser: Browser; diff --git a/tests/browsercontext-route.spec.ts b/tests/browsercontext-route.spec.ts index 65bedaba6741c3..0fd1fa900f79d1 100644 --- a/tests/browsercontext-route.spec.ts +++ b/tests/browsercontext-route.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should intercept', async ({browser, server}) => { const context = await browser.newContext(); diff --git a/tests/browsercontext-set-extra-http-headers.spec.ts b/tests/browsercontext-set-extra-http-headers.spec.ts index f486508f9c09c5..c63bebec318e94 100644 --- a/tests/browsercontext-set-extra-http-headers.spec.ts +++ b/tests/browsercontext-set-extra-http-headers.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should override extra headers from browser context', async ({browser, server}) => { const context = await browser.newContext({ diff --git a/tests/browsercontext-storage-state.spec.ts b/tests/browsercontext-storage-state.spec.ts index 2d6fef9416aa5d..4c0e76e3fb5d32 100644 --- a/tests/browsercontext-storage-state.spec.ts +++ b/tests/browsercontext-storage-state.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import fs from 'fs'; it('should capture local storage', async ({ contextFactory }) => { diff --git a/tests/browsercontext-timezone-id.spec.ts b/tests/browsercontext-timezone-id.spec.ts index 5be420f3e2640f..9ed8953f9faada 100644 --- a/tests/browsercontext-timezone-id.spec.ts +++ b/tests/browsercontext-timezone-id.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should work', async ({ browser }) => { const func = () => new Date(1479579154987).toString(); diff --git a/tests/browsercontext-user-agent.spec.ts b/tests/browsercontext-user-agent.spec.ts index 141199edab8370..7846a1fe0565bd 100644 --- a/tests/browsercontext-user-agent.spec.ts +++ b/tests/browsercontext-user-agent.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import { attachFrame } from './config/utils'; it('should work', async ({browser, server}) => { diff --git a/tests/browsercontext-viewport-mobile.spec.ts b/tests/browsercontext-viewport-mobile.spec.ts index 4a63b60ac24f4c..1e4547f4bf306f 100644 --- a/tests/browsercontext-viewport-mobile.spec.ts +++ b/tests/browsercontext-viewport-mobile.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it.describe('mobile viewport', () => { it.beforeEach(async ({ browserName }) => { diff --git a/tests/browsercontext-viewport.spec.ts b/tests/browsercontext-viewport.spec.ts index f87d6fe70da8a7..051e634ce519c2 100644 --- a/tests/browsercontext-viewport.spec.ts +++ b/tests/browsercontext-viewport.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import { verifyViewport } from './config/utils'; it.beforeEach(async ({ isElectron, isAndroid }) => { diff --git a/tests/browsertype-basic.spec.ts b/tests/browsertype-basic.spec.ts index d4890020b86eaf..5480ed0598e7a4 100644 --- a/tests/browsertype-basic.spec.ts +++ b/tests/browsertype-basic.spec.ts @@ -16,7 +16,7 @@ */ import fs from 'fs'; -import { test, expect } from './config/playwrightTest'; +import { playwrightTest as test, expect } from './config/browserTest'; test('browserType.executablePath should work', async ({ browserType, browserChannel, browserOptions }) => { test.skip(!!browserChannel, 'We skip browser download when testing a channel'); diff --git a/tests/browsertype-connect.spec.ts b/tests/browsertype-connect.spec.ts index 94cef95e4fb79f..b73a6757439e58 100644 --- a/tests/browsertype-connect.spec.ts +++ b/tests/browsertype-connect.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { slowTest as test, expect } from './config/playwrightTest'; +import { slowPlaywrightTest as test, expect } from './config/browserTest'; import fs from 'fs'; import * as path from 'path'; diff --git a/tests/browsertype-launch-server.spec.ts b/tests/browsertype-launch-server.spec.ts index f5d95e89d6c398..8f1b288a0281d9 100644 --- a/tests/browsertype-launch-server.spec.ts +++ b/tests/browsertype-launch-server.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; it.describe('launch server', () => { it.beforeEach(async ({ mode}) => { @@ -45,7 +45,7 @@ it.describe('launch server', () => { it('should fire "close" event during kill', async ({browserType, browserOptions}) => { const order = []; const browserServer = await browserType.launchServer(browserOptions); - const closedPromise = new Promise(f => browserServer.on('close', () => { + const closedPromise = new Promise(f => browserServer.on('close', () => { order.push('closed'); f(); })); diff --git a/tests/browsertype-launch.spec.ts b/tests/browsertype-launch.spec.ts index 0357722f2a6747..19ef7d9e48014d 100644 --- a/tests/browsertype-launch.spec.ts +++ b/tests/browsertype-launch.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, slowTest, expect } from './config/playwrightTest'; +import { playwrightTest as it, slowPlaywrightTest as slowTest, expect } from './config/browserTest'; it('should reject all promises when browser is closed', async ({browserType, browserOptions}) => { const browser = await browserType.launch(browserOptions); diff --git a/tests/capabilities.spec.ts b/tests/capabilities.spec.ts index a76f3d37518087..ae17568f862a9f 100644 --- a/tests/capabilities.spec.ts +++ b/tests/capabilities.spec.ts @@ -16,7 +16,7 @@ import os from 'os'; import url from 'url'; -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; it('Web Assembly should work', async function({page, server, browserName, platform}) { it.fail(browserName === 'webkit' && platform === 'win32'); diff --git a/tests/channels.spec.ts b/tests/channels.spec.ts index 89e086d0833b4f..d7f1978f912cb5 100644 --- a/tests/channels.spec.ts +++ b/tests/channels.spec.ts @@ -16,7 +16,7 @@ */ import domain from 'domain'; -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; it('should scope context handles', async ({browserType, browserOptions, server}) => { const browser = await browserType.launch(browserOptions); diff --git a/tests/chromium/chromium.spec.ts b/tests/chromium/chromium.spec.ts index 42c297280d1ddd..315672e22139b1 100644 --- a/tests/chromium/chromium.spec.ts +++ b/tests/chromium/chromium.spec.ts @@ -16,7 +16,7 @@ */ import { test as pageTest, expect } from '../config/pageTest'; -import { test as playwrightTest } from '../config/playwrightTest'; +import { playwrightTest } from '../config/browserTest'; import http from 'http'; pageTest.describe('chromium', () => { diff --git a/tests/chromium/launcher.spec.ts b/tests/chromium/launcher.spec.ts index c1a05902ce4024..4855c6e627a840 100644 --- a/tests/chromium/launcher.spec.ts +++ b/tests/chromium/launcher.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from '../config/playwrightTest'; +import { playwrightTest as it, expect } from '../config/browserTest'; it.beforeEach(async ({ browserName }) => { it.skip(browserName !== 'chromium'); diff --git a/tests/chromium/oopif.spec.ts b/tests/chromium/oopif.spec.ts index 3e2dbb8c89ef15..696c3774867440 100644 --- a/tests/chromium/oopif.spec.ts +++ b/tests/chromium/oopif.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from '../config/playwrightTest'; +import { playwrightTest as it, expect } from '../config/browserTest'; import type { Browser, Page } from '../../index'; it.describe('oopif', () => { diff --git a/tests/chromium/session.spec.ts b/tests/chromium/session.spec.ts index 59438a10492e05..3a5ae7a73a3ed6 100644 --- a/tests/chromium/session.spec.ts +++ b/tests/chromium/session.spec.ts @@ -15,7 +15,7 @@ */ import { test as it, expect } from '../config/pageTest'; -import { test as browserTest } from '../config/browserTest'; +import { browserTest } from '../config/browserTest'; it.describe('session', () => { it.beforeEach(async ({ browserName }) => { @@ -58,7 +58,7 @@ it.describe('session', () => { page.on('console', console.log); // generate a script in page and wait for the event. await Promise.all([ - new Promise(f => client.on('Debugger.scriptParsed', event => { + new Promise(f => client.on('Debugger.scriptParsed', event => { if (event.url === 'foo.js') f(); })), diff --git a/tests/chromium/tracing.spec.ts b/tests/chromium/tracing.spec.ts index 180a533c83a70b..575cd0e00e4f28 100644 --- a/tests/chromium/tracing.spec.ts +++ b/tests/chromium/tracing.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from '../config/browserTest'; +import { browserTest as it, expect } from '../config/browserTest'; import fs from 'fs'; import path from 'path'; diff --git a/tests/cli/cli-codegen-1.spec.ts b/tests/cli/cli-codegen-1.spec.ts index 227655aabc327b..4f12d66a3b1041 100644 --- a/tests/cli/cli-codegen-1.spec.ts +++ b/tests/cli/cli-codegen-1.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; import * as http from 'http'; test.describe('cli codegen', () => { diff --git a/tests/cli/cli-codegen-2.spec.ts b/tests/cli/cli-codegen-2.spec.ts index 80ac325f6944e5..e5e4fcf024f6e6 100644 --- a/tests/cli/cli-codegen-2.spec.ts +++ b/tests/cli/cli-codegen-2.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; import * as http from 'http'; import * as url from 'url'; diff --git a/tests/cli/cli-codegen-csharp.spec.ts b/tests/cli/cli-codegen-csharp.spec.ts index 2abef1df75db32..e752de0df3f025 100644 --- a/tests/cli/cli-codegen-csharp.spec.ts +++ b/tests/cli/cli-codegen-csharp.spec.ts @@ -16,7 +16,7 @@ import path from 'path'; import fs from 'fs'; -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString(); const launchOptions = (channel: string) => { diff --git a/tests/cli/cli-codegen-java.spec.ts b/tests/cli/cli-codegen-java.spec.ts index 3fe1ba23a77515..75d6cb35a1a109 100644 --- a/tests/cli/cli-codegen-java.spec.ts +++ b/tests/cli/cli-codegen-java.spec.ts @@ -16,7 +16,7 @@ import fs from 'fs'; import path from 'path'; -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString(); const launchOptions = (channel: string) => { diff --git a/tests/cli/cli-codegen-javascript.spec.ts b/tests/cli/cli-codegen-javascript.spec.ts index 947f1840743273..d64ed99c021540 100644 --- a/tests/cli/cli-codegen-javascript.spec.ts +++ b/tests/cli/cli-codegen-javascript.spec.ts @@ -16,7 +16,7 @@ import fs from 'fs'; import path from 'path'; -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString(); diff --git a/tests/cli/cli-codegen-python-async.spec.ts b/tests/cli/cli-codegen-python-async.spec.ts index 0722026cc327d1..d17db779eb66a3 100644 --- a/tests/cli/cli-codegen-python-async.spec.ts +++ b/tests/cli/cli-codegen-python-async.spec.ts @@ -16,7 +16,7 @@ import fs from 'fs'; import path from 'path'; -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString(); const launchOptions = (channel: string) => { diff --git a/tests/cli/cli-codegen-python.spec.ts b/tests/cli/cli-codegen-python.spec.ts index 7dd6fde89a80a2..0fbd53d99c4fbd 100644 --- a/tests/cli/cli-codegen-python.spec.ts +++ b/tests/cli/cli-codegen-python.spec.ts @@ -16,7 +16,7 @@ import fs from 'fs'; import path from 'path'; -import { test, expect } from '../config/cliTest'; +import { cliTest as test, expect } from '../config/cliTest'; const emptyHTML = new URL('file://' + path.join(__dirname, '..', 'assets', 'empty.html')).toString(); const launchOptions = (channel: string) => { diff --git a/tests/config/android.config.ts b/tests/config/android.config.ts index 24fb01c6821745..3ca7920d4d5069 100644 --- a/tests/config/android.config.ts +++ b/tests/config/android.config.ts @@ -17,9 +17,8 @@ import * as folio from 'folio'; import * as path from 'path'; import { test as pageTest } from './pageTest'; -import { test as androidTest } from './androidTest'; -import { ServerEnv } from './serverEnv'; -import { AndroidEnv, AndroidPageEnv } from './androidEnv'; +import { AndroidEnv, androidTest } from './androidTest'; +import type { BrowserContext } from '../../index'; const config: folio.Config = { testDir: path.join(__dirname, '..'), @@ -41,6 +40,34 @@ if (process.env.CI) { ]); } -const serverEnv = new ServerEnv('10.0.2.2'); -pageTest.runWith(folio.merge(serverEnv, new AndroidPageEnv()), { tag: 'android' }); -androidTest.runWith(folio.merge(serverEnv, new AndroidEnv()), { tag: 'android' }); +class AndroidPageEnv extends AndroidEnv { + private _context?: BrowserContext; + + async beforeAll(args: any, workerInfo: folio.WorkerInfo) { + await super.beforeAll(args, workerInfo); + this._context = await this._device!.launchBrowser(); + } + + async beforeEach(args: any, testInfo: folio.TestInfo) { + const result = await super.beforeEach(args, testInfo); + const page = await this._context!.newPage(); + return { ...result, browserVersion: this._browserVersion, page }; + } + + async afterEach({}, testInfo: folio.TestInfo) { + for (const page of this._context!.pages()) + await page.close(); + } +} + +const envConfig = { + tag: 'android', + options: { + mode: 'default' as const, + engine: 'android' as const, + loopback: '10.0.2.2', + } +}; + +pageTest.runWith(envConfig, new AndroidPageEnv()); +androidTest.runWith(envConfig); diff --git a/tests/config/androidEnv.ts b/tests/config/androidEnv.ts deleted file mode 100644 index ed52642b815f7c..00000000000000 --- a/tests/config/androidEnv.ts +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Env, WorkerInfo, TestInfo } from 'folio'; -import type { AndroidDevice, BrowserContext } from '../../index'; -import * as os from 'os'; -import { AndroidTestArgs } from './androidTest'; -import { PageTestArgs } from './pageTest'; - -require('../../lib/utils/utils').setUnderTest(); -const playwright: typeof import('../../index') = require('../../index'); - -export class AndroidEnv implements Env { - protected _device?: AndroidDevice; - protected _browserVersion: string; - - async beforeAll(workerInfo: WorkerInfo) { - this._device = (await playwright._android.devices())[0]; - await this._device.shell('am force-stop org.chromium.webview_shell'); - await this._device.shell('am force-stop com.android.chrome'); - this._browserVersion = (await this._device.shell('dumpsys package com.android.chrome')) - .toString('utf8') - .split('\n') - .find(line => line.includes('versionName=')) - .trim() - .split('=')[1]; - this._device.setDefaultTimeout(90000); - } - - async beforeEach(testInfo: TestInfo) { - // Use chromium screenshots. - testInfo.snapshotPathSegment = 'chromium'; - testInfo.data = { - browserName: 'chromium', - platform: 'Android', - headful: true, - browserVersion: this._browserVersion, - }; - return { - mode: 'default' as const, - isChromium: true, - isFirefox: false, - isWebKit: false, - isAndroid: true, - isElectron: false, - browserName: 'chromium' as const, - browserChannel: undefined, - isWindows: os.platform() === 'win32', - isMac: os.platform() === 'darwin', - isLinux: os.platform() === 'linux', - platform: os.platform() as ('win32' | 'darwin' | 'linux'), - video: false, - headful: true, - toImpl: (playwright as any)._toImpl, - playwright, - androidDevice: this._device!, - }; - } - - async afterAll(workerInfo: WorkerInfo) { - if (this._device) - await this._device.close(); - this._device = undefined; - } -} - -export class AndroidPageEnv extends AndroidEnv implements Env { - private _context?: BrowserContext; - - async beforeAll(workerInfo: WorkerInfo) { - await super.beforeAll(workerInfo); - this._context = await this._device!.launchBrowser(); - } - - async beforeEach(testInfo: TestInfo) { - const result = await super.beforeEach(testInfo); - const page = await this._context!.newPage(); - return { - ...result, - browserVersion: this._browserVersion, - androidDevice: undefined, - page, - }; - } - - async afterEach(testInfo: TestInfo) { - for (const page of this._context!.pages()) - await page.close(); - } -} diff --git a/tests/config/androidTest.ts b/tests/config/androidTest.ts index 86abb6d61e005a..94a8cd3b60da2b 100644 --- a/tests/config/androidTest.ts +++ b/tests/config/androidTest.ts @@ -14,14 +14,46 @@ * limitations under the License. */ -import { newTestType } from 'folio'; import type { AndroidDevice } from '../../index'; -import type { CommonTestArgs } from './pageTest'; -import type { ServerTestArgs } from './serverTest'; +import { CommonWorkerArgs, test as baseTest } from './baseTest'; +import * as folio from 'folio'; export { expect } from 'folio'; -export type AndroidTestArgs = CommonTestArgs & { +type AndroidTestArgs = { androidDevice: AndroidDevice; }; -export const test = newTestType(); +export class AndroidEnv { + protected _device?: AndroidDevice; + protected _browserVersion: string; + + async beforeAll(args: CommonWorkerArgs, workerInfo: folio.WorkerInfo) { + this._device = (await args.playwright._android.devices())[0]; + await this._device.shell('am force-stop org.chromium.webview_shell'); + await this._device.shell('am force-stop com.android.chrome'); + this._browserVersion = (await this._device.shell('dumpsys package com.android.chrome')) + .toString('utf8') + .split('\n') + .find(line => line.includes('versionName=')) + .trim() + .split('=')[1]; + this._device.setDefaultTimeout(90000); + } + + async beforeEach({}, testInfo: folio.TestInfo): Promise { + testInfo.data.platform = 'Android'; + testInfo.data.headful = true; + testInfo.data.browserVersion = this._browserVersion; + return { + androidDevice: this._device!, + }; + } + + async afterAll({}, workerInfo: folio.WorkerInfo) { + if (this._device) + await this._device.close(); + this._device = undefined; + } +} + +export const androidTest = baseTest.extend(new AndroidEnv()); diff --git a/tests/config/baseTest.ts b/tests/config/baseTest.ts new file mode 100644 index 00000000000000..be89a3fdcee7c1 --- /dev/null +++ b/tests/config/baseTest.ts @@ -0,0 +1,295 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TestServer } from '../../utils/testserver'; +import * as folio from 'folio'; +import * as path from 'path'; +import * as fs from 'fs'; +import socks from 'socksv5'; +import { installCoverageHooks } from './coverage'; +import * as childProcess from 'child_process'; +import { start } from '../../lib/outofprocess'; +import { PlaywrightClient } from '../../lib/remote/playwrightClient'; + +export type BrowserName = 'chromium' | 'firefox' | 'webkit'; +type Mode = 'default' | 'driver' | 'service'; +type BaseTestArgs = { + mode: Mode; + platform: 'win32' | 'darwin' | 'linux'; + video: boolean; + headful: boolean; + + playwright: typeof import('../../index'); + toImpl: (rpcObject: any) => any; + browserName: BrowserName; + browserChannel: string | undefined; + + isChromium: boolean; + isFirefox: boolean; + isWebKit: boolean; + isAndroid: boolean; + isElectron: boolean; + isWindows: boolean; + isMac: boolean; + isLinux: boolean; +}; + +type BaseWorkerArgs = { + playwright: typeof import('../../index'); + browserName: BrowserName; + channel: string | undefined; +}; + +type BaseOptions = { + mode: Mode; + engine: 'chromium' | 'firefox' | 'webkit' | 'android' | 'electron'; + channel?: string; + video?: boolean; + headful?: boolean; +}; + +class DriverMode { + private _playwrightObject: any; + + async setup(workerInfo: folio.WorkerInfo) { + this._playwrightObject = await start(); + return this._playwrightObject; + } + + async teardown() { + await this._playwrightObject.stop(); + } +} + +class ServiceMode { + private _playwrightObejct: any; + private _client: any; + private _serviceProcess: childProcess.ChildProcess; + + async setup(workerInfo: folio.WorkerInfo) { + const port = 10507 + workerInfo.workerIndex; + this._serviceProcess = childProcess.fork(path.join(__dirname, '..', '..', 'lib', 'cli', 'cli.js'), ['run-server', String(port)], { + stdio: 'pipe' + }); + this._serviceProcess.stderr.pipe(process.stderr); + await new Promise(f => { + this._serviceProcess.stdout.on('data', data => { + if (data.toString().includes('Listening on')) + f(); + }); + }); + this._serviceProcess.on('exit', this._onExit); + this._client = await PlaywrightClient.connect(`ws://localhost:${port}/ws`); + this._playwrightObejct = this._client.playwright(); + return this._playwrightObejct; + } + + async teardown() { + await this._client.close(); + this._serviceProcess.removeListener('exit', this._onExit); + const processExited = new Promise(f => this._serviceProcess.on('exit', f)); + this._serviceProcess.kill(); + await processExited; + } + + private _onExit(exitCode, signal) { + throw new Error(`Server closed with exitCode=${exitCode} signal=${signal}`); + } +} + +class DefaultMode { + async setup(workerInfo: folio.WorkerInfo) { + return require('../../index'); + } + + async teardown() { + } +} + +class BaseEnv { + private _mode: DriverMode | ServiceMode | DefaultMode; + private _options: BaseOptions; + private _playwright: typeof import('../../index'); + + optionsType(): BaseOptions { + return {} as any; + } + + private _browserName(): BrowserName { + return (this._options.engine === 'android' || this._options.engine === 'electron') ? 'chromium' : this._options.engine; + } + + async beforeAll(options: BaseOptions, workerInfo: folio.WorkerInfo): Promise { + this._options = options; + this._mode = { + default: new DefaultMode(), + service: new ServiceMode(), + driver: new DriverMode(), + }[this._options.mode]; + require('../../lib/utils/utils').setUnderTest(); + this._playwright = await this._mode.setup(workerInfo); + return { + playwright: this._playwright, + browserName: this._browserName(), + channel: this._options.channel, + }; + } + + async beforeEach({}, testInfo: folio.TestInfo): Promise { + const browserName = this._browserName(); + testInfo.snapshotPathSegment = browserName; + testInfo.data = { + browserName, + }; + if (this._options.headful) + testInfo.data.headful = true; + if (this._options.mode !== 'default') + testInfo.data.mode = this._options.mode; + if (this._options.video) + testInfo.data.video = true; + return { + playwright: this._playwright, + browserName, + browserChannel: this._options.channel, + isChromium: browserName === 'chromium', + isFirefox: browserName === 'firefox', + isWebKit: browserName === 'webkit', + isAndroid: this._options.engine === 'android', + isElectron: this._options.engine === 'electron', + isWindows: process.platform === 'win32', + isMac: process.platform === 'darwin', + isLinux: process.platform === 'linux', + headful: !!this._options.headful, + video: !!this._options.video, + mode: this._options.mode, + platform: process.platform as ('win32' | 'darwin' | 'linux'), + toImpl: (this._playwright as any)._toImpl, + }; + } + + async afterAll({}, workerInfo: folio.WorkerInfo) { + await this._mode.teardown(); + } +} + +type ServerTestArgs = { + asset: (path: string) => string; + socksPort: number; + server: TestServer; + httpsServer: TestServer; +}; + +type ServerOptions = { + loopback?: string; +}; + +class ServerEnv { + private _server: TestServer; + private _httpsServer: TestServer; + private _socksServer: any; + private _socksPort: number; + + optionsType(): ServerOptions { + return {}; + } + + async beforeAll(options: ServerOptions, workerInfo: folio.WorkerInfo) { + const assetsPath = path.join(__dirname, '..', 'assets'); + const cachedPath = path.join(__dirname, '..', 'assets', 'cached'); + + const port = 8907 + workerInfo.workerIndex * 3; + this._server = await TestServer.create(assetsPath, port, options.loopback); + this._server.enableHTTPCache(cachedPath); + + const httpsPort = port + 1; + this._httpsServer = await TestServer.createHTTPS(assetsPath, httpsPort, options.loopback); + this._httpsServer.enableHTTPCache(cachedPath); + + this._socksServer = socks.createServer((info, accept, deny) => { + let socket; + if ((socket = accept(true))) { + // Catch and ignore ECONNRESET errors. + socket.on('error', () => {}); + const body = 'Served by the SOCKS proxy'; + socket.end([ + 'HTTP/1.1 200 OK', + 'Connection: close', + 'Content-Type: text/html', + 'Content-Length: ' + Buffer.byteLength(body), + '', + body + ].join('\r\n')); + } + }); + this._socksPort = port + 2; + this._socksServer.listen(this._socksPort, 'localhost'); + this._socksServer.useAuth(socks.auth.None()); + return {}; + } + + async beforeEach({}, testInfo: folio.TestInfo): Promise { + this._server.reset(); + this._httpsServer.reset(); + return { + asset: (p: string) => path.join(__dirname, '..', 'assets', ...p.split('/')), + server: this._server, + httpsServer: this._httpsServer, + socksPort: this._socksPort, + }; + } + + async afterAll({}, workerInfo: folio.WorkerInfo) { + await Promise.all([ + this._server.stop(), + this._httpsServer.stop(), + this._socksServer.close(), + ]); + } +} + +type CoverageOptions = { + coverageName?: string; +}; + +class CoverageEnv { + private _coverage: ReturnType | undefined; + + optionsType(): CoverageOptions { + return {}; + } + + async beforeAll(options: CoverageOptions, workerInfo: folio.WorkerInfo) { + if (options.coverageName) + this._coverage = installCoverageHooks(options.coverageName); + return {}; + } + + async afterAll({}, workerInfo: folio.WorkerInfo) { + if (!this._coverage) + return; + const { coverage, uninstall } = this._coverage; + uninstall(); + const coveragePath = path.join(__dirname, '..', 'coverage-report', workerInfo.workerIndex + '.json'); + const coverageJSON = Array.from(coverage.keys()).filter(key => coverage.get(key)); + await fs.promises.mkdir(path.dirname(coveragePath), { recursive: true }); + await fs.promises.writeFile(coveragePath, JSON.stringify(coverageJSON, undefined, 2), 'utf8'); + } +} + +export type CommonTestArgs = BaseTestArgs & ServerTestArgs; +export type CommonWorkerArgs = BaseWorkerArgs; + +export const test = folio.test.extend(new CoverageEnv()).extend(new ServerEnv()).extend(new BaseEnv()); diff --git a/tests/config/browserEnv.ts b/tests/config/browserEnv.ts deleted file mode 100644 index 1c38173c484a6c..00000000000000 --- a/tests/config/browserEnv.ts +++ /dev/null @@ -1,286 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Env, WorkerInfo, TestInfo } from 'folio'; -import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions } from '../../index'; -import { start } from '../../lib/outofprocess'; -import { PlaywrightClient } from '../../lib/remote/playwrightClient'; -import { removeFolders } from '../../lib/utils/utils'; -import * as path from 'path'; -import * as fs from 'fs'; -import * as os from 'os'; -import * as util from 'util'; -import * as childProcess from 'child_process'; -import { PlaywrightTestArgs } from './playwrightTest'; -import { BrowserTestArgs } from './browserTest'; -import { RemoteServer, RemoteServerOptions } from './remoteServer'; - -const mkdtempAsync = util.promisify(fs.mkdtemp); - -export type BrowserName = 'chromium' | 'firefox' | 'webkit'; - -type TestOptions = { - mode: 'default' | 'driver' | 'service'; - video?: boolean; - traceDir?: string; -}; - -class DriverMode { - private _playwrightObject: any; - - async setup(workerInfo: WorkerInfo) { - this._playwrightObject = await start(); - return this._playwrightObject; - } - - async teardown() { - await this._playwrightObject.stop(); - } -} - -class ServiceMode { - private _playwrightObejct: any; - private _client: any; - private _serviceProcess: childProcess.ChildProcess; - - async setup(workerInfo: WorkerInfo) { - const port = 10507 + workerInfo.workerIndex; - this._serviceProcess = childProcess.fork(path.join(__dirname, '..', '..', 'lib', 'cli', 'cli.js'), ['run-server', String(port)], { - stdio: 'pipe' - }); - this._serviceProcess.stderr.pipe(process.stderr); - await new Promise(f => { - this._serviceProcess.stdout.on('data', data => { - if (data.toString().includes('Listening on')) - f(); - }); - }); - this._serviceProcess.on('exit', this._onExit); - this._client = await PlaywrightClient.connect(`ws://localhost:${port}/ws`); - this._playwrightObejct = this._client.playwright(); - return this._playwrightObejct; - } - - async teardown() { - await this._client.close(); - this._serviceProcess.removeListener('exit', this._onExit); - const processExited = new Promise(f => this._serviceProcess.on('exit', f)); - this._serviceProcess.kill(); - await processExited; - } - - private _onExit(exitCode, signal) { - throw new Error(`Server closed with exitCode=${exitCode} signal=${signal}`); - } -} - -class DefaultMode { - async setup(workerInfo: WorkerInfo) { - return require('../../index'); - } - - async teardown() { - } -} - -export class PlaywrightEnv implements Env { - private _mode: DriverMode | ServiceMode | DefaultMode; - protected _browserName: BrowserName; - protected _options: LaunchOptions & TestOptions; - protected _browserOptions: LaunchOptions; - private _playwright: typeof import('../../index'); - protected _browserType: BrowserType; - private _userDataDirs: string[] = []; - private _persistentContext: BrowserContext | undefined; - private _remoteServer: RemoteServer | undefined; - - constructor(browserName: BrowserName, options: LaunchOptions & TestOptions) { - this._browserName = browserName; - this._options = options; - this._mode = { - default: new DefaultMode(), - service: new ServiceMode(), - driver: new DriverMode(), - }[this._options.mode]; - } - - async beforeAll(workerInfo: WorkerInfo) { - require('../../lib/utils/utils').setUnderTest(); - this._playwright = await this._mode.setup(workerInfo); - this._browserType = this._playwright[this._browserName]; - const options = { - ...this._options, - _traceDir: this._options.traceDir, - handleSIGINT: false, - }; - this._browserOptions = options; - } - - private async _createUserDataDir() { - // We do not put user data dir in testOutputPath, - // because we do not want to upload them as test result artifacts. - // - // Additionally, it is impossible to upload user data dir after test run: - // - Firefox removes lock file later, presumably from another watchdog process? - // - WebKit has circular symlinks that makes CI go crazy. - const dir = await mkdtempAsync(path.join(os.tmpdir(), 'playwright-test-')); - this._userDataDirs.push(dir); - return dir; - } - - private async _launchPersistent(options?: Parameters[1]) { - if (this._persistentContext) - throw new Error('can only launch one persitent context'); - const userDataDir = await this._createUserDataDir(); - this._persistentContext = await this._browserType.launchPersistentContext(userDataDir, { ...this._browserOptions, ...options }); - const page = this._persistentContext.pages()[0]; - return { context: this._persistentContext, page }; - } - - private async _startRemoteServer(options?: RemoteServerOptions): Promise { - if (this._remoteServer) - throw new Error('can only start one remote server'); - this._remoteServer = new RemoteServer(); - await this._remoteServer._start(this._browserType, this._browserOptions, options); - return this._remoteServer; - } - - async beforeEach(testInfo: TestInfo) { - // Different screenshots per browser. - testInfo.snapshotPathSegment = this._browserName; - testInfo.data = { - browserName: this._browserName, - }; - const headful = !this._browserOptions.headless; - if (headful) - testInfo.data.headful = true; - if (this._options.mode !== 'default') - testInfo.data.mode = this._options.mode; - if (this._options.video) - testInfo.data.video = true; - return { - playwright: this._playwright, - browserName: this._browserName, - browserType: this._browserType, - browserChannel: this._options.channel, - browserOptions: this._browserOptions, - isChromium: this._browserName === 'chromium', - isFirefox: this._browserName === 'firefox', - isWebKit: this._browserName === 'webkit', - isAndroid: false, - isElectron: false, - isWindows: os.platform() === 'win32', - isMac: os.platform() === 'darwin', - isLinux: os.platform() === 'linux', - headful, - video: !!this._options.video, - mode: this._options.mode, - platform: os.platform() as ('win32' | 'darwin' | 'linux'), - createUserDataDir: this._createUserDataDir.bind(this), - launchPersistent: this._launchPersistent.bind(this), - toImpl: (this._playwright as any)._toImpl, - startRemoteServer: this._startRemoteServer.bind(this), - }; - } - - async afterEach(testInfo: TestInfo) { - if (this._persistentContext) { - await this._persistentContext.close(); - this._persistentContext = undefined; - } - if (this._remoteServer) { - await this._remoteServer.close(); - this._remoteServer = undefined; - } - await removeFolders(this._userDataDirs); - this._userDataDirs = []; - } - - async afterAll(workerInfo: WorkerInfo) { - await this._mode.teardown(); - } -} - -export class BrowserEnv extends PlaywrightEnv implements Env { - private _browser: Browser | undefined; - private _contextOptions: BrowserContextOptions; - private _contexts: BrowserContext[] = []; - protected _browserVersion: string; - - constructor(browserName: BrowserName, options: LaunchOptions & BrowserContextOptions & TestOptions) { - super(browserName, options); - this._contextOptions = options; - } - - async beforeAll(workerInfo: WorkerInfo) { - await super.beforeAll(workerInfo); - this._browser = await this._browserType.launch(this._browserOptions); - this._browserVersion = this._browser.version(); - } - - async beforeEach(testInfo: TestInfo) { - const result = await super.beforeEach(testInfo); - const debugName = path.relative(testInfo.config.outputDir, testInfo.outputPath('')).replace(/[\/\\]/g, '-'); - const contextOptions = { - recordVideo: this._options.video ? { dir: testInfo.outputPath('') } : undefined, - _debugName: debugName, - ...this._contextOptions, - } as BrowserContextOptions; - - testInfo.data.browserVersion = this._browserVersion; - - const contextFactory = async (options: BrowserContextOptions = {}) => { - const context = await this._browser.newContext({ ...contextOptions, ...options }); - this._contexts.push(context); - return context; - }; - - return { - ...result, - browser: this._browser, - contextOptions: this._contextOptions as BrowserContextOptions, - contextFactory, - }; - } - - async afterEach(testInfo: TestInfo) { - for (const context of this._contexts) - await context.close(); - this._contexts = []; - await super.afterEach(testInfo); - } - - async afterAll(workerInfo: WorkerInfo) { - if (this._browser) - await this._browser.close(); - this._browser = undefined; - await super.afterAll(workerInfo); - } -} - -export class PageEnv extends BrowserEnv { - async beforeEach(testInfo: TestInfo) { - const result = await super.beforeEach(testInfo); - const context = await result.contextFactory(); - const page = await context.newPage(); - return { - ...result, - browserVersion: this._browserVersion, - context, - page, - }; - } -} diff --git a/tests/config/browserTest.ts b/tests/config/browserTest.ts index 44fd8b539647ab..3a336d78286411 100644 --- a/tests/config/browserTest.ts +++ b/tests/config/browserTest.ts @@ -14,17 +14,199 @@ * limitations under the License. */ -import { newTestType } from 'folio'; -import type { Browser, BrowserContextOptions, BrowserContext } from '../../index'; -import type { PlaywrightTestArgs } from './playwrightTest'; -import type { ServerTestArgs } from './serverTest'; -export { expect } from 'folio'; +import * as folio from 'folio'; +import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions, Page } from '../../index'; +import { removeFolders } from '../../lib/utils/utils'; +import * as path from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as util from 'util'; +import { RemoteServer, RemoteServerOptions } from './remoteServer'; +import { CommonTestArgs, CommonWorkerArgs, test as baseTest } from './baseTest'; + +const mkdtempAsync = util.promisify(fs.mkdtemp); + +type PlaywrightTestArgs = { + browserType: BrowserType; + browserOptions: LaunchOptions; + createUserDataDir: () => Promise; + launchPersistent: (options?: Parameters[1]) => Promise<{ context: BrowserContext, page: Page }>; + startRemoteServer: (options?: RemoteServerOptions) => Promise; +}; + +type PlaywrightEnvOptions = { + launchOptions?: LaunchOptions; + traceDir?: string; +}; + +type PlaywrightEnvWorkerArgs = { + browserType: BrowserType; + browserOptions: LaunchOptions; +}; + +class PlaywrightEnv { + protected _browserOptions: LaunchOptions; + protected _browserType: BrowserType; + private _userDataDirs: string[] = []; + private _persistentContext: BrowserContext | undefined; + private _remoteServer: RemoteServer | undefined; + + optionsType(): PlaywrightEnvOptions { + return {}; + } + + async beforeAll(args: CommonWorkerArgs & PlaywrightEnvOptions, workerInfo: folio.WorkerInfo): Promise { + this._browserType = args.playwright[args.browserName]; + this._browserOptions = { + ...args.launchOptions, + _traceDir: args.traceDir, + channel: args.channel, + handleSIGINT: false, + } as any; + return { + browserType: this._browserType, + browserOptions: this._browserOptions, + }; + } + + private async _createUserDataDir() { + // We do not put user data dir in testOutputPath, + // because we do not want to upload them as test result artifacts. + // + // Additionally, it is impossible to upload user data dir after test run: + // - Firefox removes lock file later, presumably from another watchdog process? + // - WebKit has circular symlinks that makes CI go crazy. + const dir = await mkdtempAsync(path.join(os.tmpdir(), 'playwright-test-')); + this._userDataDirs.push(dir); + return dir; + } + + private async _launchPersistent(options?: Parameters[1]) { + if (this._persistentContext) + throw new Error('can only launch one persitent context'); + const userDataDir = await this._createUserDataDir(); + this._persistentContext = await this._browserType.launchPersistentContext(userDataDir, { ...this._browserOptions, ...options }); + const page = this._persistentContext.pages()[0]; + return { context: this._persistentContext, page }; + } + + private async _startRemoteServer(options?: RemoteServerOptions): Promise { + if (this._remoteServer) + throw new Error('can only start one remote server'); + this._remoteServer = new RemoteServer(); + await this._remoteServer._start(this._browserType, this._browserOptions, options); + return this._remoteServer; + } + + async beforeEach({}, testInfo: folio.TestInfo): Promise { + return { + browserType: this._browserType, + browserOptions: this._browserOptions, + createUserDataDir: this._createUserDataDir.bind(this), + launchPersistent: this._launchPersistent.bind(this), + startRemoteServer: this._startRemoteServer.bind(this), + }; + } + + async afterEach({}, testInfo: folio.TestInfo) { + if (this._persistentContext) { + await this._persistentContext.close(); + this._persistentContext = undefined; + } + if (this._remoteServer) { + await this._remoteServer.close(); + this._remoteServer = undefined; + } + await removeFolders(this._userDataDirs); + this._userDataDirs = []; + } +} + +export const playwrightTest = baseTest.extend(new PlaywrightEnv()); +export const slowPlaywrightTest = baseTest.extend(new PlaywrightEnv()); -export type BrowserTestArgs = PlaywrightTestArgs & { +type BrowserEnvOptions = { + contextOptions?: BrowserContextOptions; +}; + +type BrowserTestArgs = { browser: Browser; + browserVersion: string; contextOptions: BrowserContextOptions; contextFactory: (options?: BrowserContextOptions) => Promise; }; -export const test = newTestType(); -export const slowTest = newTestType(); +class BrowserEnv { + private _browser: Browser | undefined; + private _contextOptions: BrowserContextOptions; + private _contexts: BrowserContext[] = []; + protected _browserVersion: string; + + optionsType(): BrowserEnvOptions { + return {}; + } + + async beforeAll(args: PlaywrightEnvWorkerArgs, workerInfo: folio.WorkerInfo) { + this._browser = await args.browserType.launch(args.browserOptions); + this._browserVersion = this._browser.version(); + } + + async beforeEach(options: CommonTestArgs, testInfo: folio.TestInfo): Promise { + const debugName = path.relative(testInfo.config.outputDir, testInfo.outputDir).replace(/[\/\\]/g, '-'); + const contextOptions = { + recordVideo: options.video ? { dir: testInfo.outputPath('') } : undefined, + _debugName: debugName, + ...this._contextOptions, + } as BrowserContextOptions; + + testInfo.data.browserVersion = this._browserVersion; + + const contextFactory = async (options: BrowserContextOptions = {}) => { + const context = await this._browser.newContext({ ...contextOptions, ...options }); + this._contexts.push(context); + return context; + }; + + return { + browser: this._browser, + browserVersion: this._browserVersion, + contextOptions: this._contextOptions as BrowserContextOptions, + contextFactory, + }; + } + + async afterEach({}, testInfo: folio.TestInfo) { + for (const context of this._contexts) + await context.close(); + this._contexts = []; + } + + async afterAll({}, workerInfo: folio.WorkerInfo) { + if (this._browser) + await this._browser.close(); + this._browser = undefined; + } +} + +export const browserTest = playwrightTest.extend(new BrowserEnv()); +export const slowBrowserTest = slowPlaywrightTest.extend(new BrowserEnv()); + +type ContextTestArgs = { + context: BrowserContext; + page: Page; +}; + +class ContextEnv { + async beforeEach(args: BrowserTestArgs, testInfo: folio.TestInfo): Promise { + const context = await args.contextFactory(); + const page = await context.newPage(); + return { + context, + page, + }; + } +} + +export const contextTest = browserTest.extend(new ContextEnv()); + +export { expect } from 'folio'; diff --git a/tests/config/cliEnv.ts b/tests/config/cliEnv.ts deleted file mode 100644 index db4c6def0ce162..00000000000000 --- a/tests/config/cliEnv.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Env, TestInfo, WorkerInfo } from 'folio'; -import { PageEnv } from './browserEnv'; -import { CLIMock, CLITestArgs, Recorder } from './cliTest'; -import * as http from 'http'; -import { chromium } from '../../index'; - -export class CLIEnv extends PageEnv implements Env { - private _server: http.Server | undefined; - private _handler = (req: http.IncomingMessage, res: http.ServerResponse) => res.end(); - private _port: number; - private _cli: CLIMock | undefined; - - async beforeAll(workerInfo: WorkerInfo) { - await super.beforeAll(workerInfo); - - this._port = 10907 + workerInfo.workerIndex * 2; - this._server = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => this._handler(req, res)).listen(this._port); - process.env.PWTEST_RECORDER_PORT = String(this._port + 1); - } - - private _runCLI(args: string[]) { - this._cli = new CLIMock(this._browserName, this._browserOptions.channel, !!this._browserOptions.headless, args); - return this._cli; - } - - async beforeEach(testInfo: TestInfo) { - const result = await super.beforeEach(testInfo); - const { page, context, toImpl } = result; - const recorderPageGetter = async () => { - while (!toImpl(context).recorderAppForTest) - await new Promise(f => setTimeout(f, 100)); - const wsEndpoint = toImpl(context).recorderAppForTest.wsEndpoint; - const browser = await chromium.connectOverCDP({ wsEndpoint }); - const c = browser.contexts()[0]; - return c.pages()[0] || await c.waitForEvent('page'); - }; - return { - ...result, - httpServer: { - setHandler: newHandler => this._handler = newHandler, - PREFIX: `http://127.0.0.1:${this._port}`, - }, - runCLI: this._runCLI.bind(this), - openRecorder: async () => { - await (page.context() as any)._enableRecorder({ language: 'javascript', startRecording: true }); - return new Recorder(page, await recorderPageGetter()); - }, - recorderPageGetter, - }; - } - - async afterEach(testInfo: TestInfo) { - if (this._cli) { - await this._cli.exited; - this._cli = undefined; - } - await super.afterEach(testInfo); - } - - async afterAll(workerInfo: WorkerInfo) { - if (this._server) { - this._server.close(); - this._server = undefined; - } - await super.afterAll(workerInfo); - } -} diff --git a/tests/config/cliTest.ts b/tests/config/cliTest.ts index f74f428b0b0768..e9f6877839e1c0 100644 --- a/tests/config/cliTest.ts +++ b/tests/config/cliTest.ts @@ -14,33 +14,78 @@ * limitations under the License. */ -import { newTestType } from 'folio'; -import type { Page, BrowserContext } from '../../index'; -import type { ServerTestArgs } from './serverTest'; -import type { BrowserTestArgs } from './browserTest'; +import { contextTest } from './browserTest'; +import type { Page } from '../../index'; import * as http from 'http'; import * as path from 'path'; import type { Source } from '../../src/server/supplements/recorder/recorderTypes'; import { ChildProcess, spawn } from 'child_process'; +import { chromium } from '../../index'; +import * as folio from 'folio'; export { expect } from 'folio'; interface CLIHTTPServer { - setHandler: (handler: http.RequestListener) => void - PREFIX: string + setHandler: (handler: http.RequestListener) => void; + PREFIX: string; } -export type CLITestArgs = BrowserTestArgs & { - page: Page; - context: BrowserContext; +type CLITestArgs = { httpServer: CLIHTTPServer; recorderPageGetter: () => Promise; openRecorder: () => Promise; runCLI: (args: string[]) => CLIMock; }; -export const test = newTestType(); +export const cliTest = contextTest.extend({ + async beforeAll({}, workerInfo: folio.WorkerInfo) { + this._port = 10907 + workerInfo.workerIndex * 2; + this._server = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => this._handler(req, res)).listen(this._port); + process.env.PWTEST_RECORDER_PORT = String(this._port + 1); + }, + + async beforeEach({ page, context, toImpl, browserName, browserChannel, headful, mode }, testInfo: folio.TestInfo): Promise { + testInfo.skip(mode === 'service'); + const recorderPageGetter = async () => { + while (!toImpl(context).recorderAppForTest) + await new Promise(f => setTimeout(f, 100)); + const wsEndpoint = toImpl(context).recorderAppForTest.wsEndpoint; + const browser = await chromium.connectOverCDP({ wsEndpoint }); + const c = browser.contexts()[0]; + return c.pages()[0] || await c.waitForEvent('page'); + }; + return { + httpServer: { + setHandler: newHandler => this._handler = newHandler, + PREFIX: `http://127.0.0.1:${this._port}`, + }, + runCLI: (cliArgs: string[]) => { + this._cli = new CLIMock(browserName, browserChannel, !headful, cliArgs); + return this._cli; + }, + openRecorder: async () => { + await (page.context() as any)._enableRecorder({ language: 'javascript', startRecording: true }); + return new Recorder(page, await recorderPageGetter()); + }, + recorderPageGetter, + }; + }, + + async afterEach({}, testInfo: folio.TestInfo) { + if (this._cli) { + await this._cli.exited; + this._cli = undefined; + } + }, + + async afterAll({}, workerInfo: folio.WorkerInfo) { + if (this._server) { + this._server.close(); + this._server = undefined; + } + }, +}); -export class Recorder { +class Recorder { page: Page; _highlightCallback: Function _highlightInstalled: boolean @@ -129,7 +174,7 @@ export class Recorder { } } -export class CLIMock { +class CLIMock { private process: ChildProcess; private data: string; private waitForText: string; diff --git a/tests/config/contextTest.ts b/tests/config/contextTest.ts deleted file mode 100644 index 9885e20b9a813d..00000000000000 --- a/tests/config/contextTest.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { newTestType } from 'folio'; -import type { BrowserContext, Page } from '../../index'; -import type { BrowserTestArgs } from './browserTest'; -import type { ServerTestArgs } from './serverTest'; -export { expect } from 'folio'; - -// Context test guarantees an isolated context. -export type ContextTestArgs = BrowserTestArgs & { - context: BrowserContext; - page: Page; -}; -export const test = newTestType(); diff --git a/tests/config/coverage.js b/tests/config/coverage.js index 9b6c3c7e5f62b2..48c3965da7d56f 100644 --- a/tests/config/coverage.js +++ b/tests/config/coverage.js @@ -93,35 +93,6 @@ function installCoverageHooks(browserName) { return {coverage, uninstall}; } -class CoverageEnv { - /** - * @param {string} browserName - */ - constructor(browserName) { - this.browserName = browserName; - } - - /** - * @param {import('folio').WorkerInfo} workerInfo - */ - async beforeAll(workerInfo) { - this.coverage = installCoverageHooks(this.browserName); - } - - /** - * @param {import('folio').WorkerInfo} workerInfo - */ - async afterAll(workerInfo) { - const { coverage, uninstall } = this.coverage; - uninstall(); - const coveragePath = path.join(__dirname, '..', 'coverage-report', workerInfo.workerIndex + '.json'); - const coverageJSON = Array.from(coverage.keys()).filter(key => coverage.get(key)); - await fs.promises.mkdir(path.dirname(coveragePath), { recursive: true }); - await fs.promises.writeFile(coveragePath, JSON.stringify(coverageJSON, undefined, 2), 'utf8'); - } -} - module.exports = { installCoverageHooks, - CoverageEnv }; diff --git a/tests/config/default.config.ts b/tests/config/default.config.ts index 3823b7ec50e522..d75a41b670ddf2 100644 --- a/tests/config/default.config.ts +++ b/tests/config/default.config.ts @@ -16,15 +16,10 @@ import * as folio from 'folio'; import * as path from 'path'; -import { test as playwrightTest, slowTest as playwrightSlowTest } from './playwrightTest'; -import { test as browserTest, slowTest as browserSlowTest } from './browserTest'; -import { test as contextTest } from './contextTest'; +import { playwrightTest, slowPlaywrightTest, contextTest } from './browserTest'; import { test as pageTest } from './pageTest'; -import { test as cliTest } from './cliTest'; -import { PlaywrightEnv, BrowserEnv, PageEnv, BrowserName } from './browserEnv'; -import { ServerEnv } from './serverEnv'; -import { CLIEnv } from './cliEnv'; -import { CoverageEnv } from './coverage'; +import { BrowserName, CommonTestArgs, CommonWorkerArgs } from './baseTest'; +import type { Browser, BrowserContext } from '../../index'; const config: folio.Config = { testDir: path.join(__dirname, '..'), @@ -55,27 +50,68 @@ const getExecutablePath = (browserName: BrowserName) => { return process.env.WKPATH; }; +type WorkerOptionsFor = T extends folio.TestType ? WO : any; +type AllOptions = WorkerOptionsFor; + +class PageEnv { + private _browser: Browser + private _browserVersion: string; + private _context: BrowserContext | undefined; + + async beforeAll(args: AllOptions & CommonWorkerArgs, workerInfo: folio.WorkerInfo) { + this._browser = await args.playwright[args.browserName].launch({ + ...args.launchOptions, + _traceDir: args.traceDir, + channel: args.channel, + handleSIGINT: false, + } as any); + this._browserVersion = this._browser.version(); + return {}; + } + + async beforeEach(args: AllOptions & CommonTestArgs, testInfo: folio.TestInfo) { + testInfo.data.browserVersion = this._browserVersion; + this._context = await this._browser.newContext({ + recordVideo: args.video ? { dir: testInfo.outputPath('') } : undefined, + ...args.contextOptions, + }); + const page = await this._context.newPage(); + return { context: this._context, page, browserVersion: this._browserVersion }; + } + + async afterEach({}) { + if (this._context) + await this._context.close(); + this._context = undefined; + } + + async afterAll({}, workerInfo: folio.WorkerInfo) { + await this._browser.close(); + } +} + const browsers = ['chromium', 'webkit', 'firefox'] as BrowserName[]; for (const browserName of browsers) { const executablePath = getExecutablePath(browserName); if (executablePath && (process.env.FOLIO_WORKER_INDEX === undefined || process.env.FOLIO_WORKER_INDEX === '')) console.error(`Using executable at ${executablePath}`); const mode = (process.env.PWTEST_MODE || 'default') as ('default' | 'driver' | 'service'); - const options = { - mode, - executablePath, - traceDir: process.env.PWTRACE ? path.join(config.outputDir, 'trace') : undefined, - headless: !process.env.HEADFUL, - channel: process.env.PWTEST_CHANNEL as any, - video: !!process.env.PWTEST_VIDEO, + const envConfig = { + options: { + mode, + engine: browserName, + headless: !process.env.HEADFUL, + channel: process.env.PWTEST_CHANNEL as any, + video: !!process.env.PWTEST_VIDEO, + traceDir: process.env.PWTRACE ? path.join(config.outputDir, 'trace') : undefined, + launchOptions: { + executablePath, + }, + coverageName: browserName, + }, + tag: browserName, }; - const commonEnv = folio.merge(new CoverageEnv(browserName), new ServerEnv()); - playwrightTest.runWith(folio.merge(commonEnv, new PlaywrightEnv(browserName, options)), { tag: browserName }); - playwrightSlowTest.runWith(folio.merge(commonEnv, new PlaywrightEnv(browserName, options)), { timeout: config.timeout * 3, tag: browserName }); - browserTest.runWith(folio.merge(commonEnv, new BrowserEnv(browserName, options)), { tag: browserName }); - browserSlowTest.runWith(folio.merge(commonEnv, new BrowserEnv(browserName, options)), { timeout: config.timeout * 3, tag: browserName }); - pageTest.runWith(folio.merge(commonEnv, new PageEnv(browserName, options)), { tag: browserName }); - contextTest.runWith(folio.merge(commonEnv, new PageEnv(browserName, options)), { tag: browserName }); - if (mode !== 'service') - cliTest.runWith(folio.merge(commonEnv, new CLIEnv(browserName, options)), { tag: browserName }); + playwrightTest.runWith(envConfig); + slowPlaywrightTest.runWith({ ...envConfig, timeout: config.timeout * 3 }); + pageTest.runWith(envConfig, new PageEnv()); } diff --git a/tests/config/electron.config.ts b/tests/config/electron.config.ts index 40f1a327741f2d..ce201fe6a6f015 100644 --- a/tests/config/electron.config.ts +++ b/tests/config/electron.config.ts @@ -16,11 +16,8 @@ import * as folio from 'folio'; import * as path from 'path'; -import { test as electronTest } from './electronTest'; +import { ElectronEnv, electronTest } from './electronTest'; import { test as pageTest } from './pageTest'; -import { ServerEnv } from './serverEnv'; -import { ElectronEnv, ElectronPageEnv } from './electronEnv'; -import { CoverageEnv } from './coverage'; const config: folio.Config = { testDir: path.join(__dirname, '..'), @@ -42,7 +39,26 @@ if (process.env.CI) { ]); } -const serverEnv = new ServerEnv(); -const coverageEnv = new CoverageEnv('electron'); -electronTest.runWith(folio.merge(coverageEnv, serverEnv, new ElectronEnv()), { tag: 'electron' }); -pageTest.runWith(folio.merge(coverageEnv, serverEnv, new ElectronPageEnv()), { tag: 'electron' }); +class ElectronPageEnv extends ElectronEnv { + async beforeEach(args: any, testInfo: folio.TestInfo) { + const result = await super.beforeEach(args, testInfo); + const page = await result.newWindow(); + return { + ...result, + browserVersion: this._browserVersion, + page, + }; + } +} + +const envConfig = { + tag: 'electron', + options: { + mode: 'default' as const, + engine: 'electron' as const, + coverageName: 'electron' + } +}; + +electronTest.runWith(envConfig); +pageTest.runWith(envConfig, new ElectronPageEnv()); diff --git a/tests/config/electronEnv.ts b/tests/config/electronEnv.ts deleted file mode 100644 index 43ca57dd5a6e9b..00000000000000 --- a/tests/config/electronEnv.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Env, TestInfo } from 'folio'; -import { PlaywrightEnv } from './browserEnv'; -import * as path from 'path'; -import { ElectronTestArgs } from './electronTest'; -import { ElectronApplication, Page } from '../../index'; -import { PageTestArgs } from './pageTest'; - -export class ElectronEnv extends PlaywrightEnv implements Env { - private _electronApp: ElectronApplication | undefined; - private _windows: Page[] = []; - protected _browserVersion: string; - - constructor() { - super('chromium', { mode: 'default' }); - // This env prevents 'Electron Security Policy' console message. - process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; - this._browserVersion = require('electron/package.json').version; - } - - private async _newWindow() { - const [ window ] = await Promise.all([ - this._electronApp!.waitForEvent('window'), - this._electronApp!.evaluate(electron => { - const window = new electron.BrowserWindow({ - width: 800, - height: 600, - // Sandboxed windows share process with their window.open() children - // and can script them. We use that heavily in our tests. - webPreferences: { sandbox: true } - }); - window.loadURL('about:blank'); - }) - ]); - this._windows.push(window); - return window; - } - - async beforeEach(testInfo: TestInfo) { - const result = await super.beforeEach(testInfo); - this._electronApp = await result.playwright._electron.launch({ - args: [path.join(__dirname, 'electron-app.js')], - }); - testInfo.data = { - browserName: 'electron', - browserVersion: this._browserVersion, - }; - return { - ...result, - isElectron: true, - electronApp: this._electronApp, - newWindow: this._newWindow.bind(this), - }; - } - - async afterEach(testInfo: TestInfo) { - for (const window of this._windows) - await window.close(); - this._windows = []; - if (this._electronApp) { - await this._electronApp.close(); - this._electronApp = undefined; - } - await super.afterEach(testInfo); - } -} - -export class ElectronPageEnv extends ElectronEnv implements Env { - async beforeEach(testInfo: TestInfo) { - const result = await super.beforeEach(testInfo); - const page = await result.newWindow(); - return { - ...result, - browserVersion: this._browserVersion, - page, - }; - } -} diff --git a/tests/config/electronTest.ts b/tests/config/electronTest.ts index 1942ffc28141f2..6dae12fffc29aa 100644 --- a/tests/config/electronTest.ts +++ b/tests/config/electronTest.ts @@ -14,15 +14,67 @@ * limitations under the License. */ -import { newTestType } from 'folio'; +import { CommonTestArgs, test as baseTest } from './baseTest'; import { ElectronApplication, Page } from '../../index'; -import type { CommonTestArgs } from './pageTest'; -import type { ServerTestArgs } from './serverTest'; +import * as folio from 'folio'; +import * as path from 'path'; export { expect } from 'folio'; -export type ElectronTestArgs = CommonTestArgs & { +type ElectronTestArgs = { electronApp: ElectronApplication; newWindow: () => Promise; }; -export const test = newTestType(); +export class ElectronEnv { + private _electronApp: ElectronApplication | undefined; + private _windows: Page[] = []; + protected _browserVersion: string; + + private async _newWindow() { + const [ window ] = await Promise.all([ + this._electronApp!.waitForEvent('window'), + this._electronApp!.evaluate(electron => { + const window = new electron.BrowserWindow({ + width: 800, + height: 600, + // Sandboxed windows share process with their window.open() children + // and can script them. We use that heavily in our tests. + webPreferences: { sandbox: true } + }); + window.loadURL('about:blank'); + }) + ]); + this._windows.push(window); + return window; + } + + async beforeAll() { + // This env prevents 'Electron Security Policy' console message. + process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; + this._browserVersion = require('electron/package.json').version; + return {}; + } + + async beforeEach(args: CommonTestArgs, testInfo: folio.TestInfo): Promise { + this._electronApp = await args.playwright._electron.launch({ + args: [path.join(__dirname, 'electron-app.js')], + }); + testInfo.data.browserVersion = this._browserVersion; + return { + electronApp: this._electronApp, + newWindow: this._newWindow.bind(this), + }; + } + + async afterEach({}, testInfo: folio.TestInfo) { + for (const window of this._windows) + await window.close(); + this._windows = []; + if (this._electronApp) { + await this._electronApp.close(); + this._electronApp = undefined; + } + } +} + +export const electronTest = baseTest.extend(new ElectronEnv()); diff --git a/tests/config/pageTest.ts b/tests/config/pageTest.ts index ee9c1c1041875a..21bef6558d94e4 100644 --- a/tests/config/pageTest.ts +++ b/tests/config/pageTest.ts @@ -14,36 +14,14 @@ * limitations under the License. */ -import { newTestType } from 'folio'; +import { test as baseTest } from './baseTest'; import type { Page } from '../../index'; -import type { ServerTestArgs } from './serverTest'; export { expect } from 'folio'; -export type CommonTestArgs = { - mode: 'default' | 'driver' | 'service'; - platform: 'win32' | 'darwin' | 'linux'; - video: boolean; - headful: boolean; - - playwright: typeof import('../../index'); - toImpl: (rpcObject: any) => any; - browserName: 'chromium' | 'firefox' | 'webkit'; - browserChannel: string | undefined; - - isChromium: boolean; - isFirefox: boolean; - isWebKit: boolean; - isAndroid: boolean; - isElectron: boolean; - isWindows: boolean; - isMac: boolean; - isLinux: boolean; -}; - // Page test does not guarantee an isolated context, just a new page (because Android). -export type PageTestArgs = CommonTestArgs & { +export type PageTestArgs = { browserVersion: string; page: Page; }; -export const test = newTestType(); +export const test = baseTest.declare(); diff --git a/tests/config/playwrightTest.ts b/tests/config/playwrightTest.ts deleted file mode 100644 index e13452b4334724..00000000000000 --- a/tests/config/playwrightTest.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { newTestType } from 'folio'; -import type { BrowserType, LaunchOptions, BrowserContext, Page } from '../../index'; -import { CommonTestArgs } from './pageTest'; -import type { ServerTestArgs } from './serverTest'; -import { RemoteServer, RemoteServerOptions } from './remoteServer'; -export { expect } from 'folio'; - -export type PlaywrightTestArgs = CommonTestArgs & { - browserType: BrowserType; - browserOptions: LaunchOptions; - createUserDataDir: () => Promise; - launchPersistent: (options?: Parameters[1]) => Promise<{ context: BrowserContext, page: Page }>; - startRemoteServer: (options?: RemoteServerOptions) => Promise; -}; - -export const test = newTestType(); -export const slowTest = newTestType(); diff --git a/tests/config/serverEnv.ts b/tests/config/serverEnv.ts deleted file mode 100644 index 9a9241ab983fe4..00000000000000 --- a/tests/config/serverEnv.ts +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { WorkerInfo, TestInfo, Env } from 'folio'; -import { TestServer } from '../../utils/testserver'; -import * as path from 'path'; -import socks from 'socksv5'; -import { ServerTestArgs } from './serverTest'; - -export class ServerEnv implements Env { - private _server: TestServer; - private _httpsServer: TestServer; - private _socksServer: any; - private _socksPort: number; - private _loopback: string | undefined; - - constructor(loopback?: string) { - this._loopback = loopback; - } - - async beforeAll(workerInfo: WorkerInfo) { - const assetsPath = path.join(__dirname, '..', 'assets'); - const cachedPath = path.join(__dirname, '..', 'assets', 'cached'); - - const port = 8907 + workerInfo.workerIndex * 3; - this._server = await TestServer.create(assetsPath, port, this._loopback); - this._server.enableHTTPCache(cachedPath); - - const httpsPort = port + 1; - this._httpsServer = await TestServer.createHTTPS(assetsPath, httpsPort, this._loopback); - this._httpsServer.enableHTTPCache(cachedPath); - - this._socksServer = socks.createServer((info, accept, deny) => { - let socket; - if ((socket = accept(true))) { - // Catch and ignore ECONNRESET errors. - socket.on('error', () => {}); - const body = 'Served by the SOCKS proxy'; - socket.end([ - 'HTTP/1.1 200 OK', - 'Connection: close', - 'Content-Type: text/html', - 'Content-Length: ' + Buffer.byteLength(body), - '', - body - ].join('\r\n')); - } - }); - this._socksPort = port + 2; - this._socksServer.listen(this._socksPort, 'localhost'); - this._socksServer.useAuth(socks.auth.None()); - } - - async beforeEach(testInfo: TestInfo) { - this._server.reset(); - this._httpsServer.reset(); - return { - asset: (p: string) => path.join(__dirname, '..', 'assets', ...p.split('/')), - server: this._server, - httpsServer: this._httpsServer, - socksPort: this._socksPort, - }; - } - - async afterAll(workerInfo: WorkerInfo) { - await Promise.all([ - this._server.stop(), - this._httpsServer.stop(), - this._socksServer.close(), - ]); - } -} diff --git a/tests/config/serverTest.ts b/tests/config/serverTest.ts deleted file mode 100644 index f8e69b98767a60..00000000000000 --- a/tests/config/serverTest.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TestServer } from '../../utils/testserver'; - -export type ServerTestArgs = { - asset: (path: string) => string; - socksPort: number, - server: TestServer; - httpsServer: TestServer; -}; diff --git a/tests/css-parser.spec.ts b/tests/css-parser.spec.ts index b973d8831da970..33ba62aae3e5e2 100644 --- a/tests/css-parser.spec.ts +++ b/tests/css-parser.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; import { parseCSS, serializeSelector as serialize } from '../src/server/common/cssParser'; const parse = (selector: string) => { diff --git a/tests/defaultbrowsercontext-1.spec.ts b/tests/defaultbrowsercontext-1.spec.ts index 5d80a9142437be..c159f836fd9dcc 100644 --- a/tests/defaultbrowsercontext-1.spec.ts +++ b/tests/defaultbrowsercontext-1.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; import { verifyViewport } from './config/utils'; import fs from 'fs'; diff --git a/tests/defaultbrowsercontext-2.spec.ts b/tests/defaultbrowsercontext-2.spec.ts index cb1ff4674f76a1..2d194dc403f1d3 100644 --- a/tests/defaultbrowsercontext-2.spec.ts +++ b/tests/defaultbrowsercontext-2.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, slowTest, expect } from './config/playwrightTest'; +import { playwrightTest as it, slowPlaywrightTest as slowTest, expect } from './config/browserTest'; import fs from 'fs'; it('should support hasTouch option', async ({server, launchPersistent}) => { @@ -146,14 +146,14 @@ it('should throw if page argument is passed', async ({browserType, browserOption expect(error.message).toContain('can not specify page'); }); -it('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, browserOptions, server, createUserDataDir, toImpl, mode}) => { +it('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, browserOptions, server, createUserDataDir, toImpl, mode, isFirefox}) => { it.skip(mode !== 'default'); const userDataDir = await createUserDataDir(); const args = toImpl(browserType)._defaultArgs(browserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank'); const options = { ...browserOptions, - args: [...args, server.EMPTY_PAGE], + args: isFirefox ? [...args, '-new-tab', server.EMPTY_PAGE] : [...args, server.EMPTY_PAGE], ignoreDefaultArgs: true, }; const browserContext = await browserType.launchPersistentContext(userDataDir, options); diff --git a/tests/download.spec.ts b/tests/download.spec.ts index efb7d24688e6cf..0ab8f2790640ec 100644 --- a/tests/download.spec.ts +++ b/tests/download.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import fs from 'fs'; import path from 'path'; import util from 'util'; diff --git a/tests/downloads-path.spec.ts b/tests/downloads-path.spec.ts index 27112b9db2bcf9..11ff43c2d2ca86 100644 --- a/tests/downloads-path.spec.ts +++ b/tests/downloads-path.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; import fs from 'fs'; it.describe('downloads path', () => { diff --git a/tests/electron/electron-app.spec.ts b/tests/electron/electron-app.spec.ts index 0d37fb54beb916..a37c84c2e45333 100644 --- a/tests/electron/electron-app.spec.ts +++ b/tests/electron/electron-app.spec.ts @@ -15,7 +15,7 @@ */ import path from 'path'; -import { test, expect } from '../config/electronTest'; +import { electronTest as test, expect } from '../config/electronTest'; test('should fire close event', async ({ playwright }) => { const electronApp = await playwright._electron.launch({ diff --git a/tests/electron/electron-window.spec.ts b/tests/electron/electron-window.spec.ts index 3d9b889626b563..7fb4982a7acbb9 100644 --- a/tests/electron/electron-window.spec.ts +++ b/tests/electron/electron-window.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect } from '../config/electronTest'; +import { electronTest as test, expect } from '../config/electronTest'; test('should click the button', async ({newWindow, server}) => { const window = await newWindow(); diff --git a/tests/elementhandle-bounding-box.spec.ts b/tests/elementhandle-bounding-box.spec.ts index 4fbbe4a51ef933..4aa134a7b679f3 100644 --- a/tests/elementhandle-bounding-box.spec.ts +++ b/tests/elementhandle-bounding-box.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; it.beforeEach(async ({ isAndroid }) => { it.skip(isAndroid); diff --git a/tests/elementhandle-screenshot.spec.ts b/tests/elementhandle-screenshot.spec.ts index 53d751cb11528c..a06e848c78185c 100644 --- a/tests/elementhandle-screenshot.spec.ts +++ b/tests/elementhandle-screenshot.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import { verifyViewport } from './config/utils'; import {PNG} from 'pngjs'; import path from 'path'; diff --git a/tests/emulation-focus.spec.ts b/tests/emulation-focus.spec.ts index 92c3b5b6a68373..b7f66dd68b475e 100644 --- a/tests/emulation-focus.spec.ts +++ b/tests/emulation-focus.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import { attachFrame } from './config/utils'; it('should think that it is focused by default', async ({page}) => { diff --git a/tests/favicon.spec.ts b/tests/favicon.spec.ts index 1d66b65f8ffd08..f4a395c3a53420 100644 --- a/tests/favicon.spec.ts +++ b/tests/favicon.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it } from './config/contextTest'; +import { contextTest as it } from './config/browserTest'; it('should load svg favicon with prefer-color-scheme', async ({page, server, browserName, browserChannel, headful, asset}) => { it.skip(!headful && browserName !== 'firefox', 'headless browsers, except firefox, do not request favicons'); diff --git a/tests/firefox/launcher.spec.ts b/tests/firefox/launcher.spec.ts index 38105f4b3c11aa..adc7741d4478d4 100644 --- a/tests/firefox/launcher.spec.ts +++ b/tests/firefox/launcher.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from '../config/playwrightTest'; +import { playwrightTest as it, expect } from '../config/browserTest'; it('should pass firefox user preferences', async ({browserType, browserOptions, browserName}) => { it.skip(browserName !== 'firefox'); diff --git a/tests/frame-hierarchy.spec.ts b/tests/frame-hierarchy.spec.ts index 7752a080445aff..41c60ea7d64eb1 100644 --- a/tests/frame-hierarchy.spec.ts +++ b/tests/frame-hierarchy.spec.ts @@ -20,7 +20,7 @@ import { attachFrame, detachFrame } from './config/utils'; import type { Frame } from '../index'; function dumpFrames(frame: Frame, indentation: string = ''): string[] { - let description = frame.url().replace(/:\d{4}\//, ':/'); + let description = frame.url().replace(/:\d+\//, ':/'); if (frame.name()) description += ' (' + frame.name() + ')'; const result = [indentation + description]; diff --git a/tests/geolocation.spec.ts b/tests/geolocation.spec.ts index 66fc7b328726d7..298ca025ac17e2 100644 --- a/tests/geolocation.spec.ts +++ b/tests/geolocation.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should work', async ({server, contextFactory}) => { const context = await contextFactory(); diff --git a/tests/har.spec.ts b/tests/har.spec.ts index 50aab6b43718b3..f620045febf0fa 100644 --- a/tests/har.spec.ts +++ b/tests/har.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import fs from 'fs'; import type { BrowserContext, BrowserContextOptions } from '../index'; diff --git a/tests/headful.spec.ts b/tests/headful.spec.ts index 799e1414431a3d..0003c3e80e8581 100644 --- a/tests/headful.spec.ts +++ b/tests/headful.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, slowTest, expect } from './config/playwrightTest'; +import { playwrightTest as it, slowPlaywrightTest as slowTest, expect } from './config/browserTest'; it('should have default url when launching browser', async ({browserType, browserOptions, createUserDataDir}) => { const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...browserOptions, headless: false }); diff --git a/tests/ignorehttpserrors.spec.ts b/tests/ignorehttpserrors.spec.ts index 94e148d68d3efc..a684ae826351e3 100644 --- a/tests/ignorehttpserrors.spec.ts +++ b/tests/ignorehttpserrors.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should work', async ({browser, httpsServer}) => { let error = null; diff --git a/tests/interception.spec.ts b/tests/interception.spec.ts index 638dd73de33c48..ac36037243b7f5 100644 --- a/tests/interception.spec.ts +++ b/tests/interception.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import { globToRegex } from '../lib/client/clientHelper'; import vm from 'vm'; @@ -157,10 +157,10 @@ it('should work with regular expression passed from a different context', async }); it('should not break remote worker importScripts', async ({ page, server, isChromium, browserVersion }) => { - it.fail(isChromium && +browserVersion.split('.')[0] < 91); + it.fixme(isChromium && +browserVersion.split('.')[0] < 91); - await page.route('**', async request => { - await request.continue(); + await page.route('**', async route => { + await route.continue(); }); await page.goto(server.PREFIX + '/worker/worker-http-import.html'); await page.waitForSelector("#status:has-text('finished')"); diff --git a/tests/launcher.spec.ts b/tests/launcher.spec.ts index 8bba10a14e294f..fc267815e79caa 100644 --- a/tests/launcher.spec.ts +++ b/tests/launcher.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; it('should require top-level Errors', async ({}) => { const Errors = require('../lib/utils/errors.js'); diff --git a/tests/logger.spec.ts b/tests/logger.spec.ts index 919b5c780cb27b..2d58930e31fc6a 100644 --- a/tests/logger.spec.ts +++ b/tests/logger.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; it('should log', async ({browserType, browserOptions}) => { const log = []; diff --git a/tests/page-emulate-media.spec.ts b/tests/page-emulate-media.spec.ts index 5f5f211042b992..00f1fccb056ebd 100644 --- a/tests/page-emulate-media.spec.ts +++ b/tests/page-emulate-media.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import { attachFrame } from './config/utils'; it.beforeEach(async ({ isAndroid }) => { diff --git a/tests/page-event-crash.spec.ts b/tests/page-event-crash.spec.ts index 6812102c8f2750..d13d53346e8cf3 100644 --- a/tests/page-event-crash.spec.ts +++ b/tests/page-event-crash.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { test as it, expect, PageTestArgs } from './config/pageTest'; +import { test as it, expect } from './config/pageTest'; import * as os from 'os'; -function crash({ page, toImpl, browserName, platform, mode }: PageTestArgs) { +function crash({ page, toImpl, browserName, platform, mode }: any) { if (browserName === 'chromium') { page.goto('chrome://crash').catch(e => {}); } else if (browserName === 'webkit') { diff --git a/tests/page-goto.spec.ts b/tests/page-goto.spec.ts index 61f13b3ec8538e..e73b298529109d 100644 --- a/tests/page-goto.spec.ts +++ b/tests/page-goto.spec.ts @@ -18,7 +18,7 @@ import url from 'url'; import os from 'os'; import { test as it, expect } from './config/pageTest'; -import { slowTest } from './config/browserTest'; +import { slowBrowserTest as slowTest } from './config/browserTest'; import { expectedSSLError } from './config/utils'; it('should work', async ({page, server}) => { diff --git a/tests/page-in-context.spec.ts b/tests/page-in-context.spec.ts index 95961fa006a4b4..3491944dea8810 100644 --- a/tests/page-in-context.spec.ts +++ b/tests/page-in-context.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import { attachFrame } from './config/utils'; it('should not be visible in context.pages', async ({contextFactory}) => { diff --git a/tests/page-mouse.spec.ts b/tests/page-mouse.spec.ts index 5b63ca7422263e..351b2e404f03a7 100644 --- a/tests/page-mouse.spec.ts +++ b/tests/page-mouse.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; function dimensions() { const rect = document.querySelector('textarea').getBoundingClientRect(); diff --git a/tests/page-request-fulfill.spec.ts b/tests/page-request-fulfill.spec.ts index ab466a7ebc6990..7809a08db1f834 100644 --- a/tests/page-request-fulfill.spec.ts +++ b/tests/page-request-fulfill.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import fs from 'fs'; it('should work', async ({page, server}) => { diff --git a/tests/page-screenshot.spec.ts b/tests/page-screenshot.spec.ts index 3a8a5c35b598f1..d60f1c01b4994f 100644 --- a/tests/page-screenshot.spec.ts +++ b/tests/page-screenshot.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest, slowTest as slowBrowserTest } from './config/browserTest'; +import { browserTest, slowBrowserTest } from './config/browserTest'; import { verifyViewport } from './config/utils'; import path from 'path'; import fs from 'fs'; diff --git a/tests/pause.spec.ts b/tests/pause.spec.ts index cdaeaafcd6f2ed..f0b9bfc3e48c21 100644 --- a/tests/pause.spec.ts +++ b/tests/pause.spec.ts @@ -15,7 +15,7 @@ */ import { Page } from '../index'; -import { test as it, expect } from './config/cliTest'; +import { cliTest as it, expect } from './config/cliTest'; it.describe('pause', () => { it.beforeEach(async ({ mode }) => { diff --git a/tests/pdf.spec.ts b/tests/pdf.spec.ts index c126d5ac42db7f..d184f6ba487829 100644 --- a/tests/pdf.spec.ts +++ b/tests/pdf.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import fs from 'fs'; it('should be able to save file', async ({contextFactory, headful, browserName}, testInfo) => { diff --git a/tests/permissions.spec.ts b/tests/permissions.spec.ts index 34113e39db6dbb..dbbf1aa36f0c66 100644 --- a/tests/permissions.spec.ts +++ b/tests/permissions.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; function getPermission(page, name) { return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name); diff --git a/tests/popup.spec.ts b/tests/popup.spec.ts index 6e56207f32bbd6..aee788d820a9c5 100644 --- a/tests/popup.spec.ts +++ b/tests/popup.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should inherit user agent from browser context', async function({browser, server}) { const context = await browser.newContext({ diff --git a/tests/proxy.spec.ts b/tests/proxy.spec.ts index ddb8b6da35a286..2b1323f783ebf8 100644 --- a/tests/proxy.spec.ts +++ b/tests/proxy.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/playwrightTest'; +import { playwrightTest as it, expect } from './config/browserTest'; import net from 'net'; it('should throw for bad server value', async ({browserType, browserOptions}) => { diff --git a/tests/resource-timing.spec.ts b/tests/resource-timing.spec.ts index 0c3c79d4c10678..71c5a91d0b4864 100644 --- a/tests/resource-timing.spec.ts +++ b/tests/resource-timing.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should work', async ({ contextFactory, server }) => { const context = await contextFactory(); diff --git a/tests/screencast.spec.ts b/tests/screencast.spec.ts index bd32f04db08e6a..3bc0d169e4d5ba 100644 --- a/tests/screencast.spec.ts +++ b/tests/screencast.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { slowTest as it, expect } from './config/browserTest'; +import { slowBrowserTest as it, expect } from './config/browserTest'; import fs from 'fs'; import path from 'path'; import { spawnSync } from 'child_process'; diff --git a/tests/selector-generator.spec.ts b/tests/selector-generator.spec.ts index 7e246c4a4b47a2..ce06b91e4d7c2a 100644 --- a/tests/selector-generator.spec.ts +++ b/tests/selector-generator.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; import type { Page, Frame } from '../index'; async function generate(pageOrFrame: Page | Frame, target: string): Promise { diff --git a/tests/selectors-register.spec.ts b/tests/selectors-register.spec.ts index 53df13d9b7ab64..ae388e28c830a5 100644 --- a/tests/selectors-register.spec.ts +++ b/tests/selectors-register.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; it('should work', async ({playwright, browser}) => { const createTagSelector = () => ({ diff --git a/tests/signals.spec.ts b/tests/signals.spec.ts index 2095c4db1733b7..8d7f2d6dfbcd13 100644 --- a/tests/signals.spec.ts +++ b/tests/signals.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { slowTest as test, expect } from './config/playwrightTest'; +import { slowPlaywrightTest as test, expect } from './config/browserTest'; import { execSync } from 'child_process'; test('should close the browser when the node process closes', async ({startRemoteServer, isWindows, server}) => { diff --git a/tests/snapshotter.spec.ts b/tests/snapshotter.spec.ts index 04d2d4adaa464f..b98e3e41635778 100644 --- a/tests/snapshotter.spec.ts +++ b/tests/snapshotter.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/contextTest'; +import { contextTest as it, expect } from './config/browserTest'; import { InMemorySnapshotter } from '../lib/server/snapshot/inMemorySnapshotter'; import { HttpServer } from '../lib/utils/httpServer'; import { SnapshotServer } from '../lib/server/snapshot/snapshotServer'; diff --git a/tests/stack-trace.spec.ts b/tests/stack-trace.spec.ts index e490b1da736289..58ecc3ca3572e7 100644 --- a/tests/stack-trace.spec.ts +++ b/tests/stack-trace.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test, expect } from './config/playwrightTest'; +import { playwrightTest as test, expect } from './config/browserTest'; import path from 'path'; import * as stackTrace from '../src/utils/stackTrace'; import { setUnderTest } from '../src/utils/utils'; diff --git a/tests/tap.spec.ts b/tests/tap.spec.ts index 925bcca26ff31b..03f23a49149aa7 100644 --- a/tests/tap.spec.ts +++ b/tests/tap.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { browserTest as it, expect } from './config/browserTest'; import { ElementHandle, Page } from '../index'; import type { ServerResponse } from 'http'; diff --git a/tests/workers.spec.ts b/tests/workers.spec.ts index adbd22ed22524f..99eab154b7e5af 100644 --- a/tests/workers.spec.ts +++ b/tests/workers.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './config/pageTest'; -import { test as browserTest } from './config/browserTest'; +import { browserTest } from './config/browserTest'; import { attachFrame } from './config/utils'; import type { ConsoleMessage } from '../index';