diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 48320a40cd..48aacf2186 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -186,8 +186,8 @@ jobs: name: wire-${{ matrix.browser }}-linux-test-results path: test-results - tracing_linux: - name: "Tracing Linux" + video_linux: + name: "Video Linux" strategy: fail-fast: false matrix: @@ -207,13 +207,12 @@ jobs: # XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR # Wrap `npm run` in a subshell to redirect STDERR to file. # Enable core dumps in the subshell. - - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npx folio test/ --workers=1 --forbid-only --timeout=60000 --global-timeout=5400000 --retries=3 --reporter=dot,json" + - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && npx folio test/ --workers=1 --forbid-only --timeout=60000 --global-timeout=5400000 --retries=3 --reporter=dot,json -p video" env: BROWSER: ${{ matrix.browser }} - TRACING: true FOLIO_JSON_OUTPUT_NAME: "test-results/report.json" - uses: actions/upload-artifact@v1 if: ${{ always() }} with: - name: tracing-${{ matrix.browser }}-linux-test-results + name: video-${{ matrix.browser }}-linux-test-results path: test-results diff --git a/test/browsercontext-add-cookies.spec.ts b/test/browsercontext-add-cookies.spec.ts index 6cadbab653..10f8f1a605 100644 --- a/test/browsercontext-add-cookies.spec.ts +++ b/test/browsercontext-add-cookies.spec.ts @@ -139,15 +139,15 @@ it('should isolate send cookie header', async ({server, context, browser}) => { } }); -it('should isolate cookies between launches', (test, parameters) => { +it('should isolate cookies between launches', test => { test.slow(); -}, async ({browserType, server, defaultBrowserOptions}) => { - const browser1 = await browserType.launch(defaultBrowserOptions); +}, async ({browserType, server, browserOptions}) => { + const browser1 = await browserType.launch(browserOptions); const context1 = await browser1.newContext(); await context1.addCookies([{url: server.EMPTY_PAGE, name: 'cookie-in-context-1', value: 'value', expires: Date.now() / 1000 + 10000}]); await browser1.close(); - const browser2 = await browserType.launch(defaultBrowserOptions); + const browser2 = await browserType.launch(browserOptions); const context2 = await browser2.newContext(); const cookies = await context2.cookies(); expect(cookies.length).toBe(0); diff --git a/test/browsertype-launch-server.spec.ts b/test/browsertype-launch-server.spec.ts index 86e4365a76..758c5b924e 100644 --- a/test/browsertype-launch-server.spec.ts +++ b/test/browsertype-launch-server.spec.ts @@ -20,21 +20,21 @@ import { it, expect, describe } from './fixtures'; describe('lauch server', (suite, { wire }) => { suite.skip(wire); }, () => { - it('should work', async ({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); + it('should work', async ({browserType, browserOptions}) => { + const browserServer = await browserType.launchServer(browserOptions); expect(browserServer.wsEndpoint()).not.toBe(null); await browserServer.close(); }); - it('should work with port', async ({browserType, defaultBrowserOptions, testWorkerIndex}) => { - const browserServer = await browserType.launchServer({ ...defaultBrowserOptions, port: 8800 + testWorkerIndex }); + it('should work with port', async ({browserType, browserOptions, testWorkerIndex}) => { + const browserServer = await browserType.launchServer({ ...browserOptions, port: 8800 + testWorkerIndex }); expect(browserServer.wsEndpoint()).toContain(String(8800 + testWorkerIndex)); await browserServer.close(); }); - it('should fire "close" event during kill', async ({browserType, defaultBrowserOptions}) => { + it('should fire "close" event during kill', async ({browserType, browserOptions}) => { const order = []; - const browserServer = await browserType.launchServer(defaultBrowserOptions); + const browserServer = await browserType.launchServer(browserOptions); const closedPromise = new Promise(f => browserServer.on('close', () => { order.push('closed'); f(); @@ -46,14 +46,14 @@ describe('lauch server', (suite, { wire }) => { expect(order).toEqual(['closed', 'killed']); }); - it('should return child_process instance', async ({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); + it('should return child_process instance', async ({browserType, browserOptions}) => { + const browserServer = await browserType.launchServer(browserOptions); expect(browserServer.process().pid).toBeGreaterThan(0); await browserServer.close(); }); - it('should fire close event', async ({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); + it('should fire close event', async ({browserType, browserOptions}) => { + const browserServer = await browserType.launchServer(browserOptions); const [result] = await Promise.all([ // @ts-expect-error The signal parameter is not documented. new Promise(f => browserServer.on('close', (exitCode, signal) => f({ exitCode, signal }))), diff --git a/test/browsertype-launch.spec.ts b/test/browsertype-launch.spec.ts index 3eb13c06b4..f26579aba4 100644 --- a/test/browsertype-launch.spec.ts +++ b/test/browsertype-launch.spec.ts @@ -18,8 +18,8 @@ import path from 'path'; import { it, expect } from './fixtures'; -it('should reject all promises when browser is closed', async ({browserType, defaultBrowserOptions}) => { - const browser = await browserType.launch(defaultBrowserOptions); +it('should reject all promises when browser is closed', async ({browserType, browserOptions}) => { + const browser = await browserType.launch(browserOptions); const page = await (await browser.newContext()).newPage(); let error = null; const neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e); @@ -29,54 +29,54 @@ it('should reject all promises when browser is closed', async ({browserType, def expect(error.message).toContain('Protocol error'); }); -it('should throw if userDataDir option is passed', async ({browserType, defaultBrowserOptions}) => { +it('should throw if userDataDir option is passed', async ({browserType, browserOptions}) => { let waitError = null; - const options = Object.assign({}, defaultBrowserOptions, {userDataDir: 'random-path'}); + const options = Object.assign({}, browserOptions, {userDataDir: 'random-path'}); await browserType.launch(options).catch(e => waitError = e); expect(waitError.message).toContain('userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead'); }); -it('should throw if port option is passed', async ({browserType, defaultBrowserOptions}) => { - const options = Object.assign({}, defaultBrowserOptions, {port: 1234}); +it('should throw if port option is passed', async ({browserType, browserOptions}) => { + const options = Object.assign({}, browserOptions, {port: 1234}); const error = await browserType.launch(options).catch(e => e); expect(error.message).toContain('Cannot specify a port without launching as a server.'); }); -it('should throw if port option is passed for persistent context', async ({browserType, defaultBrowserOptions}) => { - const options = Object.assign({}, defaultBrowserOptions, {port: 1234}); +it('should throw if port option is passed for persistent context', async ({browserType, browserOptions}) => { + const options = Object.assign({}, browserOptions, {port: 1234}); const error = await browserType.launchPersistentContext('foo', options).catch(e => e); expect(error.message).toContain('Cannot specify a port without launching as a server.'); }); it('should throw if page argument is passed', (test, { browserName }) => { test.skip(browserName === 'firefox'); -}, async ({browserType, defaultBrowserOptions}) => { +}, async ({browserType, browserOptions}) => { let waitError = null; - const options = Object.assign({}, defaultBrowserOptions, { args: ['http://example.com'] }); + const options = Object.assign({}, browserOptions, { args: ['http://example.com'] }); await browserType.launch(options).catch(e => waitError = e); expect(waitError.message).toContain('can not specify page'); }); it('should reject if launched browser fails immediately', (test, parameters) => { test.fixme(`I'm getting ENCONRESET on this one.`); -}, async ({browserType, defaultBrowserOptions}) => { - const options = Object.assign({}, defaultBrowserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')}); +}, async ({browserType, browserOptions}) => { + const options = Object.assign({}, browserOptions, {executablePath: path.join(__dirname, 'assets', 'dummy_bad_browser_executable.js')}); let waitError = null; await browserType.launch(options).catch(e => waitError = e); expect(waitError.message).toContain('== logs =='); }); -it('should reject if executable path is invalid', async ({browserType, defaultBrowserOptions}) => { +it('should reject if executable path is invalid', async ({browserType, browserOptions}) => { let waitError = null; - const options = Object.assign({}, defaultBrowserOptions, {executablePath: 'random-invalid-path'}); + const options = Object.assign({}, browserOptions, {executablePath: 'random-invalid-path'}); await browserType.launch(options).catch(e => waitError = e); expect(waitError.message).toContain('Failed to launch'); }); it('should handle timeout', (test, { wire }) => { test.skip(wire); -}, async ({browserType, defaultBrowserOptions}) => { - const options = { ...defaultBrowserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) }; +}, async ({browserType, browserOptions}) => { + const options = { ...browserOptions, timeout: 5000, __testHookBeforeCreateBrowser: () => new Promise(f => setTimeout(f, 6000)) }; const error = await browserType.launch(options).catch(e => e); expect(error.message).toContain(`browserType.launch: Timeout 5000ms exceeded.`); expect(error.message).toContain(``); @@ -85,32 +85,32 @@ it('should handle timeout', (test, { wire }) => { it('should handle exception', (test, { wire }) => { test.skip(wire); -}, async ({browserType, defaultBrowserOptions}) => { +}, async ({browserType, browserOptions}) => { const e = new Error('Dummy'); - const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; + const options = { ...browserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; const error = await browserType.launch(options).catch(e => e); expect(error.message).toContain('Dummy'); }); it('should report launch log', (test, { wire }) => { test.skip(wire); -}, async ({browserType, defaultBrowserOptions}) => { +}, async ({browserType, browserOptions}) => { const e = new Error('Dummy'); - const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; + const options = { ...browserOptions, __testHookBeforeCreateBrowser: () => { throw e; }, timeout: 9000 }; const error = await browserType.launch(options).catch(e => e); expect(error.message).toContain(''); }); it('should accept objects as options', (test, parameters) => { test.slow(); -}, async ({browserType, defaultBrowserOptions}) => { +}, async ({browserType, browserOptions}) => { // @ts-expect-error process is not a real option. - const browser = await browserType.launch({ ...defaultBrowserOptions, process }); + const browser = await browserType.launch({ ...browserOptions, process }); await browser.close(); }); -it('should fire close event for all contexts', async ({browserType, defaultBrowserOptions}) => { - const browser = await browserType.launch(defaultBrowserOptions); +it('should fire close event for all contexts', async ({browserType, browserOptions}) => { + const browser = await browserType.launch(browserOptions); const context = await browser.newContext(); let closed = false; context.on('close', () => closed = true); @@ -118,8 +118,8 @@ it('should fire close event for all contexts', async ({browserType, defaultBrows expect(closed).toBe(true); }); -it('should be callable twice', async ({browserType, defaultBrowserOptions}) => { - const browser = await browserType.launch(defaultBrowserOptions); +it('should be callable twice', async ({browserType, browserOptions}) => { + const browser = await browserType.launch(browserOptions); await Promise.all([ browser.close(), browser.close(), diff --git a/test/channels.spec.ts b/test/channels.spec.ts index 43ce011251..9929b8be67 100644 --- a/test/channels.spec.ts +++ b/test/channels.spec.ts @@ -118,7 +118,7 @@ it('should scope CDPSession handles', (test, { browserName }) => { await expectScopeState(browserType, GOLDEN_PRECONDITION); }); -it('should scope browser handles', async ({browserType, defaultBrowserOptions}) => { +it('should scope browser handles', async ({browserType, browserOptions}) => { const GOLDEN_PRECONDITION = { _guid: '', objects: [ @@ -135,7 +135,7 @@ it('should scope browser handles', async ({browserType, defaultBrowserOptions}) }; await expectScopeState(browserType, GOLDEN_PRECONDITION); - const browser = await browserType.launch(defaultBrowserOptions); + const browser = await browserType.launch(browserOptions); await browser.newContext(); await expectScopeState(browserType, { _guid: '', @@ -161,8 +161,8 @@ it('should scope browser handles', async ({browserType, defaultBrowserOptions}) await expectScopeState(browserType, GOLDEN_PRECONDITION); }); -it('should work with the domain module', async ({ domain, browserType, defaultBrowserOptions }) => { - const browser = await browserType.launch(defaultBrowserOptions); +it('should work with the domain module', async ({ domain, browserType, browserOptions }) => { + const browser = await browserType.launch(browserOptions); const page = await browser.newPage(); const result = await page.evaluate(() => 1 + 1); expect(result).toBe(2); diff --git a/test/chromium/launcher.spec.ts b/test/chromium/launcher.spec.ts index de044a5926..fce88994d8 100644 --- a/test/chromium/launcher.spec.ts +++ b/test/chromium/launcher.spec.ts @@ -20,8 +20,8 @@ import type { ChromiumBrowser, ChromiumBrowserContext } from '../..'; it('should throw with remote-debugging-pipe argument', (test, { browserName, wire }) => { test.skip(wire || browserName !== 'chromium'); -}, async ({browserType, defaultBrowserOptions}) => { - const options = Object.assign({}, defaultBrowserOptions); +}, async ({browserType, browserOptions}) => { + const options = Object.assign({}, browserOptions); options.args = ['--remote-debugging-pipe'].concat(options.args || []); const error = await browserType.launchServer(options).catch(e => e); expect(error.message).toContain('Playwright manages remote debugging connection itself'); @@ -29,8 +29,8 @@ it('should throw with remote-debugging-pipe argument', (test, { browserName, wir 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); +}, async ({browserType, browserOptions}) => { + const options = Object.assign({}, browserOptions); options.args = ['--remote-debugging-port=0'].concat(options.args || []); const browser = await browserType.launchServer(options); await browser.close(); @@ -38,14 +38,14 @@ it('should not throw with remote-debugging-port argument', (test, { browserName, it('should open devtools when "devtools: true" option is given', (test, { wire, browserName, platform}) => { test.skip(browserName !== 'chromium' || wire || platform === 'win32'); -}, async ({browserType, defaultBrowserOptions}) => { +}, async ({browserType, browserOptions}) => { let devtoolsCallback; const devtoolsPromise = new Promise(f => devtoolsCallback = f); const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => { if (parsed.method === 'getPreferences') devtoolsCallback(); }; - const browser = await browserType.launch({...defaultBrowserOptions, headless: false, devtools: true, __testHookForDevTools} as any); + const browser = await browserType.launch({...browserOptions, headless: false, devtools: true, __testHookForDevTools} as any); const context = await browser.newContext(); await Promise.all([ devtoolsPromise, @@ -56,10 +56,10 @@ it('should open devtools when "devtools: true" option is given', (test, { wire, it('should return background pages', (test, { browserName }) => { test.skip(browserName !== 'chromium'); -}, async ({browserType, defaultBrowserOptions, createUserDataDir}) => { +}, async ({browserType, browserOptions, createUserDataDir}) => { const userDataDir = await createUserDataDir(); const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension'); - const extensionOptions = {...defaultBrowserOptions, + const extensionOptions = {...browserOptions, headless: false, args: [ `--disable-extensions-except=${extensionPath}`, @@ -79,8 +79,8 @@ it('should return background pages', (test, { browserName }) => { it('should not create pages automatically', (test, { browserName }) => { test.skip(browserName !== 'chromium'); -}, async ({browserType, defaultBrowserOptions}) => { - const browser = await browserType.launch(defaultBrowserOptions); +}, async ({browserType, browserOptions}) => { + const browser = await browserType.launch(browserOptions); const browserSession = await (browser as ChromiumBrowser).newBrowserCDPSession(); const targets = []; browserSession.on('Target.targetCreated', async ({targetInfo}) => { diff --git a/test/chromium/oopif.spec.ts b/test/chromium/oopif.spec.ts index 4fb1c212bf..46517956ca 100644 --- a/test/chromium/oopif.spec.ts +++ b/test/chromium/oopif.spec.ts @@ -17,10 +17,10 @@ import { folio } from '../fixtures'; const fixtures = folio.extend(); -fixtures.browser.override(async ({browserType, defaultBrowserOptions}, run) => { +fixtures.browser.override(async ({browserType, browserOptions}, run) => { const browser = await browserType.launch({ - ...defaultBrowserOptions, - args: (defaultBrowserOptions.args || []).concat(['--site-per-process']) + ...browserOptions, + args: (browserOptions.args || []).concat(['--site-per-process']) }); await run(browser); await browser.close(); @@ -240,10 +240,10 @@ describe('oopif', (suite, { browserName }) => { expect(await page.evaluate(() => window['BUTTON_CLICKED'])).toBe(true); }); - it('should report google.com frame with headful', async ({browserType, defaultBrowserOptions, server}) => { + it('should report google.com frame with headful', async ({browserType, browserOptions, server}) => { // @see https://github.com/GoogleChrome/puppeteer/issues/2548 // https://google.com is isolated by default in Chromium embedder. - const browser = await browserType.launch({...defaultBrowserOptions, headless: false}); + const browser = await browserType.launch({...browserOptions, headless: false}); const page = await browser.newPage(); await page.goto(server.EMPTY_PAGE); await page.route('**/*', route => { diff --git a/test/defaultbrowsercontext-2.spec.ts b/test/defaultbrowsercontext-2.spec.ts index 2d0eaa6b0c..a2e058b5ed 100644 --- a/test/defaultbrowsercontext-2.spec.ts +++ b/test/defaultbrowsercontext-2.spec.ts @@ -79,9 +79,9 @@ it('should support extraHTTPHeaders option', (test, { browserName, platform, hea it('should accept userDataDir', (test, { browserName }) => { test.flaky(browserName === 'chromium'); -}, async ({createUserDataDir, browserType, defaultBrowserOptions}) => { +}, async ({createUserDataDir, browserType, browserOptions}) => { const userDataDir = await createUserDataDir(); - const context = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); + const context = await browserType.launchPersistentContext(userDataDir, browserOptions); expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); await context.close(); expect(fs.readdirSync(userDataDir).length).toBeGreaterThan(0); @@ -89,22 +89,22 @@ it('should accept userDataDir', (test, { browserName }) => { it('should restore state from userDataDir', (test, { browserName }) => { test.slow(); -}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { +}, async ({browserType, browserOptions, server, createUserDataDir}) => { const userDataDir = await createUserDataDir(); - const browserContext = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); + const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions); const page = await browserContext.newPage(); await page.goto(server.EMPTY_PAGE); await page.evaluate(() => localStorage.hey = 'hello'); await browserContext.close(); - const browserContext2 = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); + const browserContext2 = await browserType.launchPersistentContext(userDataDir, browserOptions); const page2 = await browserContext2.newPage(); await page2.goto(server.EMPTY_PAGE); expect(await page2.evaluate(() => localStorage.hey)).toBe('hello'); await browserContext2.close(); const userDataDir2 = await createUserDataDir(); - const browserContext3 = await browserType.launchPersistentContext(userDataDir2, defaultBrowserOptions); + const browserContext3 = await browserType.launchPersistentContext(userDataDir2, browserOptions); const page3 = await browserContext3.newPage(); await page3.goto(server.EMPTY_PAGE); expect(await page3.evaluate(() => localStorage.hey)).not.toBe('hello'); @@ -114,9 +114,9 @@ it('should restore state from userDataDir', (test, { browserName }) => { it('should restore cookies from userDataDir', (test, { browserName }) => { test.slow(); test.flaky(browserName === 'chromium'); -}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { +}, async ({browserType, browserOptions, server, createUserDataDir}) => { const userDataDir = await createUserDataDir(); - const browserContext = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); + const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions); const page = await browserContext.newPage(); await page.goto(server.EMPTY_PAGE); const documentCookie = await page.evaluate(() => { @@ -126,14 +126,14 @@ it('should restore cookies from userDataDir', (test, { browserName }) => { expect(documentCookie).toBe('doSomethingOnlyOnce=true'); await browserContext.close(); - const browserContext2 = await browserType.launchPersistentContext(userDataDir, defaultBrowserOptions); + const browserContext2 = await browserType.launchPersistentContext(userDataDir, browserOptions); const page2 = await browserContext2.newPage(); await page2.goto(server.EMPTY_PAGE); expect(await page2.evaluate(() => document.cookie)).toBe('doSomethingOnlyOnce=true'); await browserContext2.close(); const userDataDir2 = await createUserDataDir(); - const browserContext3 = await browserType.launchPersistentContext(userDataDir2, defaultBrowserOptions); + const browserContext3 = await browserType.launchPersistentContext(userDataDir2, browserOptions); const page3 = await browserContext3.newPage(); await page3.goto(server.EMPTY_PAGE); expect(await page3.evaluate(() => document.cookie)).not.toBe('doSomethingOnlyOnce=true'); @@ -148,19 +148,19 @@ it('should have default URL when launching browser', async ({launchPersistent}) 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] }; +}, async ({browserType, browserOptions, server, createUserDataDir}) => { + const options = {...browserOptions, 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, { wire }) => { test.skip(wire); -}, async ({browserType, defaultBrowserOptions, server, createUserDataDir, toImpl}) => { +}, async ({browserType, browserOptions, server, createUserDataDir, toImpl}) => { const userDataDir = await createUserDataDir(); - const args = toImpl(browserType)._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank'); + const args = toImpl(browserType)._defaultArgs(browserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank'); const options = { - ...defaultBrowserOptions, + ...browserOptions, args: [...args, server.EMPTY_PAGE], ignoreDefaultArgs: true, }; @@ -175,17 +175,17 @@ it('should have passed URL when launching with ignoreDefaultArgs: true', (test, 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)) }; +}, async ({browserType, browserOptions, createUserDataDir}) => { + const options = { ...browserOptions, 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, { wire }) => { test.skip(wire); -}, async ({browserType, defaultBrowserOptions, createUserDataDir}) => { +}, async ({browserType, browserOptions, createUserDataDir}) => { const e = new Error('Dummy'); - const options = { ...defaultBrowserOptions, __testHookBeforeCreateBrowser: () => { throw e; } }; + const options = { ...browserOptions, __testHookBeforeCreateBrowser: () => { throw e; } }; const error = await browserType.launchPersistentContext(await createUserDataDir(), options).catch(e => e); expect(error.message).toContain('Dummy'); }); diff --git a/test/download.spec.ts b/test/download.spec.ts index 8b1169ab1e..f40da07941 100644 --- a/test/download.spec.ts +++ b/test/download.spec.ts @@ -344,8 +344,8 @@ describe('download event', () => { expect(fs.existsSync(path2)).toBeFalsy(); }); - it('should delete downloads on browser gone', async ({ server, browserType, defaultBrowserOptions }) => { - const browser = await browserType.launch(defaultBrowserOptions); + it('should delete downloads on browser gone', async ({ server, browserType, browserOptions }) => { + const browser = await browserType.launch(browserOptions); const page = await browser.newPage({ acceptDownloads: true }); await page.setContent(`download`); const [ download1 ] = await Promise.all([ diff --git a/test/downloads-path.spec.ts b/test/downloads-path.spec.ts index 029b0713de..2cc352d4dd 100644 --- a/test/downloads-path.spec.ts +++ b/test/downloads-path.spec.ts @@ -25,14 +25,14 @@ type TestState = { }; const fixtures = folio.extend<{}, TestState>(); -fixtures.downloadsBrowser.init(async ({ server, browserType, defaultBrowserOptions, testInfo }, test) => { +fixtures.downloadsBrowser.init(async ({ server, browserType, browserOptions, testInfo }, test) => { server.setRoute('/download', (req, res) => { res.setHeader('Content-Type', 'application/octet-stream'); res.setHeader('Content-Disposition', 'attachment; filename=file.txt'); res.end(`Hello world`); }); const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, downloadsPath: testInfo.outputPath(''), }); await test(browser); diff --git a/test/firefox/launcher.spec.ts b/test/firefox/launcher.spec.ts index 45977d09b3..904a40cf81 100644 --- a/test/firefox/launcher.spec.ts +++ b/test/firefox/launcher.spec.ts @@ -17,9 +17,9 @@ import { it, expect } from '../fixtures'; it('should pass firefox user preferences', (test, { browserName }) => { test.skip(browserName !== 'firefox'); -}, async ({browserType, defaultBrowserOptions}) => { +}, async ({browserType, browserOptions}) => { const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, firefoxUserPrefs: { 'network.proxy.type': 1, 'network.proxy.http': '127.0.0.1', diff --git a/test/fixtures.ts b/test/fixtures.ts index a8cc1bc319..b6e29300d0 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -72,13 +72,13 @@ fixtures.createUserDataDir.init(async ({ }, run) => { await Promise.all(dirs.map(dir => removeFolderAsync(dir).catch(e => { }))); }); -fixtures.launchPersistent.init(async ({ createUserDataDir, defaultBrowserOptions, browserType }, run) => { +fixtures.launchPersistent.init(async ({ createUserDataDir, browserOptions, browserType }, run) => { let context; async function launchPersistent(options) { if (context) throw new Error('can only launch one persitent context'); const userDataDir = await createUserDataDir(); - context = await browserType.launchPersistentContext(userDataDir, { ...defaultBrowserOptions, ...options }); + context = await browserType.launchPersistentContext(userDataDir, { ...browserOptions, ...options }); const page = context.pages()[0]; return { context, page }; } @@ -87,7 +87,7 @@ fixtures.launchPersistent.init(async ({ createUserDataDir, defaultBrowserOptions await context.close(); }); -fixtures.defaultBrowserOptions.override(async ({ browserName, headful, slowMo }, run) => { +fixtures.browserOptions.override(async ({ browserName, headful, slowMo }, run) => { const executablePath = getExecutablePath(browserName); if (executablePath) console.error(`Using executable at ${executablePath}`); diff --git a/test/headful.spec.ts b/test/headful.spec.ts index 74020717b8..fef45f42a3 100644 --- a/test/headful.spec.ts +++ b/test/headful.spec.ts @@ -16,8 +16,8 @@ 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 }); +it('should have default url when launching browser', async ({browserType, browserOptions, createUserDataDir}) => { + const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...browserOptions, headless: false }); const urls = browserContext.pages().map(page => page.url()); expect(urls).toEqual(['about:blank']); await browserContext.close(); @@ -27,17 +27,17 @@ it('headless should be able to read cookies written by headful', (test, { browse test.fail(platform === 'win32' && browserName === 'chromium'); test.flaky(browserName === 'firefox'); test.slow(); -}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { +}, async ({browserType, browserOptions, server, createUserDataDir}) => { // see https://github.com/microsoft/playwright/issues/717 const userDataDir = await createUserDataDir(); // Write a cookie in headful chrome - const headfulContext = await browserType.launchPersistentContext(userDataDir, {...defaultBrowserOptions, headless: false}); + const headfulContext = await browserType.launchPersistentContext(userDataDir, {...browserOptions, headless: false}); const headfulPage = await headfulContext.newPage(); await headfulPage.goto(server.EMPTY_PAGE); await headfulPage.evaluate(() => document.cookie = 'foo=true; expires=Fri, 31 Dec 9999 23:59:59 GMT'); await headfulContext.close(); // Read the cookie from headless chrome - const headlessContext = await browserType.launchPersistentContext(userDataDir, {...defaultBrowserOptions, headless: true}); + const headlessContext = await browserType.launchPersistentContext(userDataDir, {...browserOptions, headless: true}); const headlessPage = await headlessContext.newPage(); await headlessPage.goto(server.EMPTY_PAGE); const cookie = await headlessPage.evaluate(() => document.cookie); @@ -47,8 +47,8 @@ it('headless should be able to read cookies written by headful', (test, { browse it('should close browser with beforeunload page', (test, parameters) => { test.slow(); -}, async ({browserType, defaultBrowserOptions, server, createUserDataDir}) => { - const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...defaultBrowserOptions, headless: false}); +}, async ({browserType, browserOptions, server, createUserDataDir}) => { + const browserContext = await browserType.launchPersistentContext(await createUserDataDir(), {...browserOptions, headless: false}); const page = await browserContext.newPage(); await page.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers @@ -57,8 +57,8 @@ it('should close browser with beforeunload page', (test, parameters) => { await browserContext.close(); }); -it('should not crash when creating second context', async ({browserType, defaultBrowserOptions}) => { - const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); +it('should not crash when creating second context', async ({browserType, browserOptions}) => { + const browser = await browserType.launch({...browserOptions, headless: false }); { const browserContext = await browser.newContext(); await browserContext.newPage(); @@ -72,8 +72,8 @@ it('should not crash when creating second context', async ({browserType, default await browser.close(); }); -it('should click background tab', async ({browserType, defaultBrowserOptions, server}) => { - const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); +it('should click background tab', async ({browserType, browserOptions, server}) => { + const browser = await browserType.launch({...browserOptions, headless: false }); const page = await browser.newPage(); await page.setContent(`empty.html`); await page.click('a'); @@ -81,16 +81,16 @@ it('should click background tab', async ({browserType, defaultBrowserOptions, se await browser.close(); }); -it('should close browser after context menu was triggered', async ({browserType, defaultBrowserOptions, server}) => { - const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); +it('should close browser after context menu was triggered', async ({browserType, browserOptions, server}) => { + const browser = await browserType.launch({...browserOptions, headless: false }); const page = await browser.newPage(); await page.goto(server.PREFIX + '/grid.html'); await page.click('body', {button: 'right'}); await browser.close(); }); -it('should(not) block third party cookies', async ({browserType, defaultBrowserOptions, server, isChromium, isFirefox}) => { - const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); +it('should(not) block third party cookies', async ({browserType, browserOptions, server, isChromium, isFirefox}) => { + const browser = await browserType.launch({...browserOptions, headless: false }); const page = await browser.newPage(); await page.goto(server.EMPTY_PAGE); await page.evaluate(src => { @@ -131,9 +131,9 @@ it('should(not) block third party cookies', async ({browserType, defaultBrowserO it('should not override viewport size when passed null', (test, { browserName }) => { test.fixme(browserName === 'webkit'); -}, async function({browserType, defaultBrowserOptions, server}) { +}, async function({browserType, browserOptions, server}) { // Our WebKit embedder does not respect window features. - const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); + const browser = await browserType.launch({...browserOptions, headless: false }); const context = await browser.newContext({ viewport: null }); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); @@ -150,8 +150,8 @@ it('should not override viewport size when passed null', (test, { browserName }) await browser.close(); }); -it('Page.bringToFront should work', async ({browserType, defaultBrowserOptions}) => { - const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); +it('Page.bringToFront should work', async ({browserType, browserOptions}) => { + const browser = await browserType.launch({...browserOptions, headless: false }); const page1 = await browser.newPage(); await page1.setContent('Page1'); const page2 = await browser.newPage(); diff --git a/test/logger.spec.ts b/test/logger.spec.ts index 4e7b4dd235..b0f7223a30 100644 --- a/test/logger.spec.ts +++ b/test/logger.spec.ts @@ -16,9 +16,9 @@ import { it, expect } from './fixtures'; -it('should log', async ({browserType, defaultBrowserOptions}) => { +it('should log', async ({browserType, browserOptions}) => { const log = []; - const browser = await browserType.launch({...defaultBrowserOptions, logger: { + const browser = await browserType.launch({...browserOptions, logger: { log: (name, severity, message) => log.push({name, severity, message}), isEnabled: (name, severity) => severity !== 'verbose' }}); @@ -30,9 +30,9 @@ it('should log', async ({browserType, defaultBrowserOptions}) => { expect(log.filter(item => item.message.includes('browserType.launch succeeded')).length > 0).toBeTruthy(); }); -it('should log context-level', async ({browserType, defaultBrowserOptions}) => { +it('should log context-level', async ({browserType, browserOptions}) => { const log = []; - const browser = await browserType.launch(defaultBrowserOptions); + const browser = await browserType.launch(browserOptions); const context = await browser.newContext({ logger: { log: (name, severity, message) => log.push({name, severity, message}), diff --git a/test/page-goto.spec.ts b/test/page-goto.spec.ts index bc63196386..80bb2937ff 100644 --- a/test/page-goto.spec.ts +++ b/test/page-goto.spec.ts @@ -361,7 +361,6 @@ it('should not leak listeners during bad navigation', async ({page, server}) => }); 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/playwright.fixtures.ts b/test/playwright.fixtures.ts index ab9e623d63..4c56dd3c2f 100644 --- a/test/playwright.fixtures.ts +++ b/test/playwright.fixtures.ts @@ -23,7 +23,6 @@ import { config, folio as baseFolio } from 'folio'; import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions, Page } from '../index'; -import * as path from 'path'; export { expect, config } from 'folio'; // Test timeout for e2e tests is 30 seconds. @@ -43,8 +42,8 @@ type PlaywrightParameters = { screenshotOnFailure: boolean; // Slows down Playwright operations by the specified amount of milliseconds. slowMo: number; - // Whether to record the execution trace. - trace: boolean; + // Whether to record videos for all tests. + video: boolean; }; @@ -57,7 +56,7 @@ type PlaywrightWorkerFixtures = { // Browser type (Chromium / WebKit / Firefox) browserType: BrowserType; // Default browserType.launch() options. - defaultBrowserOptions: LaunchOptions; + browserOptions: LaunchOptions; // Browser instance, shared for the worker. browser: Browser; // True iff browserName is Chromium @@ -79,7 +78,7 @@ type PlaywrightWorkerFixtures = { type PlaywrightTestFixtures = { // Default browser.newContext() options. - defaultContextOptions: BrowserContextOptions; + contextOptions: BrowserContextOptions; // Factory for creating a context with given additional options. contextFactory: (options?: BrowserContextOptions) => Promise; // Context instance for test. @@ -94,9 +93,9 @@ fixtures.headful.initParameter('Whether to run tests headless or headful', proce fixtures.platform.initParameter('Operating system', process.platform as ('win32' | 'linux' | 'darwin')); fixtures.screenshotOnFailure.initParameter('Generate screenshot on failure', false); fixtures.slowMo.initParameter('Slows down Playwright operations by the specified amount of milliseconds', 0); -fixtures.trace.initParameter('Whether to record the execution trace', !!process.env.TRACING); +fixtures.video.initParameter('Record videos while running tests', false); -fixtures.defaultBrowserOptions.init(async ({ headful, slowMo }, run) => { +fixtures.browserOptions.init(async ({ headful, slowMo }, run) => { await run({ handleSIGINT: false, slowMo, @@ -105,7 +104,7 @@ fixtures.defaultBrowserOptions.init(async ({ headful, slowMo }, run) => { }, { scope: 'worker' }); fixtures.playwright.init(async ({ }, run) => { - const playwright = require('../index'); + const playwright = require('playwright'); await run(playwright); }, { scope: 'worker' }); @@ -114,8 +113,8 @@ fixtures.browserType.init(async ({ playwright, browserName }, run) => { await run(browserType); }, { scope: 'worker' }); -fixtures.browser.init(async ({ browserType, defaultBrowserOptions }, run) => { - const browser = await browserType.launch(defaultBrowserOptions); +fixtures.browser.init(async ({ browserType, browserOptions }, run) => { + const browser = await browserType.launch(browserOptions); await run(browser); await browser.close(); }, { scope: 'worker' }); @@ -144,22 +143,20 @@ fixtures.isLinux.init(async ({ platform }, run) => { await run(platform === 'linux'); }, { scope: 'worker' }); -fixtures.defaultContextOptions.init(async ({ trace, testInfo }, run) => { - if (trace || testInfo.retry) { +fixtures.contextOptions.init(async ({ video, testInfo }, run) => { + if (video) { await run({ - _traceResourcesPath: path.join(config.outputDir, 'trace-resources'), - _tracePath: testInfo.outputPath('playwright.trace'), videosPath: testInfo.outputPath(''), - } as any); + }); } else { await run({}); } }); -fixtures.contextFactory.init(async ({ browser, defaultContextOptions, testInfo, screenshotOnFailure }, run) => { +fixtures.contextFactory.init(async ({ browser, contextOptions, testInfo, screenshotOnFailure }, run) => { const contexts: BrowserContext[] = []; async function contextFactory(options: BrowserContextOptions = {}) { - const context = await browser.newContext({ ...defaultContextOptions, ...options }); + const context = await browser.newContext({ ...contextOptions, ...options }); contexts.push(context); return context; } diff --git a/test/proxy.spec.ts b/test/proxy.spec.ts index c76c28e6e2..59fb030bff 100644 --- a/test/proxy.spec.ts +++ b/test/proxy.spec.ts @@ -18,21 +18,21 @@ import { it, expect } from './fixtures'; import socks from 'socksv5'; -it('should throw for bad server value', async ({browserType, defaultBrowserOptions}) => { +it('should throw for bad server value', async ({browserType, browserOptions}) => { const error = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, // @ts-expect-error server must be a string proxy: { server: 123 } }).catch(e => e); expect(error.message).toContain('proxy.server: expected string, got number'); }); -it('should use proxy', async ({browserType, defaultBrowserOptions, server}) => { +it('should use proxy', async ({browserType, browserOptions, server}) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, proxy: { server: `localhost:${server.PORT}` } }); const page = await browser.newPage(); @@ -41,12 +41,12 @@ it('should use proxy', async ({browserType, defaultBrowserOptions, server}) => { await browser.close(); }); -it('should work with IP:PORT notion', async ({browserType, defaultBrowserOptions, server}) => { +it('should work with IP:PORT notion', async ({browserType, browserOptions, server}) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, proxy: { server: `127.0.0.1:${server.PORT}` } }); const page = await browser.newPage(); @@ -55,7 +55,7 @@ it('should work with IP:PORT notion', async ({browserType, defaultBrowserOptions await browser.close(); }); -it('should authenticate', async ({browserType, defaultBrowserOptions, server}) => { +it('should authenticate', async ({browserType, browserOptions, server}) => { server.setRoute('/target.html', async (req, res) => { const auth = req.headers['proxy-authorization']; if (!auth) { @@ -68,7 +68,7 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) = } }); const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, proxy: { server: `localhost:${server.PORT}`, username: 'user', password: 'secret' } }); const page = await browser.newPage(); @@ -79,7 +79,7 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) = 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}) => { +}, async ({browserType, browserOptions, server}) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); @@ -88,7 +88,7 @@ it('should exclude patterns', (test, { browserName, headful }) => { // // @see https://gist.github.com/CollinChaffin/24f6c9652efb3d6d5ef2f5502720ef00 const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, proxy: { server: `localhost:${server.PORT}`, bypass: '1.non.existent.domain.for.the.test, 2.non.existent.domain.for.the.test, .another.test' } }); @@ -121,7 +121,7 @@ it('should exclude patterns', (test, { browserName, headful }) => { 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 }) => { +}, async ({ browserType, browserOptions, testWorkerIndex }) => { const server = socks.createServer((info, accept, deny) => { let socket; if ((socket = accept(true))) { @@ -143,7 +143,7 @@ it('should use socks proxy', (test, { browserName, platform }) => { server.useAuth(socks.auth.None()); const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, proxy: { server: `socks5://localhost:${socksPort}` } }); const page = await browser.newPage(); @@ -153,9 +153,9 @@ it('should use socks proxy', (test, { browserName, platform }) => { server.close(); }); -it('does launch without a port', async ({ browserType, defaultBrowserOptions }) => { +it('does launch without a port', async ({ browserType, browserOptions }) => { const browser = await browserType.launch({ - ...defaultBrowserOptions, + ...browserOptions, proxy: { server: 'http://localhost' } }); await browser.close(); diff --git a/test/remoteServer.fixture.ts b/test/remoteServer.fixture.ts index 348c5fa535..ad48a39eb7 100644 --- a/test/remoteServer.fixture.ts +++ b/test/remoteServer.fixture.ts @@ -26,16 +26,16 @@ type ServerFixtures = { }; const fixtures = base.extend<{}, ServerFixtures>(); -fixtures.remoteServer.init(async ({ browserType, defaultBrowserOptions }, run) => { +fixtures.remoteServer.init(async ({ browserType, browserOptions }, run) => { const remoteServer = new RemoteServer(); - await remoteServer._start(browserType, defaultBrowserOptions); + await remoteServer._start(browserType, browserOptions); await run(remoteServer); await remoteServer.close(); }); -fixtures.stallingRemoteServer.init(async ({ browserType, defaultBrowserOptions }, run) => { +fixtures.stallingRemoteServer.init(async ({ browserType, browserOptions }, run) => { const remoteServer = new RemoteServer(); - await remoteServer._start(browserType, defaultBrowserOptions, { stallOnClose: true }); + await remoteServer._start(browserType, browserOptions, { stallOnClose: true }); await run(remoteServer); await remoteServer.close(); }); @@ -55,17 +55,17 @@ export class RemoteServer { _didExit: boolean; _wsEndpoint: string; - async _start(browserType: BrowserType, defaultBrowserOptions: LaunchOptions, extraOptions?: { stallOnClose: boolean; }) { + async _start(browserType: BrowserType, browserOptions: LaunchOptions, extraOptions?: { stallOnClose: boolean; }) { this._output = new Map(); this._outputCallback = new Map(); this._didExit = false; this._browserType = browserType; - const launchOptions = {...defaultBrowserOptions, + const launchOptions = {...browserOptions, handleSIGINT: true, handleSIGTERM: true, handleSIGHUP: true, - executablePath: defaultBrowserOptions.executablePath || browserType.executablePath(), + executablePath: browserOptions.executablePath || browserType.executablePath(), logger: undefined, }; const options = {