From d5494edf712d9cd37551e907dc04afed2d00ba4a Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 7 Nov 2022 16:27:38 -0800 Subject: [PATCH] feat(runner): TestOptions.storageStateName (#18587) --- docs/src/test-api/class-testoptions.md | 8 +++++ packages/playwright-test/src/index.ts | 14 ++++---- packages/playwright-test/types/test.d.ts | 9 ++++++ tests/playwright-test/storage.spec.ts | 41 +++++++++++++++++++----- utils/generate_types/overrides-test.d.ts | 1 + 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/docs/src/test-api/class-testoptions.md b/docs/src/test-api/class-testoptions.md index 17da609303..7181f15d62 100644 --- a/docs/src/test-api/class-testoptions.md +++ b/docs/src/test-api/class-testoptions.md @@ -202,6 +202,14 @@ Learn more about [automatic screenshots](../test-configuration.md#automatic-scre ## property: TestOptions.storageState = %%-js-python-context-option-storage-state-%% * since: v1.10 +## property: TestOptions.storageStateName +* since: v1.28 +- type: <[string]> + +Name of the [Storage] entry that should be used to initialize [`property: TestOptions.storageState`]. The value must be +written to the storage before creatiion of a browser context that uses it (usually in [`property: TestProject.setup`]). If both +this property and [`property: TestOptions.storageState`] are specified, this property will always take precedence. + ## property: TestOptions.testIdAttribute * since: v1.27 diff --git a/packages/playwright-test/src/index.ts b/packages/playwright-test/src/index.ts index efbb4d527e..8db72000a1 100644 --- a/packages/playwright-test/src/index.ts +++ b/packages/playwright-test/src/index.ts @@ -151,6 +151,7 @@ export const test = _baseTest.extend({ permissions: [({ contextOptions }, use) => use(contextOptions.permissions), { option: true }], proxy: [({ contextOptions }, use) => use(contextOptions.proxy), { option: true }], storageState: [({ contextOptions }, use) => use(contextOptions.storageState), { option: true }], + storageStateName: [undefined, { option: true }], timezoneId: [({ contextOptions }, use) => use(contextOptions.timezoneId), { option: true }], userAgent: [({ contextOptions }, use) => use(contextOptions.userAgent), { option: true }], viewport: [({ contextOptions }, use) => use(contextOptions.viewport === undefined ? { width: 1280, height: 720 } : contextOptions.viewport), { option: true }], @@ -180,6 +181,7 @@ export const test = _baseTest.extend({ permissions, proxy, storageState, + storageStateName, viewport, timezoneId, userAgent, @@ -218,13 +220,13 @@ export const test = _baseTest.extend({ options.permissions = permissions; if (proxy !== undefined) options.proxy = proxy; - if (storageState !== undefined) { + if (storageStateName !== undefined) { + const value = await test.info().storage().get(storageStateName); + if (!value) + throw new Error(`Cannot find value in the storage for storageStateName: "${storageStateName}"`); + options.storageState = value as any; + } else if (storageState !== undefined) { options.storageState = storageState; - if (typeof storageState === 'string') { - const value = await test.info().storage().get(storageState); - if (value) - options.storageState = value as any; - } } if (timezoneId !== undefined) options.timezoneId = timezoneId; diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index 361ed3ce43..67f6e50ec9 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -2949,6 +2949,15 @@ export interface PlaywrightTestOptions { * Either a path to the file with saved storage, or an object with the following fields: */ storageState: StorageState | undefined; + /** + * Name of the [Storage] entry that should be used to initialize + * [testOptions.storageState](https://playwright.dev/docs/api/class-testoptions#test-options-storage-state). The value must + * be written to the storage before creatiion of a browser context that uses it (usually in + * [testProject.setup](https://playwright.dev/docs/api/class-testproject#test-project-setup)). If both this property and + * [testOptions.storageState](https://playwright.dev/docs/api/class-testoptions#test-options-storage-state) are specified, + * this property will always take precedence. + */ + storageStateName: string | undefined; /** * Changes the timezone of the context. See * [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) diff --git a/tests/playwright-test/storage.spec.ts b/tests/playwright-test/storage.spec.ts index b748af660f..91b07dd895 100644 --- a/tests/playwright-test/storage.spec.ts +++ b/tests/playwright-test/storage.spec.ts @@ -204,7 +204,7 @@ test('should load context storageState from storage', async ({ runInlineTest, se 'a.test.ts': ` const { test } = pwt; test.use({ - storageState: 'user' + storageStateName: 'user' }) test('should get data from setup', async ({ page }) => { await page.goto('${server.EMPTY_PAGE}'); @@ -225,7 +225,7 @@ test('should load context storageState from storage', async ({ runInlineTest, se expect(result.passed).toBe(3); }); -test('should load storageState specified in the project config from storage', async ({ runInlineTest, server }) => { +test('should load storageStateName specified in the project config from storage', async ({ runInlineTest, server }) => { server.setRoute('/setcookie.html', (req, res) => { res.setHeader('Set-Cookie', ['a=v1']); res.end(); @@ -238,7 +238,7 @@ test('should load storageState specified in the project config from storage', as name: 'p1', setup: /.*storage.setup.ts/, use: { - storageState: 'stateInStorage', + storageStateName: 'stateInStorage', }, } ] @@ -247,7 +247,7 @@ test('should load storageState specified in the project config from storage', as 'storage.setup.ts': ` const { test, expect } = pwt; test.reset({ - storageState: 'default' + storageStateName: 'default' }) test('should save storageState', async ({ page, context }) => { const storage = test.info().storage(); @@ -270,7 +270,7 @@ test('should load storageState specified in the project config from storage', as expect(result.passed).toBe(2); }); -test('should load storageState specified in the global config from storage', async ({ runInlineTest, server }) => { +test('should load storageStateName specified in the global config from storage', async ({ runInlineTest, server }) => { server.setRoute('/setcookie.html', (req, res) => { res.setHeader('Set-Cookie', ['a=v1']); res.end(); @@ -279,7 +279,7 @@ test('should load storageState specified in the global config from storage', asy 'playwright.config.js': ` module.exports = { use: { - storageState: 'stateInStorage', + storageStateName: 'stateInStorage', }, projects: [ { @@ -292,9 +292,9 @@ test('should load storageState specified in the global config from storage', asy 'storage.setup.ts': ` const { test, expect } = pwt; test.reset({ - storageState: 'default' + storageStateName: 'default' }) - test('should save storageState', async ({ page, context }) => { + test('should save storageStateName', async ({ page, context }) => { const storage = test.info().storage(); expect(await storage.get('stateInStorage')).toBe(undefined); await page.goto('${server.PREFIX}/setcookie.html'); @@ -313,4 +313,29 @@ test('should load storageState specified in the global config from storage', asy }, { workers: 1 }); expect(result.exitCode).toBe(0); expect(result.passed).toBe(2); +}); + +test('should throw on unknown storageStateName value', async ({ runInlineTest, server }) => { + const result = await runInlineTest({ + 'playwright.config.js': ` + module.exports = { + projects: [ + { + name: 'p1', + use: { + storageStateName: 'stateInStorage', + }, + } + ] + }; + `, + 'a.test.ts': ` + const { test } = pwt; + test('should fail to initialize page', async ({ page }) => { + }); + `, + }, { workers: 1 }); + expect(result.exitCode).toBe(1); + expect(result.passed).toBe(0); + expect(result.output).toContain('Error: Cannot find value in the storage for storageStateName: "stateInStorage"'); }); \ No newline at end of file diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 41d9a6138b..68de70bc65 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -235,6 +235,7 @@ export interface PlaywrightTestOptions { permissions: string[] | undefined; proxy: Proxy | undefined; storageState: StorageState | undefined; + storageStateName: string | undefined; timezoneId: string | undefined; userAgent: string | undefined; viewport: ViewportSize | null | undefined;