From 3d895067047176b01a2cca78b4c243dadad162d0 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 28 Jul 2022 12:57:05 -0700 Subject: [PATCH] fix(fixtures): make undefined option mean "default value" (#16026) In the following example, `locale` inside the `describe` would be reverted to the default value: ```js test.use({ locale: 'en-GB' }); test.decsribe(() => { test.use({ locale: undefined }); }); ``` --- packages/playwright-test/src/fixtures.ts | 11 +++++- tests/playwright-test/test-extend.spec.ts | 46 +++++++++++++++-------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/packages/playwright-test/src/fixtures.ts b/packages/playwright-test/src/fixtures.ts index a3b1d8f1cc..32f4410d8b 100644 --- a/packages/playwright-test/src/fixtures.ts +++ b/packages/playwright-test/src/fixtures.ts @@ -203,7 +203,7 @@ export class FixturePool { }; value = value[0]; } - const fn = value as (Function | any); + let fn = value as (Function | any); const previous = this.registrations.get(name); if (previous && options) { @@ -222,6 +222,15 @@ export class FixturePool { if (options.scope === 'worker' && disallowWorkerFixtures) throw errorWithLocations(`Cannot use({ ${name} }) in a describe group, because it forces a new worker.\nMake it top-level in the test file or put in the configuration file.`, { location, name }); + // Overriding option with "undefined" value means setting it to the default value + // from the original declaration of the option. + if (fn === undefined && options.option && previous) { + let original = previous; + while (original.super) + original = original.super; + fn = original.fn; + } + const deps = fixtureParameterNames(fn, location); const registration: FixtureRegistration = { id: '', name, location, scope: options.scope, fn, auto: options.auto, option: options.option, timeout: options.timeout, customTitle: options.customTitle, deps, super: previous }; registrationId(registration); diff --git a/tests/playwright-test/test-extend.spec.ts b/tests/playwright-test/test-extend.spec.ts index ab385337dd..8fd3b0af5a 100644 --- a/tests/playwright-test/test-extend.spec.ts +++ b/tests/playwright-test/test-extend.spec.ts @@ -230,35 +230,49 @@ test('test.use() with undefined should not be ignored', async ({ runInlineTest } const result = await runInlineTest({ 'playwright.config.ts': ` module.exports = { - use: { option: 'config' }, + use: { option1: 'config' }, }; `, 'a.test.js': ` - const test = pwt.test.extend({ option: [ 'default', { option: true } ] }); - test('test1', async ({ option }) => { - console.log('test1-' + option); + const test = pwt.test.extend({ + option1: [ 'default', { option: true } ], + option2: [ 'default', { option: true } ], }); + test('test1', async ({ option1, option2 }) => { + console.log('test1: option1=' + option1); + console.log('test1: option2=' + option2); + }); + test.describe('', () => { - test.use({ option: 'foo' }); - test('test2', async ({ option }) => { - console.log('test2-' + option); + test.use({ option1: 'foo', option2: 'foo' }); + test('test2', async ({ option1, option2 }) => { + console.log('test2: option1=' + option1); + console.log('test2: option2=' + option2); }); + test.describe('', () => { - test.use({ option: undefined }); - test('test3', async ({ option }) => { - console.log('test3-' + option); + test.use({ option1: undefined, option2: undefined }); + test('test3', async ({ option1, option2 }) => { + console.log('test3: option1=' + option1); + console.log('test3: option2=' + option2); }); }); }); - test.extend({ option: undefined })('test4', async ({ option }) => { - console.log('test4-' + option); + + test.extend({ option1: undefined, option2: undefined })('test4', async ({ option1, option2 }) => { + console.log('test4: option1=' + option1); + console.log('test4: option2=' + option2); }); `, }); expect(result.exitCode).toBe(0); expect(result.passed).toBe(4); - expect(result.output).toContain('test1-config'); - expect(result.output).toContain('test2-foo'); - expect(result.output).toContain('test3-undefined'); - expect(result.output).toContain('test4-undefined'); + expect(result.output).toContain('test1: option1=config'); + expect(result.output).toContain('test1: option2=default'); + expect(result.output).toContain('test2: option1=foo'); + expect(result.output).toContain('test2: option2=foo'); + expect(result.output).toContain('test3: option1=config'); + expect(result.output).toContain('test3: option2=default'); + expect(result.output).toContain('test4: option1=config'); + expect(result.output).toContain('test4: option2=default'); });