Revert #18561 "feat(test runner): test.reset() to reset options to default/config value" (#18704)

This reverts commit 6fef227f43.

Not shipping in 1.28.
This commit is contained in:
Dmitry Gozman 2022-11-10 14:45:05 -08:00 коммит произвёл GitHub
Родитель ac25fdd74b
Коммит 194abc35cd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 71 добавлений и 238 удалений

Просмотреть файл

@ -1083,51 +1083,6 @@ Test function that takes one or two arguments: an object with fixtures and optio
## method: Test.reset
* since: v1.28
Resets options that were set up in the configuration file or with [`method: Test.use`] to their default or config-specified value.
```js tab=js-js
const { test, expect } = require('@playwright/test');
test.reset({
// Reset storage state to the default empty value.
storageStage: 'default',
// Reset locale to the value specified in the config file.
locale: 'config',
});
test('example', async ({ page }) => {
// ...
});
```
```js tab=js-ts
import { test, expect } from '@playwright/test';
test.reset({
// Reset storage state to the default empty value.
storageStage: 'default',
// Reset locale to the value specified in the config file.
locale: 'config',
});
test('example', async ({ page }) => {
// ...
});
```
### param: Test.reset.fixtures
* since: v1.28
- `options` <[Object]>
An object with options set to either `'config'` or `'default'`.
## method: Test.setTimeout
* since: v1.10

Просмотреть файл

