From 109688a066a3168177b0244534b0d35dcd6161a9 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Sat, 26 Sep 2020 16:05:58 -0700 Subject: [PATCH] chore: split playwright.fixtures into files (6) (#3988) --- test/accessibility.spec.ts | 16 +- test/autowaiting-basic.spec.ts | 6 +- test/browsercontext-cookies.spec.ts | 10 +- test/browsercontext-credentials.spec.ts | 10 +- test/browsercontext-device.spec.ts | 6 +- test/browsercontext-page-event.spec.ts | 12 +- test/browsercontext-viewport-mobile.spec.ts | 10 +- test/browsertype-connect.spec.ts | 5 +- test/browsertype-launch-server.spec.ts | 6 +- test/browsertype-launch.spec.ts | 18 +- test/capabilities.spec.ts | 10 +- test/channels.spec.ts | 6 +- test/chromium-css-coverage.spec.ts | 6 +- test/chromium-js-coverage.spec.ts | 10 +- test/chromium/chromium.spec.ts | 6 +- test/chromium/launcher.spec.ts | 22 +- test/chromium/oopif.spec.ts | 12 +- test/chromium/session.spec.ts | 6 +- test/chromium/tracing.spec.ts | 6 +- test/click-timeout-1.spec.ts | 6 +- test/click-timeout-3.spec.ts | 6 +- test/click.spec.ts | 14 +- test/defaultbrowsercontext-2.spec.ts | 44 ++-- test/dialog.spec.ts | 6 +- test/download.spec.ts | 17 +- test/electron/electron-app.spec.ts | 5 +- test/electron/electron-window.spec.ts | 5 +- test/elementhandle-bounding-box.spec.ts | 10 +- test/elementhandle-owner-frame.spec.ts | 6 +- test/elementhandle-screenshot.spec.ts | 28 +-- ...ementhandle-wait-for-element-state.spec.ts | 6 +- test/emulation-focus.spec.ts | 6 +- test/firefox/launcher.spec.ts | 6 +- test/fixtures.spec.ts | 5 +- test/fixtures.ts | 35 ++-- test/focus.spec.ts | 10 +- test/frame-evaluate.spec.ts | 20 +- test/frame-hierarchy.spec.ts | 6 +- test/headful.spec.ts | 12 +- test/keyboard.spec.ts | 14 +- test/mouse.spec.ts | 10 +- test/network-request.spec.ts | 6 +- test/page-add-script-tag.spec.ts | 6 +- test/page-basic.spec.ts | 6 +- test/page-evaluate.spec.ts | 28 +-- test/page-event-crash.spec.ts | 14 +- test/page-event-pageerror.spec.ts | 14 +- test/page-fill.spec.ts | 16 +- test/page-goto.spec.ts | 8 +- test/page-history.spec.ts | 6 +- test/page-screenshot.spec.ts | 28 +-- test/pdf.spec.ts | 10 +- test/permissions.spec.ts | 22 +- test/platform.fixtures.ts | 6 - test/playwright.fixtures.ts | 189 ++++++++++++------ test/proxy.spec.ts | 10 +- test/request-fulfill.spec.ts | 10 +- test/screencast.spec.ts | 12 +- test/slowmo.spec.ts | 6 +- 59 files changed, 450 insertions(+), 407 deletions(-) diff --git a/test/accessibility.spec.ts b/test/accessibility.spec.ts index 6120b3cca3772..262d36c9127df 100644 --- a/test/accessibility.spec.ts +++ b/test/accessibility.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; it('should work', async ({ page, isFirefox, isChromium }) => { await page.setContent(` @@ -139,8 +139,8 @@ it('should not report text nodes inside controls', async function({page, isFiref expect(await page.accessibility.snapshot()).toEqual(golden); }); -it('rich text editable fields should have children', (test, parameters) => { - test.skip(options.WEBKIT(parameters), 'WebKit rich text accessibility is iffy'); +it('rich text editable fields should have children', (test, { browserName }) => { + test.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); }, async function({page, isFirefox}) { await page.setContent(`
@@ -172,8 +172,8 @@ it('rich text editable fields should have children', (test, parameters) => { expect(snapshot.children[0]).toEqual(golden); }); -it('rich text editable fields with role should have children', (test, parameters) => { - test.skip(options.WEBKIT(parameters), 'WebKit rich text accessibility is iffy'); +it('rich text editable fields with role should have children', (test, { browserName }) => { + test.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); }, async function({page, isFirefox}) { await page.setContent(`
@@ -203,9 +203,9 @@ it('rich text editable fields with role should have children', (test, parameters expect(snapshot.children[0]).toEqual(golden); }); -describe('contenteditable', (suite, parameters) => { - suite.skip(options.FIREFOX(parameters), 'Firefox does not support contenteditable="plaintext-only"'); - suite.skip(options.WEBKIT(parameters), 'WebKit rich text accessibility is iffy'); +describe('contenteditable', (suite, { browserName }) => { + suite.skip(browserName === 'firefox', 'Firefox does not support contenteditable="plaintext-only"'); + suite.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); }, () => { it('plain text field with role should not have children', async function({page}) { await page.setContent(` diff --git a/test/autowaiting-basic.spec.ts b/test/autowaiting-basic.spec.ts index a86b3a21f8e04..204786f78415b 100644 --- a/test/autowaiting-basic.spec.ts +++ b/test/autowaiting-basic.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should await navigation when clicking anchor', async ({page, server}) => { const messages = []; @@ -201,8 +201,8 @@ it('should work with goto following click', async ({page, server}) => { await page.goto(server.EMPTY_PAGE); }); -it('should report navigation in the log when clicking anchor', (test, parameters) => { - test.skip(options.WIRE); +it('should report navigation in the log when clicking anchor', (test, { wire }) => { + test.skip(wire); }, async ({page, server}) => { await page.setContent(`click me`); const __testHookAfterPointerAction = () => new Promise(f => setTimeout(f, 6000)); diff --git a/test/browsercontext-cookies.spec.ts b/test/browsercontext-cookies.spec.ts index f71356e621e37..81504c42b2dc6 100644 --- a/test/browsercontext-cookies.spec.ts +++ b/test/browsercontext-cookies.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should return no cookies in pristine browser context', async ({context, page, server}) => { expect(await context.cookies()).toEqual([]); @@ -73,8 +73,8 @@ it('should properly report httpOnly cookie', async ({context, page, server}) => expect(cookies[0].httpOnly).toBe(true); }); -it('should properly report "Strict" sameSite cookie', (test, parameters) => { - test.fail(options.WEBKIT(parameters) && options.WIN(parameters)); +it('should properly report "Strict" sameSite cookie', (test, { browserName, platform }) => { + test.fail(browserName === 'webkit' && platform === 'win32'); }, async ({context, page, server}) => { server.setRoute('/empty.html', (req, res) => { res.setHeader('Set-Cookie', 'name=value;SameSite=Strict'); @@ -86,8 +86,8 @@ it('should properly report "Strict" sameSite cookie', (test, parameters) => { expect(cookies[0].sameSite).toBe('Strict'); }); -it('should properly report "Lax" sameSite cookie', (test, parameters) => { - test.fail(options.WEBKIT(parameters) && options.WIN(parameters)); +it('should properly report "Lax" sameSite cookie', (test, { browserName, platform }) => { + test.fail(browserName === 'webkit' && platform === 'win32'); }, async ({context, page, server}) => { server.setRoute('/empty.html', (req, res) => { res.setHeader('Set-Cookie', 'name=value;SameSite=Lax'); diff --git a/test/browsercontext-credentials.spec.ts b/test/browsercontext-credentials.spec.ts index 84917b6a4ae91..711835dcd3036 100644 --- a/test/browsercontext-credentials.spec.ts +++ b/test/browsercontext-credentials.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; -it('should fail without credentials', (test, parameters) => { - test.fail(options.CHROMIUM(parameters) && !options.HEADLESS); +it('should fail without credentials', (test, { browserName, headful}) => { + test.fail(browserName === 'chromium' && headful); }, async ({browser, server}) => { server.setAuth('/empty.html', 'user', 'pass'); const context = await browser.newContext(); @@ -28,8 +28,8 @@ it('should fail without credentials', (test, parameters) => { await context.close(); }); -it('should work with setHTTPCredentials', (test, parameters) => { - test.fail(options.CHROMIUM(parameters) && !options.HEADLESS); +it('should work with setHTTPCredentials', (test, { browserName, headful }) => { + test.fail(browserName === 'chromium' && headful); }, async ({browser, server}) => { server.setAuth('/empty.html', 'user', 'pass'); const context = await browser.newContext(); diff --git a/test/browsercontext-device.spec.ts b/test/browsercontext-device.spec.ts index 22e7111610f5f..6b6e2170a5e14 100644 --- a/test/browsercontext-device.spec.ts +++ b/test/browsercontext-device.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; -describe('device', (suite, parameters) => { - suite.skip(options.FIREFOX(parameters)); +describe('device', (suite, { browserName }) => { + suite.skip(browserName === 'firefox'); }, () => { it('should work', async ({playwright, browser, server}) => { const iPhone = playwright.devices['iPhone 6']; diff --git a/test/browsercontext-page-event.spec.ts b/test/browsercontext-page-event.spec.ts index 0db153b64ec0a..27cce17ae22d0 100644 --- a/test/browsercontext-page-event.spec.ts +++ b/test/browsercontext-page-event.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should have url', async ({browser, server}) => { const context = await browser.newContext(); @@ -157,8 +157,8 @@ it('should fire page lifecycle events', async function({browser, server}) { await context.close(); }); -it('should work with Shift-clicking', (test, parameters) => { - test.fixme(options.WEBKIT(parameters), 'WebKit: Shift+Click does not open a new window.'); +it('should work with Shift-clicking', (test, { browserName }) => { + test.fixme(browserName === 'webkit', 'WebKit: Shift+Click does not open a new window.'); }, async ({browser, server}) => { const context = await browser.newContext(); const page = await context.newPage(); @@ -172,9 +172,9 @@ it('should work with Shift-clicking', (test, parameters) => { await context.close(); }); -it('should work with Ctrl-clicking', (test, parameters) => { - test.fixme(options.WEBKIT(parameters), 'Ctrl+Click does not open a new tab.'); - test.fixme(options.FIREFOX(parameters), 'Reports an opener in this case.'); +it('should work with Ctrl-clicking', (test, { browserName }) => { + test.fixme(browserName === 'webkit', 'Ctrl+Click does not open a new tab.'); + test.fixme(browserName === 'firefox', 'Reports an opener in this case.'); }, async ({browser, server, isMac}) => { const context = await browser.newContext(); const page = await context.newPage(); diff --git a/test/browsercontext-viewport-mobile.spec.ts b/test/browsercontext-viewport-mobile.spec.ts index 5d2f6ac4ff776..a5ea4be5038bb 100644 --- a/test/browsercontext-viewport-mobile.spec.ts +++ b/test/browsercontext-viewport-mobile.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; -describe('mobile viewport', (suite, parameters) => { - suite.skip(options.FIREFOX(parameters)); +describe('mobile viewport', (suite, { browserName }) => { + suite.skip(browserName === 'firefox'); }, () => { it('should support mobile emulation', async ({playwright, browser, server}) => { const iPhone = playwright.devices['iPhone 6']; @@ -131,8 +131,8 @@ describe('mobile viewport', (suite, parameters) => { await context.close(); }); - it('should emulate the hover media feature', (test, parameters) => { - test.fail(options.WEBKIT(parameters)); + it('should emulate the hover media feature', (test, { browserName }) => { + test.fail(browserName === 'webkit'); }, async ({playwright, browser}) => { const iPhone = playwright.devices['iPhone 6']; const mobilepage = await browser.newPage({ ...iPhone }); diff --git a/test/browsertype-connect.spec.ts b/test/browsertype-connect.spec.ts index f856a9c08e6f0..7aa2ed0029b5d 100644 --- a/test/browsertype-connect.spec.ts +++ b/test/browsertype-connect.spec.ts @@ -15,12 +15,11 @@ * limitations under the License. */ -import { options } from './fixtures'; import { serverFixtures } from './remoteServer.fixture'; const { it, expect, describe } = serverFixtures; -describe('connect', suite => { - suite.skip(options.WIRE); +describe('connect', (suite, { wire }) => { + suite.skip(wire); suite.slow(); }, () => { it('should be able to reconnect to a browser', async ({browserType, remoteServer, server}) => { diff --git a/test/browsertype-launch-server.spec.ts b/test/browsertype-launch-server.spec.ts index d90a080fb0dcc..86e4365a76ec8 100644 --- a/test/browsertype-launch-server.spec.ts +++ b/test/browsertype-launch-server.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; -describe('lauch server', suite => { - suite.skip(options.WIRE); +describe('lauch server', (suite, { wire }) => { + suite.skip(wire); }, () => { it('should work', async ({browserType, defaultBrowserOptions}) => { const browserServer = await browserType.launchServer(defaultBrowserOptions); diff --git a/test/browsertype-launch.spec.ts b/test/browsertype-launch.spec.ts index 0a8769b141088..3eb13c06b4958 100644 --- a/test/browsertype-launch.spec.ts +++ b/test/browsertype-launch.spec.ts @@ -16,7 +16,7 @@ */ import path from 'path'; -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should reject all promises when browser is closed', async ({browserType, defaultBrowserOptions}) => { const browser = await browserType.launch(defaultBrowserOptions); @@ -48,8 +48,8 @@ it('should throw if port option is passed for persistent context', async ({brows expect(error.message).toContain('Cannot specify a port without launching as a server.'); }); -it('should throw if page argument is passed', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); +it('should throw if page argument is passed', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browserType, defaultBrowserOptions}) => { let waitError = null; const options = Object.assign({}, defaultBrowserOptions, { args: ['http://example.com'] }); @@ -73,8 +73,8 @@ it('should reject if executable path is invalid', async ({browserType, defaultBr expect(waitError.message).toContain('Failed to launch'); }); -it('should handle timeout', (test, parameters) => { - test.skip(options.WIRE); +it('should handle timeout', (test, { wire }) => { + test.skip(wire); }, async ({browserType, defaultBrowserOptions}) => { const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) }; const error = await browserType.launch(options).catch(e => e); @@ -83,8 +83,8 @@ it('should handle timeout', (test, parameters) => { expect(error.message).toContain(` pid=`); }); -it('should handle exception', (test, parameters) => { - test.skip(options.WIRE); +it('should handle exception', (test, { wire }) => { + test.skip(wire); }, async ({browserType, defaultBrowserOptions}) => { const e = new Error('Dummy'); const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; @@ -92,8 +92,8 @@ it('should handle exception', (test, parameters) => { expect(error.message).toContain('Dummy'); }); -it('should report launch log', (test, parameters) => { - test.skip(options.WIRE); +it('should report launch log', (test, { wire }) => { + test.skip(wire); }, async ({browserType, defaultBrowserOptions}) => { const e = new Error('Dummy'); const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; diff --git a/test/capabilities.spec.ts b/test/capabilities.spec.ts index ef2c1cfde80db..0a3aca9a0eb8f 100644 --- a/test/capabilities.spec.ts +++ b/test/capabilities.spec.ts @@ -15,10 +15,10 @@ */ import url from 'url'; -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; -it('Web Assembly should work', (test, parameters) => { - test.fail(options.WEBKIT(parameters) && options.WIN(parameters)); +it('Web Assembly should work', (test, { browserName, platform }) => { + test.fail(browserName === 'webkit' && platform === 'win32'); }, async function({page, server}) { await page.goto(server.PREFIX + '/wasm/table2.html'); expect(await page.evaluate('loadTable()')).toBe('42, 83'); @@ -50,8 +50,8 @@ it('should respect CSP', async ({page, server}) => { expect(await page.evaluate(() => window['testStatus'])).toBe('SUCCESS'); }); -it('should play video', (test, parameters) => { - test.fixme(options.WEBKIT(parameters) && (options.WIN(parameters) || options.LINUX(parameters))); +it('should play video', (test, { browserName, platform }) => { + test.fixme(browserName === 'webkit' && (platform !== 'darwin')); }, async ({page, asset, isWebKit}) => { // TODO: the test passes on Windows locally but fails on GitHub Action bot, // apparently due to a Media Pack issue in the Windows Server. diff --git a/test/channels.spec.ts b/test/channels.spec.ts index 6644db98d5874..fc1b1abfdf0f1 100644 --- a/test/channels.spec.ts +++ b/test/channels.spec.ts @@ -16,7 +16,7 @@ */ import domain from 'domain'; -import { options, fixtures as baseFixtures } from './fixtures'; +import { fixtures as baseFixtures } from './fixtures'; import type { ChromiumBrowser } from '..'; type DomainFixtures = { @@ -84,8 +84,8 @@ it('should scope context handles', async ({browserType, browser, server}) => { await expectScopeState(browser, GOLDEN_PRECONDITION); }); -it('should scope CDPSession handles', (test, parameters) => { - test.skip(!options.CHROMIUM(parameters)); +it('should scope CDPSession handles', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); }, async ({browserType, browser}) => { const GOLDEN_PRECONDITION = { _guid: '', diff --git a/test/chromium-css-coverage.spec.ts b/test/chromium-css-coverage.spec.ts index 3d25dfff1ba66..d976266128be4 100644 --- a/test/chromium-css-coverage.spec.ts +++ b/test/chromium-css-coverage.spec.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; -describe('oopif', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('oopif', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should work', async function({browserType, page, server}) { await page.coverage.startCSSCoverage(); diff --git a/test/chromium-js-coverage.spec.ts b/test/chromium-js-coverage.spec.ts index 98b02560fbbff..ddb1c23d34089 100644 --- a/test/chromium-js-coverage.spec.ts +++ b/test/chromium-js-coverage.spec.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; -it('should be missing', (test, parameters) => { - test.skip(options.CHROMIUM(parameters)); +it('should be missing', (test, { browserName }) => { + test.skip(browserName === 'chromium'); }, async function({page}) { expect(page.coverage).toBe(null); }); -describe('oopif', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('oopif', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should work', async function({page, server}) { await page.coverage.startJSCoverage(); diff --git a/test/chromium/chromium.spec.ts b/test/chromium/chromium.spec.ts index 25153b35f4d30..01ac984d1ac96 100644 --- a/test/chromium/chromium.spec.ts +++ b/test/chromium/chromium.spec.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { it, expect, describe, options } from '../fixtures'; +import { it, expect, describe } from '../fixtures'; import type { ChromiumBrowserContext } from '../..'; -describe('chromium', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('chromium', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should create a worker from a service worker', async ({page, server, context}) => { const [worker] = await Promise.all([ diff --git a/test/chromium/launcher.spec.ts b/test/chromium/launcher.spec.ts index 449310abdfe84..de044a5926cee 100644 --- a/test/chromium/launcher.spec.ts +++ b/test/chromium/launcher.spec.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { it, expect, options } from '../fixtures'; +import { it, expect } from '../fixtures'; import path from 'path'; import type { ChromiumBrowser, ChromiumBrowserContext } from '../..'; -it('should throw with remote-debugging-pipe argument', (test, parameters) => { - test.skip(options.WIRE || !options.CHROMIUM(parameters)); +it('should throw with remote-debugging-pipe argument', (test, { browserName, wire }) => { + test.skip(wire || browserName !== 'chromium'); }, async ({browserType, defaultBrowserOptions}) => { const options = Object.assign({}, defaultBrowserOptions); options.args = ['--remote-debugging-pipe'].concat(options.args || []); @@ -27,8 +27,8 @@ it('should throw with remote-debugging-pipe argument', (test, parameters) => { expect(error.message).toContain('Playwright manages remote debugging connection itself'); }); -it('should not throw with remote-debugging-port argument', (test, parameters) => { - test.skip(options.WIRE || !options.CHROMIUM(parameters)); +it('should not throw with remote-debugging-port argument', (test, { browserName, wire }) => { + test.skip(wire || browserName !== 'chromium'); }, async ({browserType, defaultBrowserOptions}) => { const options = Object.assign({}, defaultBrowserOptions); options.args = ['--remote-debugging-port=0'].concat(options.args || []); @@ -36,8 +36,8 @@ it('should not throw with remote-debugging-port argument', (test, parameters) => await browser.close(); }); -it('should open devtools when "devtools: true" option is given', (test, parameters) => { - test.skip(!options.CHROMIUM(parameters) || options.WIRE || options.WIN(parameters)); +it('should open devtools when "devtools: true" option is given', (test, { wire, browserName, platform}) => { + test.skip(browserName !== 'chromium' || wire || platform === 'win32'); }, async ({browserType, defaultBrowserOptions}) => { let devtoolsCallback; const devtoolsPromise = new Promise(f => devtoolsCallback = f); @@ -54,8 +54,8 @@ it('should open devtools when "devtools: true" option is given', (test, paramete await browser.close(); }); -it('should return background pages', (test, parameters) => { - test.skip(!options.CHROMIUM(parameters)); +it('should return background pages', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); }, async ({browserType, defaultBrowserOptions, createUserDataDir}) => { const userDataDir = await createUserDataDir(); const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension'); @@ -77,8 +77,8 @@ it('should return background pages', (test, parameters) => { await context.close(); }); -it('should not create pages automatically', (test, parameters) => { - test.skip(!options.CHROMIUM(parameters)); +it('should not create pages automatically', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); }, async ({browserType, defaultBrowserOptions}) => { const browser = await browserType.launch(defaultBrowserOptions); const browserSession = await (browser as ChromiumBrowser).newBrowserCDPSession(); diff --git a/test/chromium/oopif.spec.ts b/test/chromium/oopif.spec.ts index af7c6e7209dc8..b6077c6c2ffdb 100644 --- a/test/chromium/oopif.spec.ts +++ b/test/chromium/oopif.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { options, fixtures as playwrightFixtures } from '../fixtures'; +import { fixtures as playwrightFixtures } from '../fixtures'; const { it, expect, describe, overrideWorkerFixture } = playwrightFixtures; overrideWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, test) => { @@ -26,8 +26,8 @@ overrideWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, te await browser.close(); }); -describe('oopif', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('oopif', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should report oopif frames', async function({browser, page, server}) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); @@ -68,9 +68,9 @@ describe('oopif', (suite, parameters) => { expect(await countOOPIFs(browser)).toBe(1); }); - it('should get the proper viewport', (test, parameters) => { - test.fixme(options.CHROMIUM(parameters)); - test.skip(!options.CHROMIUM(parameters)); + it('should get the proper viewport', (test, { browserName }) => { + test.fixme(browserName === 'chromium'); + test.skip(browserName !== 'chromium'); }, async ({browser, page, server}) => { expect(page.viewportSize()).toEqual({width: 1280, height: 720}); await page.goto(server.PREFIX + '/dynamic-oopif.html'); diff --git a/test/chromium/session.spec.ts b/test/chromium/session.spec.ts index 34eab2641dd43..4402a878bcc1b 100644 --- a/test/chromium/session.spec.ts +++ b/test/chromium/session.spec.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { it, expect, describe, options } from '../fixtures'; +import { it, expect, describe } from '../fixtures'; import type { ChromiumBrowserContext, ChromiumBrowser } from '../../types/types'; -describe('session', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('session', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should work', async function({page}) { const client = await (page.context() as ChromiumBrowserContext).newCDPSession(page); diff --git a/test/chromium/tracing.spec.ts b/test/chromium/tracing.spec.ts index f2734b3416611..68c2a5e51d557 100644 --- a/test/chromium/tracing.spec.ts +++ b/test/chromium/tracing.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { options, fixtures as playwrightFixtures } from '../fixtures'; +import { fixtures as playwrightFixtures } from '../fixtures'; import fs from 'fs'; import path from 'path'; import type { ChromiumBrowser } from '../..'; @@ -29,8 +29,8 @@ defineTestFixture('outputTraceFile', async ({testOutputDir}, test) => { await test(path.join(testOutputDir, `trace.json`)); }); -describe('oopif', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('oopif', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should output a trace', async ({browser, page, server, outputTraceFile}) => { await (browser as ChromiumBrowser).startTracing(page, {screenshots: true, path: outputTraceFile}); diff --git a/test/click-timeout-1.spec.ts b/test/click-timeout-1.spec.ts index 9278fe6e3742e..8d8c1f6eed144 100644 --- a/test/click-timeout-1.spec.ts +++ b/test/click-timeout-1.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; -it('should avoid side effects after timeout', (test, parameters) => { - test.skip(options.WIRE); +it('should avoid side effects after timeout', (test, { wire }) => { + test.skip(wire); }, async ({page, server}) => { await page.goto(server.PREFIX + '/input/button.html'); const error = await page.click('button', { timeout: 2000, __testHookBeforePointerAction: () => new Promise(f => setTimeout(f, 2500))} as any).catch(e => e); diff --git a/test/click-timeout-3.spec.ts b/test/click-timeout-3.spec.ts index f384ac8ee299e..d3c571223d3e9 100644 --- a/test/click-timeout-3.spec.ts +++ b/test/click-timeout-3.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; -it('should fail when element jumps during hit testing', (test, parameters) => { - test.skip(options.WIRE); +it('should fail when element jumps during hit testing', (test, { wire }) => { + test.skip(wire); }, async ({page}) => { await page.setContent(''); let clicked = false; diff --git a/test/click.spec.ts b/test/click.spec.ts index 2e4bd3db7e669..3b3ff68d9e2be 100644 --- a/test/click.spec.ts +++ b/test/click.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame } from './utils'; async function giveItAChanceToClick(page) { @@ -322,8 +322,8 @@ it('should click the button inside an iframe', async ({page, server}) => { expect(await frame.evaluate(() => window['result'])).toBe('Clicked'); }); -it('should click the button with fixed position inside an iframe', (test, parameters) => { - test.fixme(options.CHROMIUM(parameters) || options.WEBKIT(parameters)); +it('should click the button with fixed position inside an iframe', (test, { browserName }) => { + test.fixme(browserName === 'chromium' || browserName === 'webkit'); }, async ({page, server}) => { // @see https://github.com/GoogleChrome/puppeteer/issues/4110 // @see https://bugs.chromium.org/p/chromium/issues/detail?id=986390 @@ -403,9 +403,9 @@ it('should click a button in scrolling container with offset', async ({page, ser expect(await page.evaluate('offsetY')).toBe(isWebKit ? 1910 + 8 : 1910); }); -it('should click the button with offset with page scale', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); -}, async ({browser, server, isWebKit, isChromium}) => { +it('should click the button with offset with page scale', (test, { browserName }) => { + test.skip(browserName === 'firefox'); +}, async ({browser, server, isWebKit, isChromium, headful}) => { const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true }); const page = await context.newPage(); await page.goto(server.PREFIX + '/input/button.html'); @@ -420,7 +420,7 @@ it('should click the button with offset with page scale', (test, parameters) => if (isWebKit) { // WebKit rounds up during css -> dip -> css conversion. expected = { x: 29, y: 19 }; - } else if (isChromium && options.HEADLESS) { + } else if (isChromium && !headful) { // Headless Chromium rounds down during css -> dip -> css conversion. expected = { x: 27, y: 18 }; } diff --git a/test/defaultbrowsercontext-2.spec.ts b/test/defaultbrowsercontext-2.spec.ts index 1d4848eba34ea..2d0eaa6b0c8f1 100644 --- a/test/defaultbrowsercontext-2.spec.ts +++ b/test/defaultbrowsercontext-2.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import fs from 'fs'; it('should support hasTouch option', async ({server, launchPersistent}) => { @@ -24,8 +24,8 @@ it('should support hasTouch option', async ({server, launchPersistent}) => { expect(await page.evaluate(() => 'ontouchstart' in window)).toBe(true); }); -it('should work in persistent context', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); +it('should work in persistent context', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({server, launchPersistent}) => { // Firefox does not support mobile. const {page} = await launchPersistent({viewport: {width: 320, height: 480}, isMobile: true}); @@ -66,8 +66,8 @@ it('should support ignoreHTTPSErrors option', async ({httpsServer, launchPersist expect(response.ok()).toBe(true); }); -it('should support extraHTTPHeaders option', (test, parameters) => { - test.flaky(options.FIREFOX(parameters) && !options.HEADLESS && options.LINUX(parameters), 'Intermittent timeout on bots'); +it('should support extraHTTPHeaders option', (test, { browserName, platform, headful }) => { + test.flaky(browserName === 'firefox' && headful && platform === 'linux', 'Intermittent timeout on bots'); }, async ({server, launchPersistent}) => { const {page} = await launchPersistent({extraHTTPHeaders: { foo: 'bar' }}); const [request] = await Promise.all([ @@ -77,8 +77,8 @@ it('should support extraHTTPHeaders option', (test, parameters) => { expect(request.headers['foo']).toBe('bar'); }); -it('should accept userDataDir', (test, parameters) => { - test.flaky(options.CHROMIUM(parameters)); +it('should accept userDataDir', (test, { browserName }) => { + test.flaky(browserName === 'chromium'); }, async ({createUserDataDir, browserType, defaultBrowserOptions}) => { const userDataDir = await createUserDataDir(); const context = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); @@ -87,7 +87,7 @@ it('should accept userDataDir', (test, parameters) => { expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); }); -it('should restore state from userDataDir', (test, parameters) => { +it('should restore state from userDataDir', (test, { browserName }) => { test.slow(); }, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { const userDataDir = await createUserDataDir(); @@ -111,9 +111,9 @@ it('should restore state from userDataDir', (test, parameters) => { await browserContext3.close(); }); -it('should restore cookies from userDataDir', (test, parameters) => { +it('should restore cookies from userDataDir', (test, { browserName }) => { test.slow(); - test.flaky(options.CHROMIUM(parameters)); + test.flaky(browserName === 'chromium'); }, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { const userDataDir = await createUserDataDir(); const browserContext = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); @@ -146,16 +146,16 @@ it('should have default URL when launching browser', async ({launchPersistent}) expect(urls).toEqual(['about:blank']); }); -it('should throw if page argument is passed', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); +it('should throw if page argument is passed', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { const options = {...defaultBrowserOptions, args: [server.EMPTY_PAGE] }; const error = await browserType.launchPersistentContext(await createUserDataDir(), options).catch(e => e); expect(error.message).toContain('can not specify page'); }); -it('should have passed URL when launching with ignoreDefaultArgs: true', (test, parameters) => { - test.skip(options.WIRE); +it('should have passed URL when launching with ignoreDefaultArgs: true', (test, { wire }) => { + test.skip(wire); }, async ({browserType, defaultBrowserOptions, server, createUserDataDir, toImpl}) => { const userDataDir = await createUserDataDir(); const args = toImpl(browserType)._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank'); @@ -173,16 +173,16 @@ it('should have passed URL when launching with ignoreDefaultArgs: true', (test, await browserContext.close(); }); -it('should handle timeout', (test, parameters) => { - test.skip(options.WIRE); +it('should handle timeout', (test, { wire }) => { + test.skip(wire); }, async ({browserType, defaultBrowserOptions, createUserDataDir}) => { const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) }; const error = await browserType.launchPersistentContext(await createUserDataDir(), options).catch(e => e); expect(error.message).toContain(`browserType.launchPersistentContext: Timeout 5000ms exceeded.`); }); -it('should handle exception', (test, parameters) => { - test.skip(options.WIRE); +it('should handle exception', (test, { wire }) => { + test.skip(wire); }, async ({browserType, defaultBrowserOptions, createUserDataDir}) => { const e = new Error('Dummy'); const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; } }; @@ -198,8 +198,8 @@ it('should fire close event for a persistent context', async ({launchPersistent} expect(closed).toBe(true); }); -it('coverage should work', (test, parameters) => { - test.skip(!options.CHROMIUM(parameters)); +it('coverage should work', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); }, async ({server, launchPersistent}) => { const {page} = await launchPersistent(); await page.coverage.startJSCoverage(); @@ -210,8 +210,8 @@ it('coverage should work', (test, parameters) => { expect(coverage[0].functions.find(f => f.functionName === 'foo').ranges[0].count).toEqual(1); }); -it('coverage should be missing', (test, parameters) => { - test.skip(options.CHROMIUM(parameters)); +it('coverage should be missing', (test, { browserName }) => { + test.skip(browserName === 'chromium'); }, async ({launchPersistent}) => { const {page} = await launchPersistent(); expect(page.coverage).toBe(null); diff --git a/test/dialog.spec.ts b/test/dialog.spec.ts index a8ff4f2e227fa..3a8de60d0fff6 100644 --- a/test/dialog.spec.ts +++ b/test/dialog.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should fire', async ({page, server}) => { page.on('dialog', dialog => { @@ -62,8 +62,8 @@ it('should dismiss the confirm prompt', async ({page}) => { expect(result).toBe(false); }); -it('should be able to close context with open alert', (test, parameters) => { - test.fixme(options.WEBKIT(parameters) && options.MAC(parameters)); +it('should be able to close context with open alert', (test, { browserName, platform }) => { + test.fixme(browserName === 'webkit' && platform === 'darwin'); }, async ({browser}) => { const context = await browser.newContext(); const page = await context.newPage(); diff --git a/test/download.spec.ts b/test/download.spec.ts index f153d90e551eb..3f61462e25ed9 100644 --- a/test/download.spec.ts +++ b/test/download.spec.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { options } from './fixtures'; import { serverFixtures } from './remoteServer.fixture'; const { it, expect, beforeEach } = serverFixtures; @@ -145,8 +144,8 @@ it('should create subdirectories when saving to non-existent user-specified path await page.close(); }); -it('should save when connected remotely', (test, parameters) => { - test.skip(options.WIRE); +it('should save when connected remotely', (test, { wire }) => { + test.skip(wire); }, async ({testOutputDir, server, browserType, remoteServer}) => { const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); const page = await browser.newPage({ acceptDownloads: true }); @@ -191,8 +190,8 @@ it('should error when saving after deletion', async ({testOutputDir, browser, se await page.close(); }); -it('should error when saving after deletion when connected remotely', (test, parameters) => { - test.skip(options.WIRE); +it('should error when saving after deletion when connected remotely', (test, { wire }) => { + test.skip(wire); }, async ({testOutputDir, server, browserType, remoteServer}) => { const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); const page = await browser.newPage({ acceptDownloads: true }); @@ -255,8 +254,8 @@ it(`should report download path within page.on('download', …) handler for Blob expect(fs.readFileSync(path).toString()).toBe('Hello world'); await page.close(); }); -it('should report alt-click downloads', (test, parameters) => { - test.fixme(options.FIREFOX(parameters) || options.WEBKIT(parameters)); +it('should report alt-click downloads', (test, { browserName }) => { + test.fixme(browserName === 'firefox' || browserName === 'webkit'); }, async ({browser, server}) => { // Firefox does not download on alt-click by default. // Our WebKit embedder does not download on alt-click, although Safari does. @@ -278,8 +277,8 @@ it('should report alt-click downloads', (test, parameters) => { await page.close(); }); -it('should report new window downloads', (test, parameters) => { - test.fixme(options.CHROMIUM(parameters) && !options.HEADLESS); +it('should report new window downloads', (test, { browserName, headful }) => { + test.fixme(browserName === 'chromium' && headful); }, async ({browser, server}) => { // TODO: - the test fails in headful Chromium as the popup page gets closed along // with the session before download completed event arrives. diff --git a/test/electron/electron-app.spec.ts b/test/electron/electron-app.spec.ts index a71d08f650781..845cab4cdaf99 100644 --- a/test/electron/electron-app.spec.ts +++ b/test/electron/electron-app.spec.ts @@ -14,15 +14,14 @@ * limitations under the License. */ -import { options } from '../fixtures'; import { electronFixtures } from './electron.fixture'; const { it, expect, describe } = electronFixtures; import path from 'path'; const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron'; -describe('electron app', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('electron app', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should fire close event', async ({ playwright }) => { const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName); diff --git a/test/electron/electron-window.spec.ts b/test/electron/electron-window.spec.ts index 1fd4464239b7a..8f8d26595cddb 100644 --- a/test/electron/electron-window.spec.ts +++ b/test/electron/electron-window.spec.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import { options } from '../fixtures'; import { electronFixtures } from './electron.fixture'; const { it, expect, describe } = electronFixtures; -describe('electron window', (suite, parameters) => { - suite.skip(!options.CHROMIUM(parameters)); +describe('electron window', (suite, { browserName }) => { + suite.skip(browserName !== 'chromium'); }, () => { it('should click the button', async ({window, server}) => { await window.goto(server.PREFIX + '/input/button.html'); diff --git a/test/elementhandle-bounding-box.spec.ts b/test/elementhandle-bounding-box.spec.ts index edc06c3e8a0a3..1c954959b6374 100644 --- a/test/elementhandle-bounding-box.spec.ts +++ b/test/elementhandle-bounding-box.spec.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; -it('should work', (test, parameters) => { - test.fail(options.FIREFOX(parameters) && !options.HEADLESS); +it('should work', (test, { browserName, headful }) => { + test.fail(browserName === 'firefox' && headful); }, async ({ page, server }) => { await page.setViewportSize({ width: 500, height: 500 }); await page.goto(server.PREFIX + '/grid.html'); @@ -67,8 +67,8 @@ it('should work with SVG nodes', async ({ page, server }) => { expect(pwBoundingBox).toEqual(webBoundingBox); }); -it('should work with page scale', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); +it('should work with page scale', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({ browser, server }) => { const context = await browser.newContext({ viewport: { width: 400, height: 400 }, isMobile: true }); const page = await context.newPage(); diff --git a/test/elementhandle-owner-frame.spec.ts b/test/elementhandle-owner-frame.spec.ts index a4986230a0ac2..16b2c6ee08fae 100644 --- a/test/elementhandle-owner-frame.spec.ts +++ b/test/elementhandle-owner-frame.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame } from './utils'; it('should work', async ({ page, server }) => { @@ -34,8 +34,8 @@ it('should work for cross-process iframes', async ({ page, server }) => { expect(await elementHandle.ownerFrame()).toBe(frame); }); -it('should work for document', (test, parameters) => { - test.flaky(options.WIN(parameters) && options.WEBKIT(parameters)); +it('should work for document', (test, { browserName, platform }) => { + test.flaky(platform === 'win32' && browserName === 'webkit'); }, async ({ page, server }) => { await page.goto(server.EMPTY_PAGE); await attachFrame(page, 'frame1', server.EMPTY_PAGE); diff --git a/test/elementhandle-screenshot.spec.ts b/test/elementhandle-screenshot.spec.ts index 6ca1bdbbb7619..da62da7d73bde 100644 --- a/test/elementhandle-screenshot.spec.ts +++ b/test/elementhandle-screenshot.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; import { verifyViewport } from './utils'; import {PNG} from 'pngjs'; @@ -23,7 +23,7 @@ import path from 'path'; import fs from 'fs'; describe('element screenshot', (suite, parameters) => { - suite.skip(parameters.browserName === 'firefox' && !options.HEADLESS); + suite.skip(parameters.browserName === 'firefox' && parameters.headful); }, () => { it('should work', async ({page, server, golden}) => { await page.setViewportSize({width: 500, height: 500}); @@ -211,8 +211,8 @@ describe('element screenshot', (suite, parameters) => { expect(screenshot).toMatchImage(golden('screenshot-element-fractional.png')); }); - it('should work with a mobile viewport', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); + it('should work with a mobile viewport', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browser, server, golden}) => { const context = await browser.newContext({viewport: { width: 320, height: 480 }, isMobile: true}); const page = await context.newPage(); @@ -224,8 +224,8 @@ describe('element screenshot', (suite, parameters) => { await context.close(); }); - it('should work with device scale factor', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); + it('should work with device scale factor', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browser, server, golden}) => { const context = await browser.newContext({ viewport: { width: 320, height: 480 }, deviceScaleFactor: 2 }); const page = await context.newPage(); @@ -289,8 +289,8 @@ describe('element screenshot', (suite, parameters) => { await context.close(); }); - it('should restore viewport after page screenshot and exception', (test, parameters) => { - test.skip(options.WIRE); + it('should restore viewport after page screenshot and exception', (test, { wire }) => { + test.skip(wire); }, async ({ browser, server }) => { const context = await browser.newContext({ viewport: { width: 350, height: 360 } }); const page = await context.newPage(); @@ -302,8 +302,8 @@ describe('element screenshot', (suite, parameters) => { await context.close(); }); - it('should restore viewport after page screenshot and timeout', (test, parameters) => { - test.skip(options.WIRE); + it('should restore viewport after page screenshot and timeout', (test, { wire }) => { + test.skip(wire); }, async ({ browser, server }) => { const context = await browser.newContext({ viewport: { width: 350, height: 360 } }); const page = await context.newPage(); @@ -348,8 +348,8 @@ describe('element screenshot', (suite, parameters) => { await context.close(); }); - it('should restore viewport after element screenshot and exception', (test, parameters) => { - test.skip(options.WIRE); + it('should restore viewport after element screenshot and exception', (test, { wire }) => { + test.skip(wire); }, async ({browser}) => { const context = await browser.newContext({ viewport: { width: 350, height: 360 } }); const page = await context.newPage(); @@ -362,8 +362,8 @@ describe('element screenshot', (suite, parameters) => { await context.close(); }); - it('should wait for element to stop moving', (test, parameters) => { - test.flaky(options.WEBKIT(parameters) && !options.HEADLESS && options.LINUX(parameters)); + it('should wait for element to stop moving', (test, { browserName, headful, platform }) => { + test.flaky(browserName === 'webkit' && headful && platform === 'linux'); }, async ({ page, server, golden }) => { await page.setViewportSize({ width: 500, height: 500 }); await page.goto(server.PREFIX + '/grid.html'); diff --git a/test/elementhandle-wait-for-element-state.spec.ts b/test/elementhandle-wait-for-element-state.spec.ts index b7a2da0165670..dd88c9056ed8a 100644 --- a/test/elementhandle-wait-for-element-state.spec.ts +++ b/test/elementhandle-wait-for-element-state.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; async function giveItAChanceToResolve(page) { for (let i = 0; i < 5; i++) @@ -114,8 +114,8 @@ it('should wait for disabled button', async ({page}) => { await promise; }); -it('should wait for stable position', (test, parameters) => { - test.fixme(options.FIREFOX(parameters) && options.LINUX(parameters)); +it('should wait for stable position', (test, { browserName, platform }) => { + test.fixme(browserName === 'firefox' && platform === 'linux'); }, async ({page, server}) => { await page.goto(server.PREFIX + '/input/button.html'); const button = await page.$('button'); diff --git a/test/emulation-focus.spec.ts b/test/emulation-focus.spec.ts index 1398326bf3235..9f5d431821b3d 100644 --- a/test/emulation-focus.spec.ts +++ b/test/emulation-focus.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame } from './utils'; it('should think that it is focused by default', async ({page}) => { @@ -101,8 +101,8 @@ it('should change document.activeElement', async ({page, server}) => { expect(active).toEqual(['INPUT', 'TEXTAREA']); }); -it('should not affect screenshots', (test, parameters) => { - test.skip(options.FIREFOX(parameters) && !options.HEADLESS); +it('should not affect screenshots', (test, { browserName, headful }) => { + test.skip(browserName === 'firefox' && headful); }, async ({page, server, golden}) => { // Firefox headful produces a different image. const page2 = await page.context().newPage(); diff --git a/test/firefox/launcher.spec.ts b/test/firefox/launcher.spec.ts index e0744ff51249c..45977d09b3cf6 100644 --- a/test/firefox/launcher.spec.ts +++ b/test/firefox/launcher.spec.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { it, expect, options } from '../fixtures'; +import { it, expect } from '../fixtures'; -it('should pass firefox user preferences', (test, parameters) => { - test.skip(!options.FIREFOX(parameters)); +it('should pass firefox user preferences', (test, { browserName }) => { + test.skip(browserName !== 'firefox'); }, async ({browserType, defaultBrowserOptions}) => { const browser = await browserType.launch({ ...defaultBrowserOptions, diff --git a/test/fixtures.spec.ts b/test/fixtures.spec.ts index 8043a9b986391..55375687f2072 100644 --- a/test/fixtures.spec.ts +++ b/test/fixtures.spec.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { options } from './fixtures'; import { serverFixtures } from './remoteServer.fixture'; import { execSync } from 'child_process'; import path from 'path'; @@ -58,8 +57,8 @@ it('should close the browser when the node process closes', test => { // so we don't check it here. }); -describe('fixtures', (suite, parameters) => { - suite.skip(options.WIN(parameters) || !options.HEADLESS); +describe('fixtures', (suite, { platform, headful }) => { + suite.skip(platform === 'win32' || headful); suite.slow(); }, () => { // Cannot reliably send signals on Windows. diff --git a/test/fixtures.ts b/test/fixtures.ts index cdff300b24533..24782c1e65a72 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -26,15 +26,15 @@ import { Transport } from '../lib/protocol/transport'; import { installCoverageHooks } from './coverage'; import { fixtures as httpFixtures } from './http.fixtures'; import { fixtures as implFixtures } from './impl.fixtures'; -import { fixtures as platformFixtures, options as platformOptions } from './platform.fixtures'; -import { fixtures as playwrightFixtures, options as playwrightOptions } from './playwright.fixtures'; +import { fixtures as platformFixtures } from './platform.fixtures'; +import { fixtures as playwrightFixtures } from './playwright.fixtures'; export { expect } from '@playwright/test/out/matcher.fixtures'; export { config } from '@playwright/test-runner'; const removeFolderAsync = util.promisify(require('rimraf')); type AllParameters = { - browserName: string; + wire: boolean; }; type AllWorkerFixtures = { @@ -53,7 +53,6 @@ export const fixtures = playwrightFixtures .declareParameters() .declareWorkerFixtures() .declareTestFixtures(); -const { defineTestFixture, defineWorkerFixture, overrideWorkerFixture } = fixtures; export const it = fixtures.it; export const fit = fixtures.fit; @@ -66,11 +65,7 @@ export const afterEach = fixtures.afterEach; export const beforeAll = fixtures.beforeAll; export const afterAll = fixtures.afterAll; -export const options = { - ...platformOptions, - ...playwrightOptions, - WIRE: !!process.env.PWWIRE, -}; +fixtures.defineParameter('wire', 'Wire testing mode', !!process.env.PWWIRE || false); const getExecutablePath = browserName => { if (browserName === 'chromium' && process.env.CRPATH) @@ -81,23 +76,23 @@ const getExecutablePath = browserName => { return process.env.WKPATH; }; -overrideWorkerFixture('defaultBrowserOptions', async ({browserName}, runTest) => { +fixtures.overrideWorkerFixture('defaultBrowserOptions', async ({ browserName, headful, slowMo }, runTest) => { const executablePath = getExecutablePath(browserName); if (executablePath) console.error(`Using executable at ${executablePath}`); await runTest({ - handleSIGINT: false, - slowMo: options.SLOW_MO, - headless: options.HEADLESS, executablePath, + handleSIGINT: false, + slowMo, + headless: !headful, artifactsPath: config.outputDir, }); }); -overrideWorkerFixture('playwright', async ({browserName, testWorkerIndex, platform}, test) => { +fixtures.overrideWorkerFixture('playwright', async ({ browserName, testWorkerIndex, platform, wire }, runTest) => { assert(platform); // Depend on platform to generate all tests. const {coverage, uninstall} = installCoverageHooks(browserName); - if (options.WIRE) { + if (wire) { require('../lib/utils/utils').setUnderTest(); const connection = new Connection(); const spawnedProcess = childProcess.fork(path.join(__dirname, '..', 'lib', 'server.js'), [], { @@ -113,7 +108,7 @@ overrideWorkerFixture('playwright', async ({browserName, testWorkerIndex, platfo connection.onmessage = message => transport.send(JSON.stringify(message)); transport.onmessage = message => connection.dispatch(JSON.parse(message)); const playwrightObject = await connection.waitForObjectWithKnownName('Playwright'); - await test(playwrightObject); + await runTest(playwrightObject); spawnedProcess.removeListener('exit', onExit); spawnedProcess.stdin.destroy(); spawnedProcess.stdout.destroy(); @@ -121,7 +116,7 @@ overrideWorkerFixture('playwright', async ({browserName, testWorkerIndex, platfo await teardownCoverage(); } else { const playwright = require('../index'); - await test(playwright); + await runTest(playwright); await teardownCoverage(); } @@ -134,11 +129,11 @@ overrideWorkerFixture('playwright', async ({browserName, testWorkerIndex, platfo } }); -defineWorkerFixture('golden', async ({browserName}, test) => { +fixtures.defineWorkerFixture('golden', async ({browserName}, test) => { await test(p => path.join(browserName, p)); }); -defineTestFixture('createUserDataDir', async ({testOutputDir}, runTest) => { +fixtures.defineTestFixture('createUserDataDir', async ({testOutputDir}, runTest) => { let counter = 0; const dirs: string[] = []; async function createUserDataDir() { @@ -154,7 +149,7 @@ defineTestFixture('createUserDataDir', async ({testOutputDir}, runTest) => { await Promise.all(dirs.map(dir => removeFolderAsync(dir).catch(e => {}))); }); -defineTestFixture('launchPersistent', async ({createUserDataDir, defaultBrowserOptions, browserType}, test) => { +fixtures.defineTestFixture('launchPersistent', async ({createUserDataDir, defaultBrowserOptions, browserType}, test) => { let context; async function launchPersistent(options) { if (context) diff --git a/test/focus.spec.ts b/test/focus.spec.ts index 26f920f02f1eb..071d6a8854224 100644 --- a/test/focus.spec.ts +++ b/test/focus.spec.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; -it('should work', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); +it('should work', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async function({page}) { await page.setContent(`
`); expect(await page.evaluate(() => document.activeElement.nodeName)).toBe('BODY'); @@ -78,8 +78,8 @@ it('should traverse focus in all directions', async function({page}) { expect(await page.evaluate(() => (document.activeElement as HTMLInputElement).value)).toBe('1'); }); -it('should traverse only form elements', (test, parameters) => { - test.skip(!options.MAC(parameters) || !options.WEBKIT(parameters), +it('should traverse only form elements', (test, { browserName, platform }) => { + test.skip(platform !== 'darwin' || browserName !== 'webkit', 'Chromium and WebKit both have settings for tab traversing all links, but it is only on by default in WebKit.'); }, async function({page}) { await page.setContent(` diff --git a/test/frame-evaluate.spec.ts b/test/frame-evaluate.spec.ts index 584e4772e6b59..fe9da6368633c 100644 --- a/test/frame-evaluate.spec.ts +++ b/test/frame-evaluate.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame, detachFrame } from './utils'; import type { Frame } from '../src/client/frame'; @@ -44,8 +44,8 @@ function expectContexts(pageImpl, count, isChromium) { expect(pageImpl._delegate._contextIdToContext.size).toBe(count); } -it('should dispose context on navigation', test => { - test.skip(options.WIRE); +it('should dispose context on navigation', (test, { wire }) => { + test.skip(wire); }, async ({ page, server, toImpl, isChromium }) => { await page.goto(server.PREFIX + '/frames/one-frame.html'); expect(page.frames().length).toBe(2); @@ -54,8 +54,8 @@ it('should dispose context on navigation', test => { expectContexts(toImpl(page), 2, isChromium); }); -it('should dispose context on cross-origin navigation', (test, parameters) => { - test.skip(options.WIRE); +it('should dispose context on cross-origin navigation', (test, { wire }) => { + test.skip(wire); }, async ({ page, server, toImpl, isChromium }) => { await page.goto(server.PREFIX + '/frames/one-frame.html'); expect(page.frames().length).toBe(2); @@ -132,9 +132,9 @@ it('should be isolated between frames', async ({page, server}) => { expect(a2).toBe(2); }); -it('should work in iframes that failed initial navigation', (test, parameters) => { - test.fail(options.CHROMIUM(parameters)); - test.fixme(options.FIREFOX(parameters)); +it('should work in iframes that failed initial navigation', (test, { browserName }) => { + test.fail(browserName === 'chromium'); + test.fixme(browserName === 'firefox'); }, async ({page}) => { // - Firefox does not report domcontentloaded for the iframe. // - Chromium and Firefox report empty url. @@ -156,8 +156,8 @@ it('should work in iframes that failed initial navigation', (test, parameters) = expect(await page.frames()[1].$('div')).toBeTruthy(); }); -it('should work in iframes that interrupted initial javascript url navigation', (test, parameters) => { - test.fixme(options.CHROMIUM(parameters)); +it('should work in iframes that interrupted initial javascript url navigation', (test, { browserName }) => { + test.fixme(browserName === 'chromium'); }, async ({page, server}) => { // Chromium does not report isolated world for the iframe. await page.goto(server.EMPTY_PAGE); diff --git a/test/frame-hierarchy.spec.ts b/test/frame-hierarchy.spec.ts index bdb7b877511a7..2d365a2952f8c 100644 --- a/test/frame-hierarchy.spec.ts +++ b/test/frame-hierarchy.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame, detachFrame } from './utils'; import type { Frame } from '../index'; @@ -189,8 +189,8 @@ it('should report different frame instance when frame re-attaches', async ({page expect(frame1).not.toBe(frame2); }); -it('should refuse to display x-frame-options:deny iframe', (test, parameters) => { - test.fixme(options.FIREFOX(parameters)); +it('should refuse to display x-frame-options:deny iframe', (test, { browserName }) => { + test.fixme(browserName === 'firefox'); }, async ({page, server}) => { server.setRoute('/x-frame-options-deny.html', async (req, res) => { res.setHeader('Content-Type', 'text/html'); diff --git a/test/headful.spec.ts b/test/headful.spec.ts index fdcf91b7c4e8a..74020717b847f 100644 --- a/test/headful.spec.ts +++ b/test/headful.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should have default url when launching browser', async ({browserType, defaultBrowserOptions, createUserDataDir}) => { const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...defaultBrowserOptions, headless: false }); @@ -23,9 +23,9 @@ it('should have default url when launching browser', async ({browserType, defaul await browserContext.close(); }); -it('headless should be able to read cookies written by headful', (test, parameters) => { - test.fail(options.WIN(parameters) && options.CHROMIUM(parameters)); - test.flaky(options.FIREFOX(parameters)); +it('headless should be able to read cookies written by headful', (test, { browserName, platform }) => { + test.fail(platform === 'win32' && browserName === 'chromium'); + test.flaky(browserName === 'firefox'); test.slow(); }, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { // see https://github.com/microsoft/playwright/issues/717 @@ -129,8 +129,8 @@ it('should(not) block third party cookies', async ({browserType, defaultBrowserO await browser.close(); }); -it('should not override viewport size when passed null', (test, parameters) => { - test.fixme(options.WEBKIT(parameters)); +it('should not override viewport size when passed null', (test, { browserName }) => { + test.fixme(browserName === 'webkit'); }, async function({browserType, defaultBrowserOptions, server}) { // Our WebKit embedder does not respect window features. const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); diff --git a/test/keyboard.spec.ts b/test/keyboard.spec.ts index d8209302bd8ca..9c31bb94a7d68 100644 --- a/test/keyboard.spec.ts +++ b/test/keyboard.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame } from './utils'; it('should type into a textarea', async ({page}) => { @@ -83,8 +83,8 @@ it('insertText should only emit input event', async ({page, server}) => { expect(await events.jsonValue()).toEqual(['input']); }); -it('should report shiftKey', (test, parameters) => { - test.fail(options.FIREFOX(parameters) && options.MAC(parameters)); +it('should report shiftKey', (test, { browserName, platform }) => { + test.fail(browserName === 'firefox' && platform === 'darwin'); }, async ({page, server}) => { await page.goto(server.PREFIX + '/input/keyboard.html'); const keyboard = page.keyboard; @@ -342,8 +342,8 @@ it('should be able to prevent selectAll', async ({page, server, isMac}) => { expect(await page.$eval('textarea', textarea => textarea.value)).toBe('some tex'); }); -it('should support MacOS shortcuts', (test, parameters) => { - test.skip(!options.MAC(parameters)); +it('should support MacOS shortcuts', (test, { platform }) => { + test.skip(platform !== 'darwin'); }, async ({page, server}) => { await page.goto(server.PREFIX + '/input/textarea.html'); const textarea = await page.$('textarea'); @@ -384,8 +384,8 @@ it('should work after a cross origin navigation', async ({page, server}) => { }); // event.keyIdentifier has been removed from all browsers except WebKit -it('should expose keyIdentifier in webkit', (test, parameters) => { - test.skip(!options.WEBKIT(parameters)); +it('should expose keyIdentifier in webkit', (test, { browserName }) => { + test.skip(browserName !== 'webkit'); }, async ({page}) => { const lastEvent = await captureLastKeydown(page); const keyMap = { diff --git a/test/mouse.spec.ts b/test/mouse.spec.ts index c0dd44282587e..69b40b519be2f 100644 --- a/test/mouse.spec.ts +++ b/test/mouse.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, xdescribe, options } from './fixtures'; +import { it, expect, xdescribe } from './fixtures'; function dimensions() { const rect = document.querySelector('textarea').getBoundingClientRect(); @@ -27,8 +27,8 @@ function dimensions() { }; } -it('should click the document', (test, parameters) => { - test.flaky(options.FIREFOX(parameters) && options.WIN(parameters), 'Occasionally times out on options.FIREFOX on Windows: https://github.com/microsoft/playwright/pull/1911/checks?check_run_id=607149016'); +it('should click the document', (test, { browserName, platform }) => { + test.flaky(browserName === 'firefox' && platform === 'win32', 'Occasionally times out on options.FIREFOX on Windows: https://github.com/microsoft/playwright/pull/1911/checks?check_run_id=607149016'); }, async ({page, server}) => { await page.evaluate(() => { window['clickPromise'] = new Promise(resolve => { @@ -165,8 +165,8 @@ it('should tween mouse movement', async ({page, isWebKit}) => { ]); }); -it('should work with mobile viewports and cross process navigations', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); +it('should work with mobile viewports and cross process navigations', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browser, server}) => { // @see https://crbug.com/929806 const context = await browser.newContext({ viewport: {width: 360, height: 640}, isMobile: true }); diff --git a/test/network-request.spec.ts b/test/network-request.spec.ts index ac6adb9f6f6ed..8891e43aeba80 100644 --- a/test/network-request.spec.ts +++ b/test/network-request.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import { attachFrame } from './utils'; it('should work for main frame navigation request', async ({page, server}) => { @@ -55,8 +55,8 @@ it('should return headers', async ({page, server, isChromium, isFirefox, isWebKi expect(response.request().headers()['user-agent']).toContain('WebKit'); }); -it('should get the same headers as the server', (test, parameters) => { - test.fail(options.CHROMIUM(parameters) || options.WEBKIT(parameters), 'Provisional headers differ from those in network stack'); +it('should get the same headers as the server', (test, { browserName }) => { + test.fail(browserName === 'chromium' || browserName === 'webkit', 'Provisional headers differ from those in network stack'); }, async ({page, server}) => { await page.goto(server.PREFIX + '/empty.html'); let serverRequest; diff --git a/test/page-add-script-tag.spec.ts b/test/page-add-script-tag.spec.ts index d18211e670dd7..743ad4a437f91 100644 --- a/test/page-add-script-tag.spec.ts +++ b/test/page-add-script-tag.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import path from 'path'; it('should throw an error if no options are provided', async ({page, server}) => { @@ -74,8 +74,8 @@ it('should work with a path', async ({page, server}) => { expect(await page.evaluate(() => window['__injected'])).toBe(42); }); -it('should include sourceURL when path is provided', (test, parameters) => { - test.skip(options.WEBKIT(parameters)); +it('should include sourceURL when path is provided', (test, { browserName }) => { + test.skip(browserName === 'webkit'); }, async ({page, server}) => { await page.goto(server.EMPTY_PAGE); await page.addScriptTag({ path: path.join(__dirname, 'assets/injectedfile.js') }); diff --git a/test/page-basic.spec.ts b/test/page-basic.spec.ts index 567021afd94c2..8c8676f47834b 100644 --- a/test/page-basic.spec.ts +++ b/test/page-basic.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should reject all promises when page is closed', async ({context}) => { const newPage = await context.newPage(); @@ -252,8 +252,8 @@ it('frame.press should work', async ({page, server}) => { expect(await frame.evaluate(() => document.querySelector('textarea').value)).toBe('a'); }); -it('frame.focus should work multiple times', (test, parameters) => { - test.fail(options.FIREFOX(parameters)); +it('frame.focus should work multiple times', (test, { browserName }) => { + test.fail(browserName === 'firefox'); }, async ({ context, server }) => { const page1 = await context.newPage(); const page2 = await context.newPage(); diff --git a/test/page-evaluate.spec.ts b/test/page-evaluate.spec.ts index a6414401f8af6..3759b3b80660e 100644 --- a/test/page-evaluate.spec.ts +++ b/test/page-evaluate.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should work', async ({ page, server }) => { const result = await page.evaluate(() => 7 * 3); @@ -415,8 +415,8 @@ it('should not throw an error when evaluation does a navigation', async ({ page, expect(result).toEqual([42]); }); -it('should not throw an error when evaluation does a synchronous navigation and returns an object', (test, parameters) => { - test.fixme(options.WEBKIT(parameters)); +it('should not throw an error when evaluation does a synchronous navigation and returns an object', (test, { browserName }) => { + test.fixme(browserName === 'webkit'); }, async ({ page, server }) => { // It is imporant to be on about:blank for sync reload. const result = await page.evaluate(() => { @@ -426,7 +426,7 @@ it('should not throw an error when evaluation does a synchronous navigation and expect(result).toEqual({ a: 42 }); }); -it('should not throw an error when evaluation does a synchronous navigation and returns undefined', async ({ page, server }) => { +it('should not throw an error when evaluation does a synchronous navigation and returns undefined', async ({ page }) => { // It is imporant to be on about:blank for sync reload. const result = await page.evaluate(() => { window.location.reload(); @@ -435,15 +435,15 @@ it('should not throw an error when evaluation does a synchronous navigation and expect(result).toBe(undefined); }); -it('should transfer 100Mb of data from page to node.js', (test, parameters) => { - test.skip(options.WIRE); +it('should transfer 100Mb of data from page to node.js', (test, { wire }) => { + test.skip(wire); }, async ({ page }) => { // This is too slow with wire. const a = await page.evaluate(() => Array(100 * 1024 * 1024 + 1).join('a')); expect(a.length).toBe(100 * 1024 * 1024); }); -it('should throw error with detailed information on exception inside promise ', async ({ page, server }) => { +it('should throw error with detailed information on exception inside promise ', async ({ page }) => { let error = null; await page.evaluate(() => new Promise(() => { throw new Error('Error in promise'); @@ -482,7 +482,7 @@ it('should work with non-strict expressions', async ({ page, server }) => { })).toBe(3.14); }); -it('should respect use strict expression', async ({ page, server }) => { +it('should respect use strict expression', async ({ page }) => { const error = await page.evaluate(() => { 'use strict'; // @ts-ignore @@ -493,11 +493,11 @@ it('should respect use strict expression', async ({ page, server }) => { expect(error.message).toContain('variableY'); }); -it('should not leak utility script', async function({ page, server }) { +it('should not leak utility script', async function({ page }) { expect(await page.evaluate(() => this === window)).toBe(true); }); -it('should not leak handles', async ({ page, server }) => { +it('should not leak handles', async ({ page }) => { const error = await page.evaluate('handles.length').catch(e => e); expect((error as Error).message).toContain(' handles'); }); @@ -508,7 +508,7 @@ it('should work with CSP', async ({ page, server }) => { expect(await page.evaluate(() => 2 + 2)).toBe(4); }); -it('should evaluate exception', async ({ page, server }) => { +it('should evaluate exception', async ({ page }) => { const error = await page.evaluate(() => { return (function functionOnStack() { return new Error('error message'); @@ -518,7 +518,7 @@ it('should evaluate exception', async ({ page, server }) => { expect(error).toContain('functionOnStack'); }); -it('should evaluate exception', async ({ page, server }) => { +it('should evaluate exception', async ({ page }) => { const error = await page.evaluate(`new Error('error message')`); expect(error).toContain('Error: error message'); }); @@ -545,12 +545,12 @@ it('should jsonValue() date', async ({ page }) => { expect(await resultHandle.jsonValue()).toEqual({ date: new Date('2020-05-27T01:31:38.506Z') }); }); -it('should not use toJSON when evaluating', async ({ page, server }) => { +it('should not use toJSON when evaluating', async ({ page }) => { const result = await page.evaluate(() => ({ toJSON: () => 'string', data: 'data' })); expect(result).toEqual({ data: 'data', toJSON: {} }); }); -it('should not use toJSON in jsonValue', async ({ page, server }) => { +it('should not use toJSON in jsonValue', async ({ page }) => { const resultHandle = await page.evaluateHandle(() => ({ toJSON: () => 'string', data: 'data' })); expect(await resultHandle.jsonValue()).toEqual({ data: 'data', toJSON: {} }); }); diff --git a/test/page-event-crash.spec.ts b/test/page-event-crash.spec.ts index 7e20b3c06b9bc..9625343e1b786 100644 --- a/test/page-event-crash.spec.ts +++ b/test/page-event-crash.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; function crash(page, toImpl, browserName) { if (browserName === 'chromium') @@ -26,9 +26,9 @@ function crash(page, toImpl, browserName) { toImpl(page)._delegate._session.send('Page.crash', {}).catch(e => {}); } -describe('', (suite, parameters) => { - suite.fixme(options.WIRE); - suite.flaky(options.FIREFOX(parameters) && options.WIN(parameters)); +describe('', (suite, { browserName, platform, wire }) => { + suite.fixme(wire); + suite.flaky(browserName === 'firefox' && platform === 'win32'); }, () => { it('should emit crash event when page crashes', async ({page, browserName, toImpl}) => { await page.setContent(`
This page should crash
`); @@ -63,9 +63,9 @@ describe('', (suite, parameters) => { expect(error.message).toContain('Navigation failed because page crashed'); }); - it('should be able to close context when page crashes', (test, parameters) => { - test.fixme(options.WIRE); - test.flaky(options.FIREFOX(parameters) && options.WIN(parameters)); + it('should be able to close context when page crashes', (test, { browserName, platform, wire }) => { + test.fixme(wire); + test.flaky(browserName === 'firefox' && platform === 'win32'); }, async ({page, browserName, toImpl}) => { await page.setContent(`
This page should crash
`); crash(page, toImpl, browserName); diff --git a/test/page-event-pageerror.spec.ts b/test/page-event-pageerror.spec.ts index 134d498088e08..a0fb02710349c 100644 --- a/test/page-event-pageerror.spec.ts +++ b/test/page-event-pageerror.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; it('should fire', async ({page, server, isWebKit}) => { const [error] = await Promise.all([ @@ -31,8 +31,8 @@ it('should fire', async ({page, server, isWebKit}) => { expect(error.stack).toBe(stack); }); -it('should contain sourceURL', (test, parameters) => { - test.fail(options.WEBKIT(parameters)); +it('should contain sourceURL', (test, { browserName }) => { + test.fail(browserName === 'webkit'); }, async ({page, server}) => { const [error] = await Promise.all([ page.waitForEvent('pageerror'), @@ -57,8 +57,8 @@ it('should handle odd values', async ({page, isFirefox}) => { } }); -it('should handle object', (test, parameters) => { - test.fixme(options.FIREFOX(parameters)); +it('should handle object', (test, { browserName }) => { + test.fixme(browserName === 'firefox'); }, async ({page, isChromium}) => { // Firefox just does not report this error. const [error] = await Promise.all([ @@ -68,8 +68,8 @@ it('should handle object', (test, parameters) => { expect(error.message).toBe(isChromium ? 'Object' : '[object Object]'); }); -it('should handle window', (test, parameters) => { - test.fixme(options.FIREFOX(parameters)); +it('should handle window', (test, { browserName }) => { + test.fixme(browserName === 'firefox'); }, async ({page, isChromium}) => { // Firefox just does not report this error. const [error] = await Promise.all([ diff --git a/test/page-fill.spec.ts b/test/page-fill.spec.ts index 39094616376d6..7253cad1009ed 100644 --- a/test/page-fill.spec.ts +++ b/test/page-fill.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; async function giveItAChanceToFill(page) { for (let i = 0; i < 5; i++) @@ -60,22 +60,22 @@ it('should fill date input after clicking', async ({page, server}) => { expect(await page.$eval('input', input => input.value)).toBe('2020-03-02'); }); -it('should throw on incorrect date', (test, parameters) => { - test.skip(options.WEBKIT(parameters)); +it('should throw on incorrect date', (test, { browserName }) => { + test.skip(browserName === 'webkit'); }, async ({page}) => { await page.setContent(''); const error = await page.fill('input', '2020-13-05').catch(e => e); expect(error.message).toContain('Malformed value'); }); -it('should fill time input', async ({page, server}) => { +it('should fill time input', async ({page}) => { await page.setContent(''); await page.fill('input', '13:15'); expect(await page.$eval('input', input => input.value)).toBe('13:15'); }); -it('should throw on incorrect time', (test, parameters) => { - test.skip(options.WEBKIT(parameters)); +it('should throw on incorrect time', (test, { browserName }) => { + test.skip(browserName === 'webkit'); }, async ({page}) => { await page.setContent(''); const error = await page.fill('input', '25:05').catch(e => e); @@ -88,8 +88,8 @@ it('should fill datetime-local input', async ({page, server}) => { expect(await page.$eval('input', input => input.value)).toBe('2020-03-02T05:15'); }); -it('should throw on incorrect datetime-local', (test, parameters) => { - test.skip(options.WEBKIT(parameters) || options.FIREFOX(parameters)); +it('should throw on incorrect datetime-local', (test, { browserName }) => { + test.skip(browserName === 'webkit' || browserName === 'firefox'); }, async ({page, server}) => { await page.setContent(''); const error = await page.fill('input', 'abc').catch(e => e); diff --git a/test/page-goto.spec.ts b/test/page-goto.spec.ts index 78463b605eec8..bc631963866ee 100644 --- a/test/page-goto.spec.ts +++ b/test/page-goto.spec.ts @@ -17,7 +17,7 @@ import path from 'path'; import url from 'url'; -import { expect, it, options } from './fixtures'; +import { expect, it } from './fixtures'; import { expectedSSLError } from './utils'; it('should work', async ({page, server}) => { @@ -25,7 +25,7 @@ it('should work', async ({page, server}) => { expect(page.url()).toBe(server.EMPTY_PAGE); }); -it('should work with file URL', async ({page, server}) => { +it('should work with file URL', async ({page}) => { const fileurl = url.pathToFileURL(path.join(__dirname, 'assets', 'frames', 'two-frames.html')).href; await page.goto(fileurl); expect(page.url().toLowerCase()).toBe(fileurl.toLowerCase()); @@ -360,8 +360,8 @@ it('should not leak listeners during bad navigation', async ({page, server}) => expect(warning).toBe(null); }); -it('should not leak listeners during navigation of 20 pages', test => { - test.flaky(options.TRACING, 'Flakes on tracing'); +it('should not leak listeners during navigation of 20 pages', (test, parameters) => { + test.flaky(parameters.trace, 'Flakes on tracing'); test.slow('We open 20 pages here'); }, async ({page, context, server}) => { let warning = null; diff --git a/test/page-history.spec.ts b/test/page-history.spec.ts index e121af11f7114..38058fad0a100 100644 --- a/test/page-history.spec.ts +++ b/test/page-history.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import url from 'url'; it('page.goBack should work', async ({page, server}) => { @@ -52,8 +52,8 @@ it('page.goBack should work with HistoryAPI', async ({page, server}) => { expect(page.url()).toBe(server.PREFIX + '/first.html'); }); -it('page.goBack should work for file urls', (test, parameters) => { - test.fail(options.WEBKIT(parameters) && options.MAC(parameters)); +it('page.goBack should work for file urls', (test, { browserName, platform }) => { + test.fail(browserName === 'webkit' && platform === 'darwin'); }, async ({page, server, asset}) => { // WebKit embedder fails to go back/forward to the file url. const url1 = url.pathToFileURL(asset('empty.html')).href; diff --git a/test/page-screenshot.spec.ts b/test/page-screenshot.spec.ts index c0d6089b5de7a..2bf224c732ab0 100644 --- a/test/page-screenshot.spec.ts +++ b/test/page-screenshot.spec.ts @@ -15,15 +15,15 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; import { verifyViewport } from './utils'; import path from 'path'; import fs from 'fs'; // Firefox headful produces a different image. -describe('page screenshot', (suite, parameters) => { - suite.skip(options.FIREFOX(parameters) && !options.HEADLESS); +describe('page screenshot', (suite, { browserName, headful }) => { + suite.skip(browserName === 'firefox' && headful); }, () => { it('should work', async ({page, server, golden}) => { await page.setViewportSize({width: 500, height: 500}); @@ -141,8 +141,8 @@ describe('page screenshot', (suite, parameters) => { await Promise.all(pages.map(page => page.close())); }); - it('should allow transparency', (test, parameters) => { - test.fail(options.FIREFOX(parameters)); + it('should allow transparency', (test, { browserName }) => { + test.fail(browserName === 'firefox'); }, async ({page, golden}) => { await page.setViewportSize({ width: 50, height: 150 }); await page.setContent(` @@ -177,8 +177,8 @@ describe('page screenshot', (suite, parameters) => { expect(screenshot).toMatchImage(golden('screenshot-clip-odd-size.png')); }); - it('should work with a mobile viewport', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); + it('should work with a mobile viewport', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browser, server, golden}) => { const context = await browser.newContext({ viewport: { width: 320, height: 480 }, isMobile: true }); const page = await context.newPage(); @@ -188,8 +188,8 @@ describe('page screenshot', (suite, parameters) => { await context.close(); }); - it('should work with a mobile viewport and clip', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); + it('should work with a mobile viewport and clip', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browser, server, golden}) => { const context = await browser.newContext({viewport: { width: 320, height: 480 }, isMobile: true}); const page = await context.newPage(); @@ -199,8 +199,8 @@ describe('page screenshot', (suite, parameters) => { await context.close(); }); - it('should work with a mobile viewport and fullPage', (test, parameters) => { - test.skip(options.FIREFOX(parameters)); + it('should work with a mobile viewport and fullPage', (test, { browserName }) => { + test.skip(browserName === 'firefox'); }, async ({browser, server, golden}) => { const context = await browser.newContext({viewport: { width: 320, height: 480 }, isMobile: true}); const page = await context.newPage(); @@ -217,9 +217,9 @@ describe('page screenshot', (suite, parameters) => { expect(screenshot).toMatchImage(golden('screenshot-canvas.png'), { threshold: 0.3 }); }); - it('should work for webgl', (test, parameters) => { - test.fixme(options.FIREFOX(parameters)); - test.fixme(options.WEBKIT(parameters) && options.LINUX(parameters)); + it('should work for webgl', (test, { browserName, platform }) => { + test.fixme(browserName === 'firefox'); + test.fixme(browserName === 'webkit' && platform === 'linux'); }, async ({page, server, golden}) => { await page.setViewportSize({width: 640, height: 480}); await page.goto(server.PREFIX + '/screenshots/webgl.html'); diff --git a/test/pdf.spec.ts b/test/pdf.spec.ts index cdd64157b5945..dfa8a427635ce 100644 --- a/test/pdf.spec.ts +++ b/test/pdf.spec.ts @@ -14,22 +14,22 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import fs from 'fs'; import path from 'path'; -it('should be able to save file', (test, parameters) => { - test.skip(!(options.HEADLESS && options.CHROMIUM(parameters)), 'Printing to pdf is currently only supported in headless chromium.'); +it('should be able to save file', (test, { browserName, headful }) => { + test.skip(headful || browserName !== 'chromium', 'Printing to pdf is currently only supported in headless chromium.'); }, async ({page, testOutputDir}) => { const outputFile = path.join(testOutputDir, 'output.pdf'); await page.pdf({path: outputFile}); expect(fs.readFileSync(outputFile).byteLength).toBeGreaterThan(0); }); -it('should only have pdf in chromium', (test, parameters) => { - test.skip(options.CHROMIUM(parameters)); +it('should only have pdf in chromium', (test, { browserName }) => { + test.skip(browserName === 'chromium'); }, async ({page}) => { expect(page.pdf).toBe(undefined); }); diff --git a/test/permissions.spec.ts b/test/permissions.spec.ts index dfc04ff897a8a..c19ad5877c530 100644 --- a/test/permissions.spec.ts +++ b/test/permissions.spec.ts @@ -15,14 +15,14 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; function getPermission(page, name) { return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name); } -describe('permissions', (suite, parameters) => { - suite.skip(options.WEBKIT(parameters)); +describe('permissions', (suite, { browserName }) => { + suite.skip(browserName === 'webkit'); }, () => { it('should be prompt by default', async ({page, server, context}) => { // Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) @@ -101,10 +101,10 @@ describe('permissions', (suite, parameters) => { expect(await getPermission(page, 'geolocation')).toBe('prompt'); }); - it('should trigger permission onchange', (test, parameters) => { - test.fail(options.WEBKIT(parameters)); - test.fail(options.CHROMIUM(parameters) && !options.HEADLESS); - test.flaky(options.FIREFOX(parameters) && options.LINUX(parameters)); + it('should trigger permission onchange', (test, { browserName, headful, platform }) => { + test.fail(browserName === 'webkit'); + test.fail(browserName === 'chromium' && headful); + test.flaky(browserName === 'firefox' && platform === 'linux'); }, async ({page, server, context}) => { // TODO: flaky // - Linux: https://github.com/microsoft/playwright/pull/1790/checks?check_run_id=587327883 @@ -147,10 +147,10 @@ describe('permissions', (suite, parameters) => { await otherContext.close(); }); - it('should support clipboard read', (test, parameters) => { - test.fail(options.WEBKIT(parameters)); - test.fail(options.FIREFOX(parameters), 'No such permissions (requires flag) in Firefox'); - test.fixme(options.CHROMIUM(parameters) && !options.HEADLESS); + it('should support clipboard read', (test, { browserName, headful }) => { + test.fail(browserName === 'webkit'); + test.fail(browserName === 'firefox', 'No such permissions (requires flag) in Firefox'); + test.fixme(browserName === 'chromium' && headful); }, async ({page, server, context}) => { await page.goto(server.EMPTY_PAGE); expect(await getPermission(page, 'clipboard-read')).toBe('prompt'); diff --git a/test/platform.fixtures.ts b/test/platform.fixtures.ts index c493e3d485a2b..81263013dea00 100644 --- a/test/platform.fixtures.ts +++ b/test/platform.fixtures.ts @@ -31,12 +31,6 @@ export const fixtures = baseFixtures .declareWorkerFixtures(); const { defineWorkerFixture, defineParameter, generateParametrizedTests } = fixtures; -export const options = { - MAC: (parameters: PlatformParameters) => parameters.platform === 'darwin', - LINUX: (parameters: PlatformParameters) => parameters.platform === 'linux', - WIN: (parameters: PlatformParameters) => parameters.platform === 'win32', -}; - defineParameter('platform', 'Operating system', process.platform as ('win32' | 'linux' | 'darwin')); generateParametrizedTests( diff --git a/test/playwright.fixtures.ts b/test/playwright.fixtures.ts index 5e7fc7e46b1cf..10422a422ccb9 100644 --- a/test/playwright.fixtures.ts +++ b/test/playwright.fixtures.ts @@ -24,24 +24,61 @@ import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, Launc const mkdtempAsync = util.promisify(fs.mkdtemp); const removeFolderAsync = util.promisify(require('rimraf')); + +// Parameter declarations ------------------------------------------------------ + type PlaywrightParameters = { - browserName: string; + // Browser name, one of 'chromium', 'webkit' and 'firefox', can be specified via + // environment BROWSER=webkit or via command line, --browser-name=webkit + browserName: 'chromium' | 'firefox' | 'webkit'; + // Run tests in a headful mode, can be specified via environment HEADFUL=1 or via + // command line, --headful. Defaults to false. + headful: boolean; + // Slows down Playwright operations by the specified amount of milliseconds. + // Useful so that you can see what is going on. Defaults to 0. + slowMo: number; + // Whether to take screenshots on failure, --screenshot-on-failure. Defaults to false. + screenshotOnFailure: boolean; + // Whether to record the execution trace + trace: boolean; }; + +// Worker fixture declarations ------------------------------------------------- +// ... these live as long as the worker process. + type PlaywrightWorkerFixtures = { - defaultBrowserOptions: LaunchOptions; + // Playwright library. playwright: typeof import('../index'); + // Browser type (Chromium / WebKit / Firefox) browserType: BrowserType; + // Default browserType.launch() options. + defaultBrowserOptions: LaunchOptions; + // Factory for creating a browser with given additional options. + browserFactory: (options?: LaunchOptions) => Promise; + // Browser instance, shared for the worker. browser: Browser; + // True iff browserName is Chromium isChromium: boolean; + // True iff browserName is Firefox isFirefox: boolean; + // True iff browserName is WebKit isWebKit: boolean; }; + +// Test fixture definitions, those are created for each test ------------------ + type PlaywrightTestFixtures = { + // Default browser.newContext() options. + defaultContextOptions: BrowserContextOptions; + // Factory for creating a context with given additional options. + contextFactory: (options?: BrowserContextOptions) => Promise; + // Context instance for test. context: BrowserContext; + // Page instance for test. page: Page; - testOutputDir: string; + // Temporary directory for this test's artifacts. tmpDir: string; }; @@ -50,99 +87,121 @@ export const fixtures = baseFixtures .declareWorkerFixtures() .declareTestFixtures(); -const { defineTestFixture, defineWorkerFixture, defineParameter, generateParametrizedTests } = fixtures; +// Parameter and matrix definitions -------------------------------------------- -export const options = { - CHROMIUM: (parameters: PlaywrightParameters) => parameters.browserName === 'chromium', - FIREFOX: (parameters: PlaywrightParameters) => parameters.browserName === 'firefox', - WEBKIT: (parameters: PlaywrightParameters) => parameters.browserName === 'webkit', - HEADLESS: !!valueFromEnv('HEADLESS', true), - SLOW_MO: valueFromEnv('SLOW_MO', 0), - TRACING: valueFromEnv('TRACING', false), -}; +fixtures.defineParameter('browserName', 'Browser type name', process.env.BROWSER || 'chromium' as any); +fixtures.defineParameter('headful', 'Whether to run tests headless or headful', process.env.HEADFUL ? true : false); +fixtures.defineParameter('screenshotOnFailure', 'Generate screenshot on failure', false); +fixtures.defineParameter('slowMo', 'Slows down Playwright operations by the specified amount of milliseconds', 0); +fixtures.defineParameter('trace', 'Whether to record the execution trace', !!process.env.TRACING || false); + +// If browser is not specified, we are running tests against all three browsers. +fixtures.generateParametrizedTests( + 'browserName', + process.env.BROWSER ? [process.env.BROWSER] as any : ['chromium', 'webkit', 'firefox']); -defineWorkerFixture('defaultBrowserOptions', async ({}, runTest) => { + +// Worker fixtures definitions ------------------------------------------------- + +fixtures.defineWorkerFixture('defaultBrowserOptions', async ({ headful, slowMo }, runTest) => { await runTest({ handleSIGINT: false, - slowMo: options.SLOW_MO, - headless: options.HEADLESS, + slowMo, + headless: !headful, artifactsPath: config.outputDir, }); }); -defineWorkerFixture('playwright', async ({}, test) => { +fixtures.defineWorkerFixture('playwright', async ({}, runTest) => { const playwright = require('../index'); - await test(playwright); + await runTest(playwright); }); -defineWorkerFixture('browserType', async ({playwright, browserName}, test) => { +fixtures.defineWorkerFixture('browserType', async ({playwright, browserName}, runTest) => { const browserType = playwright[browserName]; - await test(browserType); + await runTest(browserType); }); -defineParameter('browserName', 'Browser type name', ''); - -generateParametrizedTests( - 'browserName', - process.env.BROWSER ? [process.env.BROWSER] : ['chromium', 'webkit', 'firefox']); +fixtures.defineWorkerFixture('isFirefox', async ({browserName}, runTest) => { + await runTest(browserName === 'firefox'); +}); -defineWorkerFixture('isChromium', async ({browserName}, test) => { - await test(browserName === 'chromium'); +fixtures.defineWorkerFixture('isWebKit', async ({browserName}, runTest) => { + await runTest(browserName === 'webkit'); }); -defineWorkerFixture('isFirefox', async ({browserName}, test) => { - await test(browserName === 'firefox'); +fixtures.defineWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, runTest) => { + const browser = await browserType.launch(defaultBrowserOptions); + await runTest(browser); + await browser.close(); }); -defineWorkerFixture('isWebKit', async ({browserName}, test) => { - await test(browserName === 'webkit'); +fixtures.defineWorkerFixture('isChromium', async ({browserName}, runTest) => { + await runTest(browserName === 'chromium'); }); -defineWorkerFixture('browser', async ({browserType, defaultBrowserOptions}, test) => { - const browser = await browserType.launch(defaultBrowserOptions); - await test(browser); - if (browser.contexts().length !== 0) { - console.warn(`\nWARNING: test did not close all created contexts! ${new Error().stack}\n`); - await Promise.all(browser.contexts().map(context => context.close())).catch(e => void 0); - } - await browser.close(); +fixtures.defineWorkerFixture('isFirefox', async ({browserName}, runTest) => { + await runTest(browserName === 'firefox'); }); -defineTestFixture('testOutputDir', async ({ testInfo, browserName }, runTest) => { - const relativePath = path.relative(config.testDir, testInfo.file) - .replace(/\.spec\.[jt]s/, '') - .replace(/\.test\.[jt]s/, ''); - const sanitizedTitle = testInfo.title.replace(/[^\w\d]+/g, '_'); - const testOutputDir = path.join(config.outputDir, relativePath, sanitizedTitle, browserName); - await runTest(testOutputDir); +fixtures.defineWorkerFixture('isWebKit', async ({browserName}, runTest) => { + await runTest(browserName === 'webkit'); }); -defineTestFixture('context', async ({ browser, testOutputDir }, runTest) => { - const contextOptions: BrowserContextOptions = { +// Test fixtures definitions --------------------------------------------------- + +fixtures.defineTestFixture('defaultContextOptions', async ({ testOutputDir, trace }, runTest) => { + await runTest({ relativeArtifactsPath: path.relative(config.outputDir, testOutputDir), - recordTrace: !!options.TRACING, - recordVideos: !!options.TRACING, - }; - const context = await browser.newContext(contextOptions); + recordTrace: trace, + recordVideos: trace, + }); +}); + +fixtures.defineTestFixture('contextFactory', async ({ browser, defaultContextOptions, testInfo, screenshotOnFailure, testOutputFile }, runTest) => { + const contexts: BrowserContext[] = []; + async function contextFactory(options: BrowserContextOptions = {}) { + const context = await browser.newContext({ ...defaultContextOptions, ...options }); + contexts.push(context); + return context; + } + await runTest(contextFactory); + + if (screenshotOnFailure && (testInfo.status !== testInfo.expectedStatus)) { + let ordinal = 0; + for (const context of contexts) { + for (const page of context.pages()) + await page.screenshot({ timeout: 5000, path: await testOutputFile(`test-failed-${++ordinal}.png`) }); + } + } + for (const context of contexts) + await context.close(); +}); + +fixtures.defineTestFixture('context', async ({ contextFactory }, runTest) => { + const context = await contextFactory(); await runTest(context); - await context.close(); + // Context factory is taking care of closing the context, + // so that it could capture a screenshot on failure. }); -defineTestFixture('page', async ({ context, testOutputDir, testInfo }, runTest) => { - const page = await context.newPage(); - await runTest(page); - if (testInfo.status === 'failed' || testInfo.status === 'timedOut') - await page.screenshot({ timeout: 5000, path: path.join(testOutputDir, 'test-failed.png') }); +fixtures.defineTestFixture('page', async ({context}, runTest) => { + // Always create page off context so that they matched. + await runTest(await context.newPage()); + // Context fixture is taking care of closing the page. }); -defineTestFixture('tmpDir', async ({}, test) => { +fixtures.defineTestFixture('tmpDir', async ({ }, runTest) => { const tmpDir = await mkdtempAsync(path.join(os.tmpdir(), 'playwright-test-')); - await test(tmpDir); - await removeFolderAsync(tmpDir).catch(e => {}); + await runTest(tmpDir); + await removeFolderAsync(tmpDir).catch(e => { }); }); -function valueFromEnv(name, defaultValue) { - if (!(name in process.env)) - return defaultValue; - return JSON.parse(process.env[name]); -} +fixtures.overrideTestFixture('testOutputDir', async ({ testInfo, browserName }, runTest) => { + const relativePath = path.relative(config.testDir, testInfo.file) + .replace(/\.spec\.[jt]s/, '') + .replace(/\.test\.[jt]s/, ''); + const sanitizedTitle = testInfo.title.replace(/[^\w\d]+/g, '_'); + const testOutputDir = path.join(config.outputDir, relativePath, sanitizedTitle, browserName); + await runTest(testOutputDir); +}); diff --git a/test/proxy.spec.ts b/test/proxy.spec.ts index 826498d946006..c76c28e6e2a08 100644 --- a/test/proxy.spec.ts +++ b/test/proxy.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import socks from 'socksv5'; @@ -77,8 +77,8 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) = await browser.close(); }); -it('should exclude patterns', (test, parameters) => { - test.flaky(options.CHROMIUM(parameters) && !options.HEADLESS, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.'); +it('should exclude patterns', (test, { browserName, headful }) => { + test.flaky(browserName === 'chromium' && headful, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.'); }, async ({browserType, defaultBrowserOptions, server}) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); @@ -119,8 +119,8 @@ it('should exclude patterns', (test, parameters) => { await browser.close(); }); -it('should use socks proxy', (test, parameters) => { - test.flaky(options.MAC(parameters) && options.WEBKIT(parameters), 'Intermittent page.goto: The network connection was lost error on bots'); +it('should use socks proxy', (test, { browserName, platform }) => { + test.flaky(platform === 'darwin' && browserName === 'webkit', 'Intermittent page.goto: The network connection was lost error on bots'); }, async ({ browserType, defaultBrowserOptions, testWorkerIndex }) => { const server = socks.createServer((info, accept, deny) => { let socket; diff --git a/test/request-fulfill.spec.ts b/test/request-fulfill.spec.ts index ed363a7f29fd8..910199dc49eb9 100644 --- a/test/request-fulfill.spec.ts +++ b/test/request-fulfill.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { it, expect, options } from './fixtures'; +import { it, expect } from './fixtures'; import fs from 'fs'; import path from 'path'; @@ -50,8 +50,8 @@ it('should work with status code 422', async ({page, server}) => { expect(await page.evaluate(() => document.body.textContent)).toBe('Yo, page!'); }); -it('should allow mocking binary responses', (test, parameters) => { - test.skip(options.FIREFOX(parameters) && !options.HEADLESS, '// Firefox headful produces a different image.'); +it('should allow mocking binary responses', (test, { browserName, headful }) => { + test.skip(browserName === 'firefox' && headful, '// Firefox headful produces a different image.'); }, async ({page, server, golden}) => { await page.route('**/*', route => { const imageBuffer = fs.readFileSync(path.join(__dirname, 'assets', 'pptr.png')); @@ -70,8 +70,8 @@ it('should allow mocking binary responses', (test, parameters) => { expect(await img.screenshot()).toMatchImage(golden('mock-binary-response.png')); }); -it('should allow mocking svg with charset', (test, parameters) => { - test.skip(options.FIREFOX(parameters) && !options.HEADLESS, '// Firefox headful produces a different image.'); +it('should allow mocking svg with charset', (test, { browserName, headful }) => { + test.skip(browserName === 'firefox' && headful, '// Firefox headful produces a different image.'); }, async ({page, server, golden}) => { // Firefox headful produces a different image. await page.route('**/*', route => { diff --git a/test/screencast.spec.ts b/test/screencast.spec.ts index 1e890f4553676..d2d6d941e0e06 100644 --- a/test/screencast.spec.ts +++ b/test/screencast.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { options, fixtures as playwrightFixtures, config } from './fixtures'; +import { fixtures as playwrightFixtures, config } from './fixtures'; import type { Page, Browser } from '..'; import fs from 'fs'; @@ -265,9 +265,9 @@ describe('screencast', suite => { } }); - it('should capture css transformation', (test, parameters) => { - test.fail(options.WEBKIT(parameters) && options.WIN(parameters), 'Does not work on WebKit Windows'); - test.fixme(!options.HEADLESS, 'Fails on headful'); + it('should capture css transformation', (test, { browserName, platform, headful }) => { + test.fail(browserName === 'webkit' && platform === 'win32', 'Does not work on WebKit Windows'); + test.fixme(headful, 'Fails on headful'); }, async ({browser, server, videoPlayer, relativeArtifactsPath, videoDir}) => { const size = {width: 320, height: 240}; // Set viewport equal to screencast frame size to avoid scaling. @@ -315,8 +315,8 @@ describe('screencast', suite => { expect(videoFiles.length).toBe(2); }); - it('should scale frames down to the requested size ', test => { - test.fixme(!options.HEADLESS, 'Fails on headful'); + it('should scale frames down to the requested size ', (test, parameters) => { + test.fixme(parameters.headful, 'Fails on headful'); }, async ({browser, videoPlayer, relativeArtifactsPath, videoDir, server}) => { const context = await browser.newContext({ relativeArtifactsPath, diff --git a/test/slowmo.spec.ts b/test/slowmo.spec.ts index 9ebaa4ece3c9b..ca3ace94590bc 100644 --- a/test/slowmo.spec.ts +++ b/test/slowmo.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { it, expect, describe, options } from './fixtures'; +import { it, expect, describe } from './fixtures'; import { attachFrame } from './utils'; async function checkSlowMo(toImpl, page, task) { @@ -44,8 +44,8 @@ async function checkPageSlowMo(toImpl, page, task) { `); await checkSlowMo(toImpl, page, task); } -describe('slowMo', suite => { - suite.skip(options.WIRE); +describe('slowMo', (suite, { wire }) => { + suite.skip(wire); }, () => { it('Page SlowMo $$eval', async ({page, toImpl}) => { await checkPageSlowMo(toImpl, page, () => page.$$eval('button', () => void 0));