From 2744cd6c9a6bd48a7a29aef389cd9d8ef6c17c6e Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 10 Aug 2021 09:26:36 -0700 Subject: [PATCH] feat(test runner): remove createContext fixture (#8109) We can now use `browser.newContext()` or `browser.newPage()` instead. --- docs/src/test-api/class-fixtures.md | 60 ----------------- src/test/index.ts | 43 +++++-------- .../playwright.artifacts.spec.ts | 13 ++-- types/test.d.ts | 64 ------------------- 4 files changed, 22 insertions(+), 158 deletions(-) diff --git a/docs/src/test-api/class-fixtures.md b/docs/src/test-api/class-fixtures.md index f79b17687c..adec232fb0 100644 --- a/docs/src/test-api/class-fixtures.md +++ b/docs/src/test-api/class-fixtures.md @@ -137,66 +137,6 @@ Learn how to [configure context](./test-configuration.md) through other fixtures The [`property: Fixtures.page`] belongs to this context. -## property: Fixtures.createContext -- type: <[function]\([BrowserContextOptions]|[void]\):[BrowserContext]> - -A function that creates a new context, taking into account all options set -through [configuration file](./test-configuration.md) or [`method: Test.use`] calls. All contexts created by this function are similar to the default [`property: Fixtures.context`]. - -This function is useful for multi-context scenarios, for example testing -two users talking over the chat application. - -A single `options` argument will be merged with all the default options from [configuration file](./test-configuration.md) or [`method: Test.use`] calls and passed to [`method: Browser.newContext`]. If you'd like to undo some of these options, override them with some value or `undefined`. For example: - -```js js-flavor=ts -// example.spec.ts - -import { test } from '@playwright/test'; - -// All contexts will use this storage state. -test.use({ storageState: 'state.json' }); - -test('my test', async ({ createContext }) => { - // An isolated context - const context1 = await createContext(); - - // Another isolated context with custom options - const context2 = await createContext({ - // Undo 'state.json' from above - storageState: undefined, - // Set custom locale - locale: 'en-US', - }); - - // ... -}); -``` - -```js js-flavor=js -// example.spec.js -// @ts-check - -const { test } = require('@playwright/test'); - -// All contexts will use this storage state. -test.use({ storageState: 'state.json' }); - -test('my test', async ({ createContext }) => { - // An isolated context - const context1 = await createContext(); - - // Another isolated context with custom options - const context2 = await createContext({ - // Undo 'state.json' from above - storageState: undefined, - // Set custom locale - locale: 'en-US', - }); - - // ... -}); -``` - ## property: Fixtures.contextOptions - type: <[Object]> diff --git a/src/test/index.ts b/src/test/index.ts index 0e26538823..58d2a09587 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -284,36 +284,31 @@ export const test = _baseTest.extend({ })); }, { auto: true }], - createContext: async ({ browser, video, _artifactsDir }, use, testInfo) => { + context: async ({ browser, video, _artifactsDir }, use, testInfo) => { + if (testInfo.title === 'beforeAll' || testInfo.title === 'afterAll') + throw new Error(`"context" and "page" fixtures are not suppoted in ${testInfo.title}. Use browser.newContext() instead.`); + let videoMode = typeof video === 'string' ? video : video.mode; if (videoMode === 'retry-with-video') videoMode = 'on-first-retry'; const captureVideo = (videoMode === 'on' || videoMode === 'retain-on-failure' || (videoMode === 'on-first-retry' && testInfo.retry === 1)); + const videoOptions: BrowserContextOptions = captureVideo ? { + recordVideo: { + dir: _artifactsDir(), + size: typeof video === 'string' ? undefined : video.size, + } + } : {}; + const context = await browser.newContext(videoOptions); - const allContexts: BrowserContext[] = []; const allPages: Page[] = []; + context.on('page', page => allPages.push(page)); - await use(async (additionalOptions = {}) => { - let recordVideoDir: string | null = null; - const recordVideoSize = typeof video === 'string' ? undefined : video.size; - if (captureVideo) - recordVideoDir = _artifactsDir(); + await use(context); - const combinedOptions: BrowserContextOptions = { - recordVideo: recordVideoDir ? { dir: recordVideoDir, size: recordVideoSize } : undefined, - ...additionalOptions, - }; - const context = await browser.newContext(combinedOptions); - context.on('page', page => allPages.push(page)); - - allContexts.push(context); - return context; - }); - - const prependToError = (testInfo.status === 'timedOut' && allContexts.length) ? - formatPendingCalls((allContexts[0] as any)._connection.pendingProtocolCalls()) : ''; - await Promise.all(allContexts.map(context => context.close())); + const prependToError = testInfo.status === 'timedOut' ? + formatPendingCalls((context as any)._connection.pendingProtocolCalls()) : ''; + await context.close(); if (prependToError) { if (!testInfo.error) { testInfo.error = { value: prependToError }; @@ -343,12 +338,6 @@ export const test = _baseTest.extend({ } }, - context: async ({ createContext }, use, testInfo) => { - if (testInfo.title === 'beforeAll' || testInfo.title === 'afterAll') - throw new Error(`"context" and "page" fixtures are not suppoted in ${testInfo.title}. Use browser.newContext() instead.`); - await use(await createContext()); - }, - page: async ({ context }, use) => { await use(await context.newPage()); }, diff --git a/tests/playwright-test/playwright.artifacts.spec.ts b/tests/playwright-test/playwright.artifacts.spec.ts index b00c7c3e18..ca460a22d1 100644 --- a/tests/playwright-test/playwright.artifacts.spec.ts +++ b/tests/playwright-test/playwright.artifacts.spec.ts @@ -63,12 +63,12 @@ const testFiles = { await page.setContent('I am the page'); }); - test('two contexts', async ({ page, createContext }) => { + test('two contexts', async ({ page, browser }) => { await page.setContent('I am the page'); - const context2 = await createContext(); - const page2 = await context2.newPage(); + const page2 = await browser.newPage(); await page2.setContent('I am the page'); + await page2.close(); }); test('failing', async ({ page }) => { @@ -76,14 +76,13 @@ const testFiles = { expect(1).toBe(2); }); - test('two contexts failing', async ({ page, createContext }) => { + test('two contexts failing', async ({ page, browser }) => { await page.setContent('I am the page'); - const context2 = await createContext(); - const page2 = await context2.newPage(); + const page2 = await browser.newPage(); await page2.setContent('I am the page'); - expect(1).toBe(2); + await page2.close(); }); test('own context passing', async ({ browser }) => { diff --git a/types/test.d.ts b/types/test.d.ts index 4b09f5d5c3..82eb5dce63 100644 --- a/types/test.d.ts +++ b/types/test.d.ts @@ -2720,70 +2720,6 @@ export interface PlaywrightWorkerArgs { * */ export interface PlaywrightTestArgs { - /** - * A function that creates a new context, taking into account all options set through - * [configuration file](https://playwright.dev/docs/test-configuration) or - * [test.use(fixtures)](https://playwright.dev/docs/api/class-test#test-use) calls. All contexts created by this function - * are similar to the default [fixtures.context](https://playwright.dev/docs/api/class-fixtures#fixtures-context). - * - * This function is useful for multi-context scenarios, for example testing two users talking over the chat application. - * - * A single `options` argument will be merged with all the default options from - * [configuration file](https://playwright.dev/docs/test-configuration) or - * [test.use(fixtures)](https://playwright.dev/docs/api/class-test#test-use) calls and passed to - * [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context). If you'd like to - * undo some of these options, override them with some value or `undefined`. For example: - * - * ```js js-flavor=ts - * // example.spec.ts - * - * import { test } from '@playwright/test'; - * - * // All contexts will use this storage state. - * test.use({ storageState: 'state.json' }); - * - * test('my test', async ({ createContext }) => { - * // An isolated context - * const context1 = await createContext(); - * - * // Another isolated context with custom options - * const context2 = await createContext({ - * // Undo 'state.json' from above - * storageState: undefined, - * // Set custom locale - * locale: 'en-US', - * }); - * - * // ... - * }); - * ``` - * - * ```js js-flavor=js - * // example.spec.js - * // @ts-check - * - * const { test } = require('@playwright/test'); - * - * // All contexts will use this storage state. - * test.use({ storageState: 'state.json' }); - * - * test('my test', async ({ createContext }) => { - * // An isolated context - * const context1 = await createContext(); - * - * // Another isolated context with custom options - * const context2 = await createContext({ - * // Undo 'state.json' from above - * storageState: undefined, - * // Set custom locale - * locale: 'en-US', - * }); - * - * // ... - * }); - * ``` - * - */ createContext: (options?: BrowserContextOptions) => Promise; /** * Isolated [BrowserContext] instance, created for each test. Since contexts are isolated between each other, every test