@ -48,13 +48,8 @@ type FixtureRegistration = {
id: string;
// A fixture override can use the previous version of the fixture.
super?: FixtureRegistration;
// Whether this fixture is an option value set from the config.
fromConfig?: boolean;
};
export const kResetToConfig = Symbol('reset-to-config');
export const kResetToDefault = Symbol('reset-to-default');
class Fixture {
runner: FixtureRunner;
registration: FixtureRegistration;
@ -193,7 +188,7 @@ export class FixturePool {
constructor(fixturesList: FixturesWithLocation[], parentPool?: FixturePool, disallowWorkerFixtures?: boolean) {
this.registrations = new Map(parentPool ? parentPool.registrations : []);
for (const { fixtures, location, fromConfig } of fixturesList) {
for (const { fixtures, location } of fixturesList) {
for (const entry of Object.entries(fixtures)) {
const name = entry[0];
let value = entry[1];
@ -227,30 +222,17 @@ 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 });
if (fn === undefined && options.option) {
// Overriding option with "undefined" value means setting it to the config value.
fn = kResetToConfig;
}
if (fn === kResetToConfig || fn === kResetToDefault) {
// Find the target fixture to copy the reset value from.
// It is either the original definition, or "fromConfig" one.
//
// Note that "reset to config" behaves like "reset to default"
// if no value is set in the config.
let targetFixture = previous;
while (targetFixture && targetFixture.super) {
if (fn === kResetToConfig && targetFixture.fromConfig)
break;
targetFixture = targetFixture.super;
}
if (targetFixture)
fn = targetFixture.fn;
else
fn = undefined;
// 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, fromConfig };
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);
this.registrations.set(name, registration);
}

Просмотреть файл

@ -434,17 +434,18 @@ class ProjectSuiteBuilder {
return testType.fixtures;
const result: FixturesWithLocation[] = [];
for (const f of testType.fixtures) {
result.push(f);
const optionsFromConfig: Fixtures = {};
const originalFixtures: Fixtures = {};
for (const [key, value] of Object.entries(f.fixtures)) {
if (isFixtureOption(value) && configKeys.has(key))
(optionsFromConfig as any)[key] = [(configUse as any)[key], value[1]];
else
(originalFixtures as any)[key] = value;
}
if (Object.entries(optionsFromConfig).length) {
// Add config options immediately after original option definition,
// so that any test.use() override it.
result.push({ fixtures: optionsFromConfig, location: { file: `project#${this._project._id}`, line: 1, column: 1 }, fromConfig: true });
}
if (Object.entries(optionsFromConfig).length)
result.push({ fixtures: optionsFromConfig, location: { file: `project#${this._project._id}`, line: 1, column: 1 } });
if (Object.entries(originalFixtures).length)
result.push({ fixtures: originalFixtures, location: f.location });
}
return result;
}

Просмотреть файл

@ -15,7 +15,6 @@
*/
import { expect } from './expect';
import { kResetToConfig, kResetToDefault } from './fixtures';
import { currentlyLoadingFileSuite, currentTestInfo, setCurrentlyLoadingFileSuite } from './globals';
import { TestCase, Suite } from './test';
import { wrapFunctionWithLocation } from './transform';
@ -55,7 +54,6 @@ export class TestTypeImpl {
test.setTimeout = wrapFunctionWithLocation(this._setTimeout.bind(this));
test.step = wrapFunctionWithLocation(this._step.bind(this));
test.use = wrapFunctionWithLocation(this._use.bind(this));
test.reset = wrapFunctionWithLocation(this._reset.bind(this));
test.extend = wrapFunctionWithLocation(this._extend.bind(this));
test._extendTest = wrapFunctionWithLocation(this._extendTest.bind(this));
test.info = () => {
@ -208,20 +206,6 @@ export class TestTypeImpl {
suite._use.push({ fixtures, location });
}
private _reset(location: Location, resets: Fixtures) {
const suite = this._ensureCurrentSuite(location, `test.reset()`);
const fixtures: any = {};
for (const [key, value] of Object.entries(resets)) {
if (value === 'config')
fixtures[key] = kResetToConfig;
else if (value === 'default')
fixtures[key] = kResetToDefault;
else
throw errorWithLocation(location, `test.reset() supports "config" or "default", got unexpected value "${value}"`);
}
suite._use.push({ fixtures, location });
}
private async _step<T>(location: Location, title: string, body: () => Promise<T>): Promise<T> {
const testInfo = currentTestInfo();
if (!testInfo)

Просмотреть файл

@ -24,7 +24,6 @@ export type { Location } from '../types/testReporter';
export type FixturesWithLocation = {
fixtures: Fixtures;
location: Location;
fromConfig?: boolean;
};
export type Annotation = { type: string, description?: string };

24
packages/playwright-test/types/test.d.ts поставляемый
Просмотреть файл

@ -2612,29 +2612,6 @@ export interface TestType<TestArgs extends KeyValue, WorkerArgs extends KeyValue
* @param options An object with local options.
*/
use(fixtures: Fixtures<{}, {}, TestArgs, WorkerArgs>): void;
/**
* Resets options that were set up in the configuration file or with
* [test.use(options)](https://playwright.dev/docs/api/class-test#test-use) to their default or config-specified value.
*
* ```js
* import { test, expect } from '@playwright/test';
*
* test.reset({
* // Reset storage state to the default empty value.
* storageStage: 'default',
*
* // Reset locale to the value specified in the config file.
* locale: 'config',
* });
*
* test('example', async ({ page }) => {
* // ...
* });
* ```
*
* @param options An object with options set to either `'config'` or `'default'`.
*/
reset(options: ResetOptions<TestArgs & WorkerArgs>): void;
/**
* Declares a test step.
*
@ -2759,7 +2736,6 @@ export type Fixtures<T extends KeyValue = {}, W extends KeyValue = {}, PT extend
} & {
[K in keyof T]?: TestFixtureValue<T[K], T & W & PT & PW> | [TestFixtureValue<T[K], T & W & PT & PW>, { scope?: 'test', auto?: boolean, option?: boolean, timeout?: number | undefined }];
};
type ResetOptions<T extends KeyValue> = { [K in keyof T]?: 'config' | 'default' };
type BrowserName = 'chromium' | 'firefox' | 'webkit';
type BrowserChannel = Exclude<LaunchOptions['channel'], undefined>;

Просмотреть файл

@ -246,8 +246,8 @@ test('should load storageStateName specified in the project config from storage'
`,
'storage.setup.ts': `
const { test, expect } = pwt;
test.reset({
storageStateName: 'default'
test.use({
storageStateName: ({}, use) => use(undefined),
})
test('should save storageState', async ({ page, context }) => {
const storage = test.info().storage();
@ -291,8 +291,8 @@ test('should load storageStateName specified in the global config from storage',
`,
'storage.setup.ts': `
const { test, expect } = pwt;
test.reset({
storageStateName: 'default'
test.use({
storageStateName: ({}, use) => use(undefined),
})
test('should save storageStateName', async ({ page, context }) => {
const storage = test.info().storage();

Просмотреть файл

@ -225,3 +225,54 @@ test('test._extendTest should print nice message when used as extend', async ({
expect(result.passed).toBe(0);
expect(result.output).toContain('Did you mean to call test.extend() with fixtures instead?');
});
test('test.use() with undefined should not be ignored', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `
module.exports = {
use: { option1: 'config' },
};
`,
'a.test.js': `
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({ option1: 'foo', option2: 'foo' });
test('test2', async ({ option1, option2 }) => {
console.log('test2: option1=' + option1);
console.log('test2: option2=' + option2);
});
test.describe('', () => {
test.use({ option1: undefined, option2: undefined });
test('test3', async ({ option1, option2 }) => {
console.log('test3: option1=' + option1);
console.log('test3: option2=' + option2);
});
});
});
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: 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');
});

Просмотреть файл

@ -179,109 +179,3 @@ test('test.use() should throw if called from beforeAll ', async ({ runInlineTest
expect(result.output).toContain('Playwright Test did not expect test.use() to be called here');
});
test('test.use() with undefined should not be ignored', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `
module.exports = {
use: { option1: 'config' },
};
`,
'a.test.js': `
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({ option1: 'foo', option2: 'foo' });
test('test2', async ({ option1, option2 }) => {
console.log('test2: option1=' + option1);
console.log('test2: option2=' + option2);
});
test.describe('', () => {
test.use({ option1: undefined, option2: undefined });
test('test3', async ({ option1, option2 }) => {
console.log('test3: option1=' + option1);
console.log('test3: option2=' + option2);
});
});
});
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: 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');
});
test('test.reset() should reset to default or config', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `
module.exports = {
use: { option1: 'config-value' },
};
`,
'a.test.js': `
const test = pwt.test.extend({
option1: [ 'default-value', { option: true } ],
option2: [ 'default-value', { option: true } ],
});
test.use({ option1: 'use-value', option2: 'use-value' });
test('test1', async ({ option1, option2 }) => {
console.log('test1: option1=' + option1);
console.log('test1: option2=' + option2);
});
test.describe(() => {
test.reset({ option1: 'default', option2: 'default' });
test('test2', async ({ option1, option2 }) => {
console.log('test2: option1=' + option1);
console.log('test2: option2=' + option2);
});
});
test.describe(() => {
test.reset({ option1: 'config', option2: 'config' });
test('test3', async ({ option1, option2 }) => {
console.log('test3: option1=' + option1);
console.log('test3: option2=' + option2);
});
});
`,
});
expect(result.exitCode).toBe(0);
expect(result.passed).toBe(3);
expect(result.output).toContain('test1: option1=use-value');
expect(result.output).toContain('test1: option2=use-value');
expect(result.output).toContain('test2: option1=default-value');
expect(result.output).toContain('test2: option2=default-value');
expect(result.output).toContain('test3: option1=config-value');
expect(result.output).toContain('test3: option2=default-value');
});
test('test.reset() throws for unsupported value', async ({ runInlineTest }) => {
const result = await runInlineTest({
'a.test.js': `
pwt.test.reset({ option: 'foo' });
`,
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain('test.reset() supports "config" or "default", got unexpected value "foo"');
});

Просмотреть файл

@ -136,13 +136,6 @@ test('should check types of fixtures', async ({ runTSC }) => {
// @ts-expect-error
test.use({ baz: 'baz' });
test.reset({ foo: 'default' });
test.reset({ foo: 'config' });
// @ts-expect-error
test.reset({ unknown: 'config' });
// @ts-expect-error
test.reset({ foo: 'unknown' });
test('my test', async ({ foo, bar }) => {
bar += parseInt(foo);
});

2
utils/generate_types/overrides-test.d.ts поставляемый
Просмотреть файл

@ -151,7 +151,6 @@ export interface TestType<TestArgs extends KeyValue, WorkerArgs extends KeyValue
beforeAll(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise<any> | any): void;
afterAll(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise<any> | any): void;
use(fixtures: Fixtures<{}, {}, TestArgs, WorkerArgs>): void;
reset(options: ResetOptions<TestArgs & WorkerArgs>): void;
step<T>(title: string, body: () => Promise<T>): Promise<T>;
expect: Expect;
extend<T extends KeyValue, W extends KeyValue = {}>(fixtures: Fixtures<T, W, TestArgs, WorkerArgs>): TestType<TestArgs & T, WorkerArgs & W>;
@ -172,7 +171,6 @@ export type Fixtures<T extends KeyValue = {}, W extends KeyValue = {}, PT extend
} & {
[K in keyof T]?: TestFixtureValue<T[K], T & W & PT & PW> | [TestFixtureValue<T[K], T & W & PT & PW>, { scope?: 'test', auto?: boolean, option?: boolean, timeout?: number | undefined }];
};
type ResetOptions<T extends KeyValue> = { [K in keyof T]?: 'config' | 'default' };
type BrowserName = 'chromium' | 'firefox' | 'webkit';
type BrowserChannel = Exclude<LaunchOptions['channel'], undefined>;