diff --git a/tests/beforeunload.spec.ts b/tests/beforeunload.spec.ts index f0cd52a93e..3f7aff04b7 100644 --- a/tests/beforeunload.spec.ts +++ b/tests/beforeunload.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; it('should close browser with beforeunload page', async ({server, browserType, browserOptions }) => { const browser = await browserType.launch(browserOptions); @@ -27,18 +27,15 @@ it('should close browser with beforeunload page', async ({server, browserType, b await browser.close(); }); -it('should close browsercontext with beforeunload page', async ({server, contextFactory }) => { - const browserContext = await contextFactory(); - const page = await browserContext.newPage(); +it('should close browsercontext with beforeunload page', async ({server, page, context }) => { await page.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers // fire. await page.click('body'); - await browserContext.close(); + await context.close(); }); -it('should close page with beforeunload listener', async ({contextFactory, server}) => { - const context = await contextFactory(); +it('should close page with beforeunload listener', async ({context, server}) => { const newPage = await context.newPage(); await newPage.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers @@ -47,8 +44,7 @@ it('should close page with beforeunload listener', async ({contextFactory, serve await newPage.close(); }); -it('should run beforeunload if asked for', async ({contextFactory, server, isChromium, isWebKit}) => { - const context = await contextFactory(); +it('should run beforeunload if asked for', async ({context, server, isChromium, isWebKit}) => { const newPage = await context.newPage(); await newPage.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers @@ -72,9 +68,7 @@ it('should run beforeunload if asked for', async ({contextFactory, server, isChr ]); }); -it('should access page after beforeunload', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); +it('should access page after beforeunload', async ({page, server}) => { await page.goto(server.PREFIX + '/beforeunload.html'); // We have to interact with a page so that 'beforeunload' handlers // fire. diff --git a/tests/browsercontext-add-cookies.spec.ts b/tests/browsercontext-add-cookies.spec.ts index cd436ce1b8..6d940ac5ad 100644 --- a/tests/browsercontext-add-cookies.spec.ts +++ b/tests/browsercontext-add-cookies.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { contextTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; import { slowTest as playwrightTest } from './config/playwrightTest'; it('should work', async ({context, page, server}) => { diff --git a/tests/browsercontext-add-init-script.spec.ts b/tests/browsercontext-add-init-script.spec.ts index 86c5705ddc..e8cea134c8 100644 --- a/tests/browsercontext-add-init-script.spec.ts +++ b/tests/browsercontext-add-init-script.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { contextTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; it('should work with browser context scripts', async ({ context, server }) => { await context.addInitScript(() => window['temp'] = 123); diff --git a/tests/browsercontext-clearcookies.spec.ts b/tests/browsercontext-clearcookies.spec.ts index 78427795c6..ec172824bf 100644 --- a/tests/browsercontext-clearcookies.spec.ts +++ b/tests/browsercontext-clearcookies.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { contextTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; it('should clear cookies', async ({context, page, server}) => { await page.goto(server.EMPTY_PAGE); diff --git a/tests/browsercontext-cookies.spec.ts b/tests/browsercontext-cookies.spec.ts index c2443e4e30..0301198858 100644 --- a/tests/browsercontext-cookies.spec.ts +++ b/tests/browsercontext-cookies.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { contextTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; it('should return no cookies in pristine browser context', async ({context, page, server}) => { expect(await context.cookies()).toEqual([]); diff --git a/tests/browsercontext-expose-function.spec.ts b/tests/browsercontext-expose-function.spec.ts index 0823a2fb9f..0c10c278d7 100644 --- a/tests/browsercontext-expose-function.spec.ts +++ b/tests/browsercontext-expose-function.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { contextTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; it('expose binding should work', async ({context}) => { let bindingSource; diff --git a/tests/browsercontext-proxy.spec.ts b/tests/browsercontext-proxy.spec.ts index 71dbee955a..a7319f4e0c 100644 --- a/tests/browsercontext-proxy.spec.ts +++ b/tests/browsercontext-proxy.spec.ts @@ -14,7 +14,17 @@ * limitations under the License. */ -import { proxyTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/browserTest'; +import type { Browser } from '../index'; + +let browser: Browser; +it.beforeEach(async ({ browserType, browserOptions }) => { + if (!browser) + browser = await browserType.launch({ ...browserOptions, proxy: { server: 'per-context' } }); +}); +it.afterAll(async () => { + await browser.close(); +}); it('should throw for missing global proxy', async ({ browserType, browserOptions, server }) => { delete browserOptions.proxy; @@ -24,8 +34,8 @@ it('should throw for missing global proxy', async ({ browserType, browserOptions await browser.close(); }); -it('should throw for bad server value', async ({ contextFactory, contextOptions }) => { - const error = await contextFactory({ +it('should throw for bad server value', async ({ contextOptions }) => { + const error = await browser.newContext({ ...contextOptions, // @ts-expect-error server must be a string proxy: { server: 123 } @@ -33,86 +43,86 @@ it('should throw for bad server value', async ({ contextFactory, contextOptions expect(error.message).toContain('proxy.server: expected string, got number'); }); -it('should use proxy', async ({ contextFactory, contextOptions, server }) => { +it('should use proxy', async ({ contextOptions, server }) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}` } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com/target.html'); expect(await page.title()).toBe('Served by the proxy'); - await browser.close(); + await context.close(); }); -it('should use proxy twice', async ({ contextFactory, contextOptions, server }) => { +it('should use proxy twice', async ({ contextOptions, server }) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}` } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com/target.html'); await page.goto('http://non-existent-2.com/target.html'); expect(await page.title()).toBe('Served by the proxy'); - await browser.close(); + await context.close(); }); -it('should use proxy for second page', async ({contextFactory, contextOptions, server}) => { +it('should use proxy for second page', async ({contextOptions, server}) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}` } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com/target.html'); expect(await page.title()).toBe('Served by the proxy'); - const page2 = await browser.newPage(); + const page2 = await context.newPage(); await page2.goto('http://non-existent.com/target.html'); expect(await page2.title()).toBe('Served by the proxy'); - await browser.close(); + await context.close(); }); -it('should work with IP:PORT notion', async ({contextFactory, contextOptions, server}) => { +it('should work with IP:PORT notion', async ({contextOptions, server}) => { server.setRoute('/target.html', async (req, res) => { res.end('Served by the proxy'); }); - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `127.0.0.1:${server.PORT}` } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com/target.html'); expect(await page.title()).toBe('Served by the proxy'); - await browser.close(); + await context.close(); }); -it('should throw for socks5 authentication', async ({contextFactory, contextOptions}) => { - const error = await contextFactory({ +it('should throw for socks5 authentication', async ({contextOptions}) => { + const error = await browser.newContext({ ...contextOptions, proxy: { server: `socks5://localhost:1234`, username: 'user', password: 'secret' } }).catch(e => e); expect(error.message).toContain('Browser does not support socks5 proxy authentication'); }); -it('should throw for socks4 authentication', async ({contextFactory, contextOptions}) => { - const error = await contextFactory({ +it('should throw for socks4 authentication', async ({contextOptions}) => { + const error = await browser.newContext({ ...contextOptions, proxy: { server: `socks4://localhost:1234`, username: 'user', password: 'secret' } }).catch(e => e); expect(error.message).toContain('Socks4 proxy protocol does not support authentication'); }); -it('should authenticate', async ({contextFactory, contextOptions, server}) => { +it('should authenticate', async ({contextOptions, server}) => { server.setRoute('/target.html', async (req, res) => { const auth = req.headers['proxy-authorization']; if (!auth) { @@ -124,17 +134,17 @@ it('should authenticate', async ({contextFactory, contextOptions, server}) => { res.end(`${auth}`); } }); - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}`, username: 'user', password: 'secret' } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com/target.html'); expect(await page.title()).toBe('Basic ' + Buffer.from('user:secret').toString('base64')); - await browser.close(); + await context.close(); }); -it('should authenticate with empty password', async ({contextFactory, contextOptions, server}) => { +it('should authenticate with empty password', async ({contextOptions, server}) => { server.setRoute('/target.html', async (req, res) => { const auth = req.headers['proxy-authorization']; if (!auth) { @@ -146,18 +156,18 @@ it('should authenticate with empty password', async ({contextFactory, contextOpt res.end(`${auth}`); } }); - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}`, username: 'user', password: '' } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com/target.html'); expect(await page.title()).toBe('Basic ' + Buffer.from('user:').toString('base64')); - await browser.close(); + await context.close(); }); -it('should isolate proxy credentials between contexts', async ({contextFactory, contextOptions, server, browserName}) => { +it('should isolate proxy credentials between contexts', async ({contextOptions, server, browserName}) => { it.fixme(browserName === 'firefox', 'Credentials from the first context stick around'); server.setRoute('/target.html', async (req, res) => { @@ -172,7 +182,7 @@ it('should isolate proxy credentials between contexts', async ({contextFactory, } }); { - const context = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}`, username: 'user1', password: 'secret1' } }); @@ -182,7 +192,7 @@ it('should isolate proxy credentials between contexts', async ({contextFactory, await context.close(); } { - const context = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}`, username: 'user2', password: 'secret2' } }); @@ -193,7 +203,7 @@ it('should isolate proxy credentials between contexts', async ({contextFactory, } }); -it('should exclude patterns', async ({contextFactory, contextOptions, server, browserName, headful}) => { +it('should exclude patterns', async ({contextOptions, server, browserName, headful}) => { it.fixme(browserName === 'chromium' && headful, 'Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.'); server.setRoute('/target.html', async (req, res) => { @@ -203,12 +213,12 @@ it('should exclude patterns', async ({contextFactory, contextOptions, server, br // that resolves everything to some weird search results page. // // @see https://gist.github.com/CollinChaffin/24f6c9652efb3d6d5ef2f5502720ef00 - const browser = await contextFactory({ + const context = await browser.newContext({ ...contextOptions, proxy: { server: `localhost:${server.PORT}`, bypass: '1.non.existent.domain.for.the.test, 2.non.existent.domain.for.the.test, .another.test' } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://0.non.existent.domain.for.the.test/target.html'); expect(await page.title()).toBe('Served by the proxy'); @@ -232,41 +242,41 @@ it('should exclude patterns', async ({contextFactory, contextOptions, server, br expect(await page.title()).toBe('Served by the proxy'); } - await browser.close(); + await context.close(); }); -it('should use socks proxy', async ({ contextFactory, contextOptions, socksPort }) => { - const browser = await contextFactory({ +it('should use socks proxy', async ({ contextOptions, socksPort }) => { + const context = await browser.newContext({ ...contextOptions, proxy: { server: `socks5://localhost:${socksPort}` } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com'); expect(await page.title()).toBe('Served by the SOCKS proxy'); - await browser.close(); + await context.close(); }); -it('should use socks proxy in second page', async ({ contextFactory, contextOptions, socksPort }) => { - const browser = await contextFactory({ +it('should use socks proxy in second page', async ({ contextOptions, socksPort }) => { + const context = await browser.newContext({ ...contextOptions, proxy: { server: `socks5://localhost:${socksPort}` } }); - const page = await browser.newPage(); + const page = await context.newPage(); await page.goto('http://non-existent.com'); expect(await page.title()).toBe('Served by the SOCKS proxy'); - const page2 = await browser.newPage(); + const page2 = await context.newPage(); await page2.goto('http://non-existent.com'); expect(await page2.title()).toBe('Served by the SOCKS proxy'); - await browser.close(); + await context.close(); }); -it('does launch without a port', async ({ contextFactory, contextOptions }) => { - const browser = await contextFactory({ +it('does launch without a port', async ({ contextOptions }) => { + const context = await browser.newContext({ ...contextOptions, proxy: { server: 'http://localhost' } }); - await browser.close(); + await context.close(); }); diff --git a/tests/capabilities.spec.ts b/tests/capabilities.spec.ts index c00e80c4fc..a76f3d3751 100644 --- a/tests/capabilities.spec.ts +++ b/tests/capabilities.spec.ts @@ -16,20 +16,16 @@ import os from 'os'; import url from 'url'; -import { test as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; -it('Web Assembly should work', async function({contextFactory, server, browserName, platform}) { +it('Web Assembly should work', async function({page, server, browserName, platform}) { it.fail(browserName === 'webkit' && platform === 'win32'); - const context = await contextFactory(); - const page = await context.newPage(); await page.goto(server.PREFIX + '/wasm/table2.html'); expect(await page.evaluate('loadTable()')).toBe('42, 83'); }); -it('WebSocket should work', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); +it('WebSocket should work', async ({page, server}) => { const value = await page.evaluate(port => { let cb; const result = new Promise(f => cb = f); @@ -41,7 +37,7 @@ it('WebSocket should work', async ({contextFactory, server}) => { expect(value).toBe('incoming'); }); -it('should respect CSP', async ({contextFactory, server}) => { +it('should respect CSP', async ({page, server}) => { server.setRoute('/empty.html', async (req, res) => { res.setHeader('Content-Security-Policy', `script-src 'unsafe-inline';`); res.end(` @@ -51,22 +47,17 @@ it('should respect CSP', async ({contextFactory, server}) => { `); }); - const context = await contextFactory(); - const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); expect(await page.evaluate(() => window['testStatus'])).toBe('SUCCESS'); }); -it('should play video', async ({contextFactory, asset, isWebKit, browserName, platform}) => { +it('should play video', async ({page, asset, isWebKit, browserName, platform}) => { // TODO: the test passes on Windows locally but fails on GitHub Action bot, // apparently due to a Media Pack issue in the Windows Server. // Also the test is very flaky on Linux WebKit. it.fixme(browserName === 'webkit' && platform !== 'darwin'); it.fixme(browserName === 'webkit' && platform === 'darwin' && parseInt(os.release(), 10) >= 20, 'Does not work on BigSur'); - const context = await contextFactory(); - const page = await context.newPage(); - // Safari only plays mp4 so we test WebKit with an .mp4 clip. const fileName = isWebKit ? 'video_mp4.html' : 'video.html'; const absolutePath = asset(fileName); @@ -77,11 +68,9 @@ it('should play video', async ({contextFactory, asset, isWebKit, browserName, pl await page.$eval('video', v => v.pause()); }); -it('should support webgl', async ({contextFactory, browserName, headful}) => { +it('should support webgl', async ({page, browserName, headful}) => { it.fixme(browserName === 'firefox' && !headful); - const context = await contextFactory(); - const page = await context.newPage(); const hasWebGL = await page.evaluate(() => { const canvas = document.createElement('canvas'); return !!canvas.getContext('webgl'); @@ -89,13 +78,11 @@ it('should support webgl', async ({contextFactory, browserName, headful}) => { expect(hasWebGL).toBe(true); }); -it('should support webgl 2', async ({contextFactory, browserName, headful}) => { +it('should support webgl 2', async ({page, browserName, headful}) => { it.skip(browserName === 'webkit', 'WebKit doesn\'t have webgl2 enabled yet upstream.'); it.fixme(browserName === 'firefox' && !headful); it.fixme(browserName === 'chromium' && headful, 'chromium doesn\'t like webgl2 when running under xvfb'); - const context = await contextFactory(); - const page = await context.newPage(); const hasWebGL2 = await page.evaluate(() => { const canvas = document.createElement('canvas'); return !!canvas.getContext('webgl2'); diff --git a/tests/config/browserTest.ts b/tests/config/browserTest.ts index 932a4d4a4d..44fd8b5396 100644 --- a/tests/config/browserTest.ts +++ b/tests/config/browserTest.ts @@ -15,7 +15,7 @@ */ import { newTestType } from 'folio'; -import type { Browser, BrowserContextOptions, BrowserContext, Page } from '../../index'; +import type { Browser, BrowserContextOptions, BrowserContext } from '../../index'; import type { PlaywrightTestArgs } from './playwrightTest'; import type { ServerTestArgs } from './serverTest'; export { expect } from 'folio'; @@ -28,11 +28,3 @@ export type BrowserTestArgs = PlaywrightTestArgs & { export const test = newTestType(); export const slowTest = newTestType(); -export const proxyTest = newTestType(); - -// Context test guarantees an isolated context. -export type ContextTestArgs = BrowserTestArgs & { - context: BrowserContext; - page: Page; -}; -export const contextTest = newTestType(); diff --git a/tests/config/contextTest.ts b/tests/config/contextTest.ts new file mode 100644 index 0000000000..9885e20b9a --- /dev/null +++ b/tests/config/contextTest.ts @@ -0,0 +1,28 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { newTestType } from 'folio'; +import type { BrowserContext, Page } from '../../index'; +import type { BrowserTestArgs } from './browserTest'; +import type { ServerTestArgs } from './serverTest'; +export { expect } from 'folio'; + +// Context test guarantees an isolated context. +export type ContextTestArgs = BrowserTestArgs & { + context: BrowserContext; + page: Page; +}; +export const test = newTestType(); diff --git a/tests/config/default.config.ts b/tests/config/default.config.ts index 3e6d12a3d5..a050f26871 100644 --- a/tests/config/default.config.ts +++ b/tests/config/default.config.ts @@ -17,7 +17,8 @@ import { setConfig, Config } from 'folio'; import * as path from 'path'; import { test as playwrightTest, slowTest as playwrightSlowTest } from './playwrightTest'; -import { test as browserTest, contextTest, proxyTest, slowTest as browserSlowTest } from './browserTest'; +import { test as browserTest, slowTest as browserSlowTest } from './browserTest'; +import { test as contextTest } from './contextTest'; import { test as pageTest } from './pageTest'; import { test as electronTest } from './electronTest'; import { test as cliTest } from './cliTest'; @@ -67,10 +68,7 @@ for (const browserName of browsers) { playwrightSlowTest.runWith(browserName, serverEnv, new PlaywrightEnv(browserName, options), { timeout: config.timeout * 3 }); browserTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, options), {}); browserSlowTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, options), { timeout: config.timeout * 3 }); - // TODO: perhaps export proxyTest from the test file? - proxyTest.runWith(browserName, serverEnv, new BrowserEnv(browserName, { ...options, proxy: { server: 'per-context' } }), {}); pageTest.runWith(browserName, serverEnv, new PageEnv(browserName, options), {}); - // TODO: get rid of contextTest if there isn't too many of them. contextTest.runWith(browserName, serverEnv, new PageEnv(browserName, options), {}); if (mode !== 'service') cliTest.runWith(browserName, serverEnv, new CLIEnv(browserName, options), {}); diff --git a/tests/favicon.spec.ts b/tests/favicon.spec.ts index f968c21b34..1d66b65f8f 100644 --- a/tests/favicon.spec.ts +++ b/tests/favicon.spec.ts @@ -15,15 +15,12 @@ * limitations under the License. */ -import { test as it } from './config/browserTest'; +import { test as it } from './config/contextTest'; -it('should load svg favicon with prefer-color-scheme', async ({contextFactory, server, browserName, browserChannel, headful, asset}) => { +it('should load svg favicon with prefer-color-scheme', async ({page, server, browserName, browserChannel, headful, asset}) => { it.skip(!headful && browserName !== 'firefox', 'headless browsers, except firefox, do not request favicons'); it.skip(headful && browserName === 'webkit' && !browserChannel, 'playwright headful webkit does not have a favicon feature'); - const context = await contextFactory(); - const page = await context.newPage(); - // Browsers aggresively cache favicons, so force bust with the // `d` parameter to make iterating on this test more predictable and isolated. const favicon = `/favicon.svg?d=${Date.now()}`; @@ -59,6 +56,4 @@ it('should load svg favicon with prefer-color-scheme', async ({contextFactory, s await page.waitForTimeout(500); // Text still being around ensures we haven't actually lost our browser to a crash. await page.waitForSelector('text=favicons'); - - await page.close(); }); diff --git a/tests/permissions.spec.ts b/tests/permissions.spec.ts index e8303017b5..34113e39db 100644 --- a/tests/permissions.spec.ts +++ b/tests/permissions.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; function getPermission(page, name) { return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name); @@ -26,91 +26,64 @@ it.describe('permissions', () => { it.skip(browserName === 'webkit', 'Permissions API is not implemented in WebKit (see https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)'); }); - it('should be prompt by default', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should be prompt by default', async ({page, server}) => { await page.goto(server.EMPTY_PAGE); expect(await getPermission(page, 'geolocation')).toBe('prompt'); - await context.close(); }); - it('should deny permission when not listed', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should deny permission when not listed', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions([], { origin: server.EMPTY_PAGE }); expect(await getPermission(page, 'geolocation')).toBe('denied'); - await context.close(); }); - it('should fail when bad permission is given', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should fail when bad permission is given', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); let error: Error; await context.grantPermissions(['foo'], { origin: server.EMPTY_PAGE }).catch(e => error = e); expect(error.message).toContain('Unknown permission: foo'); - await context.close(); }); - it('should grant geolocation permission when origin is listed', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should grant geolocation permission when origin is listed', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); expect(await getPermission(page, 'geolocation')).toBe('granted'); - await context.close(); }); - it('should prompt for geolocation permission when origin is not listed', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should prompt for geolocation permission when origin is not listed', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); await page.goto(server.EMPTY_PAGE.replace('localhost', '127.0.0.1')); expect(await getPermission(page, 'geolocation')).toBe('prompt'); - await context.close(); }); - it('should grant notifications permission when listed', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should grant notifications permission when listed', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['notifications'], { origin: server.EMPTY_PAGE }); expect(await getPermission(page, 'notifications')).toBe('granted'); - await context.close(); }); - it('should accumulate when adding', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should accumulate when adding', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['geolocation']); await context.grantPermissions(['notifications']); expect(await getPermission(page, 'geolocation')).toBe('granted'); expect(await getPermission(page, 'notifications')).toBe('granted'); - await context.close(); }); - it('should clear permissions', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should clear permissions', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['geolocation']); await context.clearPermissions(); await context.grantPermissions(['notifications']); expect(await getPermission(page, 'geolocation')).not.toBe('granted'); expect(await getPermission(page, 'notifications')).toBe('granted'); - await context.close(); }); - it('should grant permission when listed for all domains', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should grant permission when listed for all domains', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['geolocation']); expect(await getPermission(page, 'geolocation')).toBe('granted'); - await context.close(); }); it('should grant permission when creating context', async ({server, browser}) => { @@ -121,23 +94,18 @@ it.describe('permissions', () => { await context.close(); }); - it('should reset permissions', async ({contextFactory, server}) => { - const context = await contextFactory(); - const page = await context.newPage(); + it('should reset permissions', async ({page, context, server}) => { await page.goto(server.EMPTY_PAGE); await context.grantPermissions(['geolocation'], { origin: server.EMPTY_PAGE }); expect(await getPermission(page, 'geolocation')).toBe('granted'); await context.clearPermissions(); expect(await getPermission(page, 'geolocation')).toBe('prompt'); - await context.close(); }); - it('should trigger permission onchange', async ({contextFactory, server, browserName, headful}) => { + it('should trigger permission onchange', async ({page, context, server, browserName, headful}) => { it.fail(browserName === 'webkit'); it.fail(browserName === 'chromium' && headful); - const context = await contextFactory(); - const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); await page.evaluate(() => { window['events'] = []; @@ -155,7 +123,6 @@ it.describe('permissions', () => { expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted']); await context.clearPermissions(); expect(await page.evaluate(() => window['events'])).toEqual(['prompt', 'denied', 'granted', 'prompt']); - await context.close(); }); it('should isolate permissions between browser contexts', async ({server, browser}) => { @@ -180,13 +147,11 @@ it.describe('permissions', () => { await context.close(); }); - it('should support clipboard read', async ({contextFactory, server, browserName, headful}) => { + it('should support clipboard read', async ({page, context, server, browserName, headful}) => { it.fail(browserName === 'webkit'); it.fail(browserName === 'firefox', 'No such permissions (requires flag) in Firefox'); it.fixme(browserName === 'chromium' && headful); - const context = await contextFactory(); - const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); expect(await getPermission(page, 'clipboard-read')).toBe('prompt'); let error; @@ -195,6 +160,5 @@ it.describe('permissions', () => { await context.grantPermissions(['clipboard-read']); expect(await getPermission(page, 'clipboard-read')).toBe('granted'); await page.evaluate(() => navigator.clipboard.readText()); - await context.close(); }); }); diff --git a/tests/selector-generator.spec.ts b/tests/selector-generator.spec.ts index ce06b91e4d..7e246c4a4b 100644 --- a/tests/selector-generator.spec.ts +++ b/tests/selector-generator.spec.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { contextTest as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; import type { Page, Frame } from '../index'; async function generate(pageOrFrame: Page | Frame, target: string): Promise { diff --git a/tests/snapshotter.spec.ts b/tests/snapshotter.spec.ts index f57f194d80..c724e0b43f 100644 --- a/tests/snapshotter.spec.ts +++ b/tests/snapshotter.spec.ts @@ -14,45 +14,39 @@ * limitations under the License. */ -import { test as it, expect } from './config/browserTest'; +import { test as it, expect } from './config/contextTest'; import { InMemorySnapshotter } from '../lib/server/snapshot/inMemorySnapshotter'; import { HttpServer } from '../lib/utils/httpServer'; import { SnapshotServer } from '../lib/server/snapshot/snapshotServer'; -import type { BrowserContext, Page } from '../index'; it.describe('snapshots', () => { - let context: BrowserContext; - let page: Page; let snapshotter: any; let httpServer: any; let snapshotPort: number; - it.beforeEach(async ({ mode, toImpl, contextFactory }, testInfo) => { + it.beforeEach(async ({ mode, toImpl, context }, testInfo) => { it.skip(mode !== 'default'); - context = await contextFactory(); - page = await context.newPage(); snapshotter = new InMemorySnapshotter(toImpl(context)); await snapshotter.initialize(); httpServer = new HttpServer(); new SnapshotServer(httpServer, snapshotter); - snapshotPort = 9700 + testInfo.workerIndex; + snapshotPort = 11000 + testInfo.workerIndex; httpServer.start(snapshotPort); }); it.afterEach(async () => { await snapshotter.dispose(); httpServer.stop(); - await context.close(); }); - it('should collect snapshot', async ({ toImpl }) => { + it('should collect snapshot', async ({ page, toImpl }) => { await page.setContent(''); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot'); expect(distillSnapshot(snapshot)).toBe(''); }); - it('should capture resources', async ({ toImpl, server }) => { + it('should capture resources', async ({ page, toImpl, server }) => { await page.goto(server.EMPTY_PAGE); await page.route('**/style.css', route => { route.fulfill({ body: 'button { color: red; }', }).catch(() => {}); @@ -64,7 +58,7 @@ it.describe('snapshots', () => { expect(resources[cssHref]).toBeTruthy(); }); - it('should collect multiple', async ({ toImpl }) => { + it('should collect multiple', async ({ page, toImpl }) => { await page.setContent(''); const snapshots = []; snapshotter.on('snapshot', snapshot => snapshots.push(snapshot)); @@ -73,7 +67,7 @@ it.describe('snapshots', () => { expect(snapshots.length).toBe(2); }); - it('should only collect on change', async ({}) => { + it('should only collect on change', async ({ page }) => { await page.setContent(''); const snapshots = []; snapshotter.on('snapshot', snapshot => snapshots.push(snapshot)); @@ -88,7 +82,7 @@ it.describe('snapshots', () => { expect(snapshots.length).toBe(2); }); - it('should respect inline CSSOM change', async ({}) => { + it('should respect inline CSSOM change', async ({ page }) => { await page.setContent(''); const snapshots = []; snapshotter.on('snapshot', snapshot => snapshots.push(snapshot)); @@ -107,7 +101,7 @@ it.describe('snapshots', () => { expect(distillSnapshot(snapshots[1])).toBe(''); }); - it('should respect subresource CSSOM change', async ({ server }) => { + it('should respect subresource CSSOM change', async ({ page, server }) => { await page.goto(server.EMPTY_PAGE); await page.route('**/style.css', route => { route.fulfill({ body: 'button { color: red; }', }).catch(() => {}); @@ -134,7 +128,7 @@ it.describe('snapshots', () => { expect(snapshotter.resourceContent(sha1).toString()).toBe('button { color: blue; }'); }); - it('should capture iframe', async ({ contextFactory, server, toImpl, browserName }) => { + it('should capture iframe', async ({ page, contextFactory, server, toImpl, browserName }) => { it.skip(browserName === 'firefox'); await page.route('**/empty.html', route => { @@ -175,7 +169,7 @@ it.describe('snapshots', () => { expect(await button.textContent()).toBe('Hello iframe'); }); - it('should capture snapshot target', async ({ toImpl }) => { + it('should capture snapshot target', async ({ page, toImpl }) => { await page.setContent(''); { const handle = await page.$('text=Hello'); @@ -189,7 +183,7 @@ it.describe('snapshots', () => { } }); - it('should collect on attribute change', async ({ toImpl }) => { + it('should collect on attribute change', async ({ page, toImpl }) => { await page.setContent(''); { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot');