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 });
});
```
This commit is contained in:
Dmitry Gozman 2022-07-28 12:57:05 -07:00 committed by GitHub
parent 792aa6a080
commit 3d89506704
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 17 deletions

View file

@ -203,7 +203,7 @@ export class FixturePool {
}; };
value = value[0]; value = value[0];
} }
const fn = value as (Function | any); let fn = value as (Function | any);
const previous = this.registrations.get(name); const previous = this.registrations.get(name);
if (previous && options) { if (previous && options) {
@ -222,6 +222,15 @@ export class FixturePool {
if (options.scope === 'worker' && disallowWorkerFixtures) 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 }); 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 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 }; 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); registrationId(registration);

View file

@ -230,35 +230,49 @@ test('test.use() with undefined should not be ignored', async ({ runInlineTest }
const result = await runInlineTest({ const result = await runInlineTest({
'playwright.config.ts': ` 'playwright.config.ts': `
module.exports = { module.exports = {
use: { option: 'config' }, use: { option1: 'config' },
}; };
`, `,
'a.test.js': ` 'a.test.js': `
const test = pwt.test.extend({ option: [ 'default', { option: true } ] }); const test = pwt.test.extend({
test('test1', async ({ option }) => { option1: [ 'default', { option: true } ],
console.log('test1-' + option); option2: [ 'default', { option: true } ],
}); });
test('test1', async ({ option1, option2 }) => {
console.log('test1: option1=' + option1);
console.log('test1: option2=' + option2);
});
test.describe('', () => { test.describe('', () => {
test.use({ option: 'foo' }); test.use({ option1: 'foo', option2: 'foo' });
test('test2', async ({ option }) => { test('test2', async ({ option1, option2 }) => {
console.log('test2-' + option); console.log('test2: option1=' + option1);
console.log('test2: option2=' + option2);
}); });
test.describe('', () => { test.describe('', () => {
test.use({ option: undefined }); test.use({ option1: undefined, option2: undefined });
test('test3', async ({ option }) => { test('test3', async ({ option1, option2 }) => {
console.log('test3-' + option); 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.exitCode).toBe(0);
expect(result.passed).toBe(4); expect(result.passed).toBe(4);
expect(result.output).toContain('test1-config'); expect(result.output).toContain('test1: option1=config');
expect(result.output).toContain('test2-foo'); expect(result.output).toContain('test1: option2=default');
expect(result.output).toContain('test3-undefined'); expect(result.output).toContain('test2: option1=foo');
expect(result.output).toContain('test4-undefined'); 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');
}); });