mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-13 17:14:02 +03:00
chore: setup -> test.projectSetup (#19932)
* Changed `setup` to `test.projectSetup` * Only `test.projectSetup.only` is supported on the new method * test.* methods except for before/after/Each/All hooks can be called inside the project setup files
This commit is contained in:
parent
e3d615e9f2
commit
a39a97f0ee
@ -1174,6 +1174,22 @@ Test title.
|
||||
Test function that takes one or two arguments: an object with fixtures and optional [TestInfo].
|
||||
|
||||
|
||||
## method: Test.projectSetup
|
||||
* since: v1.30
|
||||
|
||||
Declares a project setup function. The function will be run before all other tests in the same project and if it fails the project execution will be aborted.
|
||||
|
||||
### param: Test.projectSetup.title
|
||||
* since: v1.30
|
||||
- `title` <[string]>
|
||||
|
||||
Project setup title.
|
||||
|
||||
### param: Test.projectSetup.testFunction
|
||||
* since: v1.30
|
||||
- `testFunction` <[function]\([Fixtures], [TestInfo]\)>
|
||||
|
||||
Project setup function that takes one or two arguments: an object with fixtures and optional [TestInfo].
|
||||
|
||||
|
||||
## method: Test.setTimeout
|
||||
|
@ -23,7 +23,7 @@ import { removeFolders } from 'playwright-core/lib/utils/fileUtils';
|
||||
import type { Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, ScreenshotMode, TestInfo, TestType, TraceMode, VideoMode } from '../types/test';
|
||||
import { store as _baseStore } from './store';
|
||||
import type { TestInfoImpl } from './testInfo';
|
||||
import { rootTestType, _setProjectSetup } from './testType';
|
||||
import { rootTestType } from './testType';
|
||||
import { type ContextReuseMode } from './types';
|
||||
export { expect } from './expect';
|
||||
export { addRunnerPlugin as _addRunnerPlugin } from './plugins';
|
||||
@ -634,7 +634,5 @@ function normalizeScreenshotMode(screenshot: PlaywrightWorkerOptions['screenshot
|
||||
const kTracingStarted = Symbol('kTracingStarted');
|
||||
|
||||
export const test = _baseTest.extend<TestFixtures, WorkerFixtures>(playwrightFixtures);
|
||||
export const setup = _baseTest.extend<TestFixtures, WorkerFixtures>(playwrightFixtures);
|
||||
_setProjectSetup(setup, true);
|
||||
|
||||
export default test;
|
||||
|
@ -26,8 +26,6 @@ const testTypeSymbol = Symbol('testType');
|
||||
export class TestTypeImpl {
|
||||
readonly fixtures: FixturesWithLocation[];
|
||||
readonly test: TestType<any, any>;
|
||||
// Wether the test is 'setup' which should only be called inside project setup files.
|
||||
_projectSetup: boolean = false;
|
||||
|
||||
constructor(fixtures: FixturesWithLocation[]) {
|
||||
this.fixtures = fixtures;
|
||||
@ -57,6 +55,8 @@ export class TestTypeImpl {
|
||||
test.step = wrapFunctionWithLocation(this._step.bind(this));
|
||||
test.use = wrapFunctionWithLocation(this._use.bind(this));
|
||||
test.extend = wrapFunctionWithLocation(this._extend.bind(this));
|
||||
test.projectSetup = wrapFunctionWithLocation(this._createTest.bind(this, 'projectSetup'));
|
||||
(test.projectSetup as any).only = wrapFunctionWithLocation(this._createTest.bind(this, 'projectSetupOnly'));
|
||||
test._extendTest = wrapFunctionWithLocation(this._extendTest.bind(this));
|
||||
test.info = () => {
|
||||
const result = currentTestInfo();
|
||||
@ -67,7 +67,7 @@ export class TestTypeImpl {
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
private _currentSuite(location: Location, title: string): Suite | undefined {
|
||||
private _currentSuite(location: Location, title: string, allowedContext: 'test' | 'projectSetup' | 'any'): Suite | undefined {
|
||||
const suite = currentlyLoadingFileSuite();
|
||||
if (!suite) {
|
||||
addFatalError([
|
||||
@ -80,18 +80,28 @@ export class TestTypeImpl {
|
||||
].join('\n'), location);
|
||||
return;
|
||||
}
|
||||
if (this._projectSetup !== suite._isProjectSetup) {
|
||||
if (this._projectSetup)
|
||||
addFatalError(`${title} is called in a file which is not a part of project setup.`, location);
|
||||
else
|
||||
addFatalError(`${title} is called in a project setup file (use 'setup' instead of 'test').`, location);
|
||||
}
|
||||
if (allowedContext === 'projectSetup' && !suite._isProjectSetup)
|
||||
addFatalError(`${title} is only allowed in a project setup file.`, location);
|
||||
else if (allowedContext === 'test' && suite._isProjectSetup)
|
||||
addFatalError(`${title} is not allowed in a project setup file.`, location);
|
||||
return suite;
|
||||
}
|
||||
|
||||
private _createTest(type: 'default' | 'only' | 'skip' | 'fixme', location: Location, title: string, fn: Function) {
|
||||
private _createTest(type: 'default' | 'only' | 'skip' | 'fixme' | 'projectSetup' | 'projectSetupOnly', location: Location, title: string, fn: Function) {
|
||||
throwIfRunningInsideJest();
|
||||
const suite = this._currentSuite(location, this._projectSetup ? 'setup()' : 'test()');
|
||||
let functionTitle = 'test()';
|
||||
let allowedContext: 'test' | 'projectSetup' | 'any' = 'any';
|
||||
switch (type) {
|
||||
case 'projectSetup':
|
||||
case 'projectSetupOnly':
|
||||
functionTitle = 'test.projectSetup()';
|
||||
allowedContext = 'projectSetup';
|
||||
break;
|
||||
case 'default':
|
||||
allowedContext = 'test';
|
||||
break;
|
||||
}
|
||||
const suite = this._currentSuite(location, functionTitle, allowedContext);
|
||||
if (!suite)
|
||||
return;
|
||||
const test = new TestCase(title, fn, this, location);
|
||||
@ -99,7 +109,7 @@ export class TestTypeImpl {
|
||||
test._isProjectSetup = suite._isProjectSetup;
|
||||
suite._addTest(test);
|
||||
|
||||
if (type === 'only')
|
||||
if (type === 'only' || type === 'projectSetupOnly')
|
||||
test._only = true;
|
||||
if (type === 'skip' || type === 'fixme') {
|
||||
test.annotations.push({ type });
|
||||
@ -113,7 +123,7 @@ export class TestTypeImpl {
|
||||
|
||||
private _describe(type: 'default' | 'only' | 'serial' | 'serial.only' | 'parallel' | 'parallel.only' | 'skip' | 'fixme', location: Location, title: string | Function, fn?: Function) {
|
||||
throwIfRunningInsideJest();
|
||||
const suite = this._currentSuite(location, this._projectSetup ? 'setup.describe()' : 'test.describe()');
|
||||
const suite = this._currentSuite(location, 'test.describe()', 'any');
|
||||
if (!suite)
|
||||
return;
|
||||
|
||||
@ -150,7 +160,7 @@ export class TestTypeImpl {
|
||||
}
|
||||
|
||||
private _hook(name: 'beforeEach' | 'afterEach' | 'beforeAll' | 'afterAll', location: Location, fn: Function) {
|
||||
const suite = this._currentSuite(location, `${this._projectSetup ? 'setup' : 'test'}.${name}()`);
|
||||
const suite = this._currentSuite(location, `test.${name}()`, 'test');
|
||||
if (!suite)
|
||||
return;
|
||||
suite._hooks.push({ type: name, fn, location });
|
||||
@ -158,7 +168,7 @@ export class TestTypeImpl {
|
||||
|
||||
private _configure(location: Location, options: { mode?: 'parallel' | 'serial', retries?: number, timeout?: number }) {
|
||||
throwIfRunningInsideJest();
|
||||
const suite = this._currentSuite(location, `${this._projectSetup ? 'setup' : 'test'}.describe.configure()`);
|
||||
const suite = this._currentSuite(location, `test.describe.configure()`, 'any');
|
||||
if (!suite)
|
||||
return;
|
||||
|
||||
@ -225,7 +235,7 @@ export class TestTypeImpl {
|
||||
}
|
||||
|
||||
private _use(location: Location, fixtures: Fixtures) {
|
||||
const suite = this._currentSuite(location, `${this._projectSetup ? 'setup' : 'test'}.use()`);
|
||||
const suite = this._currentSuite(location, `test.use()`, 'any');
|
||||
if (!suite)
|
||||
return;
|
||||
suite._use.push({ fixtures, location });
|
||||
@ -234,7 +244,7 @@ export class TestTypeImpl {
|
||||
private async _step<T>(location: Location, title: string, body: () => Promise<T>): Promise<T> {
|
||||
const testInfo = currentTestInfo();
|
||||
if (!testInfo) {
|
||||
addFatalError(`${this._projectSetup ? 'setup' : 'test'}.step() can only be called from a test`, location);
|
||||
addFatalError(`test.step() can only be called from a test`, location);
|
||||
return undefined as any;
|
||||
}
|
||||
const step = testInfo._addStep({
|
||||
@ -281,11 +291,4 @@ function throwIfRunningInsideJest() {
|
||||
}
|
||||
}
|
||||
|
||||
export function _setProjectSetup(test: TestType<any, any>, projectSetup: boolean) {
|
||||
const testTypeImpl = (test as any)[testTypeSymbol] as TestTypeImpl;
|
||||
if (!testTypeImpl)
|
||||
throw new Error(`Argument is not a TestType`);
|
||||
testTypeImpl._projectSetup = projectSetup;
|
||||
}
|
||||
|
||||
export const rootTestType = new TestTypeImpl([]);
|
||||
|
@ -29,8 +29,8 @@ function createConfigWithProjects(names: string[], testInfo: TestInfo, projectTe
|
||||
await new Promise(f => setTimeout(f, 100));
|
||||
});`;
|
||||
files[`${name}/${name}.setup.ts`] = `
|
||||
const { setup } = pwt;
|
||||
setup('${name} setup', async () => {
|
||||
const { test } = pwt;
|
||||
test.projectSetup('${name} setup', async () => {
|
||||
await new Promise(f => setTimeout(f, 100));
|
||||
});`;
|
||||
}
|
||||
@ -142,8 +142,8 @@ test('should stop project if setup fails', async ({ runGroups }, testInfo) => {
|
||||
};
|
||||
const configWithFiles = createConfigWithProjects(['a', 'b', 'c'], testInfo, projectTemplates);
|
||||
configWithFiles[`a/a.setup.ts`] = `
|
||||
const { setup, expect } = pwt;
|
||||
setup('a setup', async () => {
|
||||
const { test, expect } = pwt;
|
||||
test.projectSetup('a setup', async () => {
|
||||
expect(1).toBe(2);
|
||||
});`;
|
||||
|
||||
@ -179,9 +179,9 @@ test('should run setup in each project shard', async ({ runGroups }, testInfo) =
|
||||
test('test2', async () => { });
|
||||
`,
|
||||
'c.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
@ -233,14 +233,14 @@ test('should run setup only for projects that have tests in the shard', async ({
|
||||
test('test2', async () => { });
|
||||
`,
|
||||
'p1.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'p2.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup3', async () => { });
|
||||
setup('setup4', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup3', async () => { });
|
||||
test.projectSetup('setup4', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
@ -347,20 +347,20 @@ test('list-files should enumerate setup files in same group', async ({ runComman
|
||||
]
|
||||
};`,
|
||||
'a1.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('test1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test1', async () => { });
|
||||
`,
|
||||
'a2.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('test1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test1', async () => { });
|
||||
`,
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('test2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('test3', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test3', async () => { });
|
||||
`,
|
||||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
@ -394,20 +394,20 @@ test('test --list should enumerate setup tests as regular ones', async ({ runCom
|
||||
]
|
||||
};`,
|
||||
'a1.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('test1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test1', async () => { });
|
||||
`,
|
||||
'a2.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('test1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test1', async () => { });
|
||||
`,
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('test2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('test3', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test3', async () => { });
|
||||
`,
|
||||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
@ -419,9 +419,9 @@ test('test --list should enumerate setup tests as regular ones', async ({ runCom
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain(`Listing tests:
|
||||
[p1] › a.test.ts:6:7 › test2
|
||||
[p1] › a1.setup.ts:5:7 › test1
|
||||
[p1] › a2.setup.ts:5:7 › test1
|
||||
[p2] › b.setup.ts:5:7 › test3
|
||||
[p1] › a1.setup.ts:5:12 › test1
|
||||
[p1] › a2.setup.ts:5:12 › test1
|
||||
[p2] › b.setup.ts:5:12 › test3
|
||||
[p2] › b.test.ts:6:7 › test4
|
||||
Total: 5 tests in 5 files`);
|
||||
});
|
||||
@ -445,17 +445,17 @@ test('should allow .only in setup files', async ({ runGroups }, testInfo) => {
|
||||
test('test4', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup.only('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
setup.only('setup3', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup.only('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
test.projectSetup.only('setup3', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, passed, timeline, output } = await runGroups(files);
|
||||
expect(output).toContain('Running 2 tests using 1 worker');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:13 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:7:13 › setup3');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:25 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:7:25 › setup3');
|
||||
expect(fileNames(timeline)).toEqual(['a.setup.ts']);
|
||||
expect(exitCode).toBe(0);
|
||||
expect(passed).toBe(2);
|
||||
@ -480,19 +480,19 @@ test('should allow describe.only in setup files', async ({ runGroups }, testInfo
|
||||
test('test4', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup.describe.only('main', () => {
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.describe.only('main', () => {
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
});
|
||||
setup('setup3', async () => { });
|
||||
test.projectSetup('setup3', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, passed, timeline, output } = await runGroups(files);
|
||||
expect(output).toContain('Running 2 tests using 1 worker');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:9 › main › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:7:9 › main › setup2');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:14 › main › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:7:14 › main › setup2');
|
||||
expect(fileNames(timeline)).toEqual(['a.setup.ts']);
|
||||
expect(exitCode).toBe(0);
|
||||
expect(passed).toBe(2);
|
||||
@ -517,19 +517,19 @@ test('should filter describe line in setup files', async ({ runGroups }, testInf
|
||||
test('test4', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup.describe('main', () => {
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.describe('main', () => {
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
});
|
||||
setup('setup3', async () => { });
|
||||
test.projectSetup('setup3', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, passed, timeline, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['a.setup.ts:5'] });
|
||||
expect(output).toContain('Running 2 tests using 1 worker');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:9 › main › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:7:9 › main › setup2');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:14 › main › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:7:14 › main › setup2');
|
||||
expect(fileNames(timeline)).toEqual(['a.setup.ts']);
|
||||
expect(exitCode).toBe(0);
|
||||
expect(passed).toBe(2);
|
||||
@ -554,16 +554,16 @@ test('should allow .only in both setup and test files', async ({ runGroups }, te
|
||||
test('test4', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup.only('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
setup('setup3', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup.only('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
test.projectSetup('setup3', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, output } = await runGroups(files);
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:13 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:25 › setup1');
|
||||
expect(output).toContain('[p1] › a.test.ts:7:12 › test2');
|
||||
});
|
||||
|
||||
@ -586,13 +586,13 @@ test('should run full setup when there is test.only', async ({ runGroups }, test
|
||||
test('test4', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup3', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup3', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
@ -600,9 +600,9 @@ test('should run full setup when there is test.only', async ({ runGroups }, test
|
||||
expect(exitCode).toBe(0);
|
||||
expect(passed).toBe(4);
|
||||
expect(output).toContain('Running 4 tests using 2 workers');
|
||||
expect(output).toContain('[p1] › b.setup.ts:5:7 › setup3');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:7 › setup2');
|
||||
expect(output).toContain('[p1] › b.setup.ts:5:12 › setup3');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:12 › setup2');
|
||||
expect(output).toContain('[p1] › a.test.ts:6:12 › test1');
|
||||
});
|
||||
|
||||
@ -628,13 +628,13 @@ test('should allow filtering setup by file:line', async ({ runGroups }, testInfo
|
||||
test('test3', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
`,
|
||||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
@ -647,16 +647,16 @@ test('should allow filtering setup by file:line', async ({ runGroups }, testInfo
|
||||
{
|
||||
const { exitCode, passed, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['.*setup.ts$'] });
|
||||
expect(output).toContain('Running 3 tests using 2 workers');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:7 › setup2');
|
||||
expect(output).toContain('[p2] › b.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:12 › setup2');
|
||||
expect(output).toContain('[p2] › b.setup.ts:5:12 › setup1');
|
||||
expect(exitCode).toBe(0);
|
||||
expect(passed).toBe(3);
|
||||
}
|
||||
{
|
||||
const { exitCode, passed, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['.*a.setup.ts:5'] });
|
||||
expect(output).toContain('Running 1 test using 1 worker');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(exitCode).toBe(0);
|
||||
expect(passed).toBe(1);
|
||||
}
|
||||
@ -680,13 +680,13 @@ test('should support filters matching both setup and test', async ({ runGroups }
|
||||
test('test3', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
`,
|
||||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
@ -697,8 +697,8 @@ test('should support filters matching both setup and test', async ({ runGroups }
|
||||
const { exitCode, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['.*a.(setup|test).ts$'] });
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain('Running 5 tests using 1 worker');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:7 › setup2');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:12 › setup2');
|
||||
expect(output).toContain('[p1] › a.test.ts:6:7 › test1');
|
||||
expect(output).toContain('[p1] › a.test.ts:7:7 › test2');
|
||||
expect(output).toContain('[p1] › a.test.ts:8:7 › test3');
|
||||
@ -726,12 +726,12 @@ test('should run setup for a project if tests match only in another project', as
|
||||
test('test1', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
`,
|
||||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
@ -742,9 +742,9 @@ test('should run setup for a project if tests match only in another project', as
|
||||
const { exitCode, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['.*a.test.ts$'] });
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain('Running 3 tests using 2 workers');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.test.ts:6:7 › test1');
|
||||
expect(output).toContain('[p2] › b.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p2] › b.setup.ts:5:12 › setup1');
|
||||
});
|
||||
|
||||
test('should run all setup files if only tests match filter', async ({ runGroups }, testInfo) => {
|
||||
@ -765,22 +765,22 @@ test('should run all setup files if only tests match filter', async ({ runGroups
|
||||
test('test3', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['a.test.ts:7'] });
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain('Running 4 tests using 2 workers');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:7 › setup2');
|
||||
expect(output).toContain('[p1] › b.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:12 › setup2');
|
||||
expect(output).toContain('[p1] › b.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.test.ts:7:7 › test2');
|
||||
});
|
||||
|
||||
@ -802,22 +802,22 @@ test('should run all setup files if only tests match grep filter', async ({ runG
|
||||
test('test3', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, output } = await runGroups(files, undefined, undefined, { additionalArgs: ['--grep', '.*test2$'] });
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain('Running 4 tests using 2 workers');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:7 › setup2');
|
||||
expect(output).toContain('[p1] › b.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:12 › setup2');
|
||||
expect(output).toContain('[p1] › b.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.test.ts:7:7 › test2');
|
||||
});
|
||||
|
||||
@ -840,21 +840,21 @@ test('should apply project.grep filter to both setup and tests', async ({ runGro
|
||||
test('foo', async () => { });
|
||||
`,
|
||||
'a.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('setup2', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('setup2', async () => { });
|
||||
`,
|
||||
'b.setup.ts': `
|
||||
const { setup } = pwt;
|
||||
setup('setup1', async () => { });
|
||||
setup('foo', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('setup1', async () => { });
|
||||
test.projectSetup('foo', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, output } = await runGroups(files);
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:7 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:7 › setup2');
|
||||
expect(output).toContain('[p1] › a.setup.ts:5:12 › setup1');
|
||||
expect(output).toContain('[p1] › a.setup.ts:6:12 › setup2');
|
||||
expect(output).toContain('[p1] › a.test.ts:6:7 › test1');
|
||||
expect(output).toContain('[p1] › a.test.ts:7:7 › test2');
|
||||
});
|
||||
@ -862,28 +862,37 @@ test('should apply project.grep filter to both setup and tests', async ({ runGro
|
||||
test('should prohibit setup in test files', async ({ runGroups }, testInfo) => {
|
||||
const files = {
|
||||
'a.test.ts': `
|
||||
const { setup, test } = pwt;
|
||||
setup('test1', async () => { });
|
||||
const { test } = pwt;
|
||||
test.projectSetup('test1', async () => { });
|
||||
test('test2', async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, output } = await runGroups(files);
|
||||
expect(exitCode).toBe(1);
|
||||
expect(output).toContain('setup() is called in a file which is not a part of project setup.');
|
||||
expect(output).toContain('test.projectSetup() is only allowed in a project setup file.');
|
||||
});
|
||||
|
||||
test('should prohibit setup hooks in test files', async ({ runGroups }, testInfo) => {
|
||||
test('should prohibit beforeAll hooks in setup files', async ({ runGroups }, testInfo) => {
|
||||
const files = {
|
||||
'a.test.ts': `
|
||||
const { setup } = pwt;
|
||||
setup.beforeAll(async () => { });
|
||||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
setupMatch: /.*.setup.ts/,
|
||||
},
|
||||
]
|
||||
};`,
|
||||
'a.setup.ts': `
|
||||
const { test } = pwt;
|
||||
test.beforeAll(async () => { });
|
||||
`,
|
||||
};
|
||||
|
||||
const { exitCode, output } = await runGroups(files);
|
||||
expect(exitCode).toBe(1);
|
||||
expect(output).toContain('setup.beforeAll() is called in a file which is not a part of project setup');
|
||||
expect(output).toContain('test.beforeAll() is not allowed in a project setup file');
|
||||
});
|
||||
|
||||
test('should prohibit test in setup files', async ({ runGroups }, testInfo) => {
|
||||
@ -905,7 +914,7 @@ test('should prohibit test in setup files', async ({ runGroups }, testInfo) => {
|
||||
|
||||
const { exitCode, output } = await runGroups(files);
|
||||
expect(exitCode).toBe(1);
|
||||
expect(output).toContain('test() is called in a project setup file');
|
||||
expect(output).toContain('test() is not allowed in a project setup file');
|
||||
});
|
||||
|
||||
test('should prohibit test hooks in setup files', async ({ runGroups }, testInfo) => {
|
||||
@ -927,5 +936,5 @@ test('should prohibit test hooks in setup files', async ({ runGroups }, testInfo
|
||||
|
||||
const { exitCode, output } = await runGroups(files);
|
||||
expect(exitCode).toBe(1);
|
||||
expect(output).toContain('test.beforeEach() is called in a project setup file');
|
||||
expect(output).toContain('test.beforeEach() is not allowed in a project setup file');
|
||||
});
|
||||
|
@ -54,8 +54,8 @@ test('should share store state between project setup and tests', async ({ runInl
|
||||
};
|
||||
`,
|
||||
'store.setup.ts': `
|
||||
const { setup, expect, store } = pwt;
|
||||
setup('should initialize store', async ({ }) => {
|
||||
const { test, expect, store } = pwt;
|
||||
test.projectSetup('should initialize store', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(undefined);
|
||||
await store.set('number', 2022)
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
@ -135,15 +135,15 @@ test('should isolate store state between projects', async ({ runInlineTest }) =>
|
||||
};
|
||||
`,
|
||||
'store.setup.ts': `
|
||||
const { setup, expect, store } = pwt;
|
||||
setup('should initialize store', async ({ }) => {
|
||||
const { test, expect, store } = pwt;
|
||||
test.projectSetup('should initialize store', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(undefined);
|
||||
await store.set('number', 2022)
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
|
||||
expect(await store.get('name')).toBe(undefined);
|
||||
await store.set('name', 'str-' + setup.info().project.name)
|
||||
expect(await store.get('name')).toBe('str-' + setup.info().project.name);
|
||||
await store.set('name', 'str-' + test.info().project.name)
|
||||
expect(await store.get('name')).toBe('str-' + test.info().project.name);
|
||||
});
|
||||
`,
|
||||
'a.test.ts': `
|
||||
@ -182,8 +182,8 @@ test('should load context storageState from store', async ({ runInlineTest, serv
|
||||
};
|
||||
`,
|
||||
'store.setup.ts': `
|
||||
const { setup, expect, store } = pwt;
|
||||
setup('should save storageState', async ({ page, context }) => {
|
||||
const { test, expect, store } = pwt;
|
||||
test.projectSetup('should save storageState', async ({ page, context }) => {
|
||||
expect(await store.get('user')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
@ -234,11 +234,11 @@ test('should load storageStateName specified in the project config from store',
|
||||
};
|
||||
`,
|
||||
'store.setup.ts': `
|
||||
const { setup, expect, store } = pwt;
|
||||
setup.use({
|
||||
const { test, expect, store } = pwt;
|
||||
test.use({
|
||||
storageStateName: ({}, use) => use(undefined),
|
||||
})
|
||||
setup('should save storageState', async ({ page, context }) => {
|
||||
test.projectSetup('should save storageState', async ({ page, context }) => {
|
||||
expect(await store.get('stateInStorage')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
@ -278,11 +278,11 @@ test('should load storageStateName specified in the global config from store', a
|
||||
};
|
||||
`,
|
||||
'store.setup.ts': `
|
||||
const { setup, expect, store } = pwt;
|
||||
setup.use({
|
||||
const { test, expect, store } = pwt;
|
||||
test.use({
|
||||
storageStateName: ({}, use) => use(undefined),
|
||||
})
|
||||
setup('should save storageStateName', async ({ page, context }) => {
|
||||
test.projectSetup('should save storageStateName', async ({ page, context }) => {
|
||||
expect(await store.get('stateInStorage')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
|
Loading…
Reference in New Issue
Block a user