chore: composed->merge (#27555)
This commit is contained in:
Родитель
3a43aaa700
Коммит
393bd36e0a
|
@ -8,46 +8,68 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
|
|||
|
||||
## Version 1.39
|
||||
|
||||
### Extending expect with custom matchers
|
||||
### Add custom matchers to your expect
|
||||
|
||||
You can extend Playwright assertions by providing custom matchers. These matchers will be available on the expect object.
|
||||
|
||||
```js title=fixtures.ts
|
||||
```js title="test.spec.ts"
|
||||
import { expect as baseExpect } from '@playwright/test';
|
||||
export const expect = baseExpect.extend({
|
||||
async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
|
||||
// Note: this matcher never passes, see the documentation for a full example.
|
||||
// Return a "pass" flag and a message getter.
|
||||
return { pass: false, message: () => `Expected ${expected} amount` };
|
||||
// ... see documentation for how to write matchers.
|
||||
},
|
||||
});
|
||||
|
||||
test('pass', async ({ page }) => {
|
||||
await expect(page.getByTestId('cart')).toHaveAmount(5);
|
||||
});
|
||||
```
|
||||
|
||||
See the documentation [for a full example](./test-configuration.md#add-custom-matchers-using-expectextend).
|
||||
|
||||
### Merging fixtures and expect matchers
|
||||
### Merge test fixtures
|
||||
|
||||
You can combine fixtures and custom expect matchers from multiple files or modules.
|
||||
You can now merge test fixtures from multiple files or modules:
|
||||
|
||||
```js title="fixtures.ts"
|
||||
import { composedTest, composedExpect } from '@playwright/test';
|
||||
import { mergeTests } from '@playwright/test';
|
||||
import { test as dbTest } from 'database-test-utils';
|
||||
import { test as a11yTest } from 'a11y-test-utils';
|
||||
|
||||
export const test = mergeTests(dbTest, a11yTest);
|
||||
```
|
||||
|
||||
```js title="test.spec.ts"
|
||||
import { test } from './fixtures';
|
||||
|
||||
test('passes', async ({ database, page, a11y }) => {
|
||||
// use database and a11y fixtures.
|
||||
});
|
||||
```
|
||||
|
||||
### Merge custom expect matchers
|
||||
|
||||
You can now merge custom expect matchers from multiple files or modules:
|
||||
|
||||
```js title="fixtures.ts"
|
||||
import { mergeTests, mergeExpects } from '@playwright/test';
|
||||
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
|
||||
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';
|
||||
|
||||
export const expect = composedExpect(dbExpect, a11yExpect);
|
||||
export const test = composedTest(dbTest, a11yTest);
|
||||
export const test = mergeTests(dbTest, a11yTest);
|
||||
export const expect = mergeExpects(dbExpect, a11yExpect);
|
||||
```
|
||||
|
||||
```js title="test.spec.ts"
|
||||
import { test, expect } from './fixtures';
|
||||
|
||||
test('passes', async ({ database, page }) => {
|
||||
test('passes', async ({ page, database }) => {
|
||||
await expect(database).toHaveDatabaseUser('admin');
|
||||
await expect(page).toPassA11yAudit();
|
||||
});
|
||||
```
|
||||
|
||||
### Boxed test steps
|
||||
### Hide implementation details: box test steps
|
||||
|
||||
You can mark a [`method: Test.step`] as "boxed" so that errors inside it point to the step call site.
|
||||
|
||||
|
|
|
@ -217,12 +217,12 @@ Do not confuse Playwright's `expect` with the [`expect` library](https://jestjs.
|
|||
You can combine custom matchers from multiple files or modules.
|
||||
|
||||
```js title="fixtures.ts"
|
||||
import { composedTest, composedExpect } from '@playwright/test';
|
||||
import { mergeTests, mergeExpects } from '@playwright/test';
|
||||
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
|
||||
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';
|
||||
|
||||
export const expect = composedExpect(dbExpect, a11yExpect);
|
||||
export const test = composedTest(dbTest, a11yTest);
|
||||
export const expect = mergeExpects(dbExpect, a11yExpect);
|
||||
export const test = mergeTests(dbTest, a11yTest);
|
||||
```
|
||||
|
||||
```js title="test.spec.ts"
|
||||
|
|
|
@ -230,7 +230,7 @@ export class TestTypeImpl {
|
|||
|
||||
private _extend(location: Location, fixtures: Fixtures) {
|
||||
if ((fixtures as any)[testTypeSymbol])
|
||||
throw new Error(`test.extend() accepts fixtures object, not a test object.\nDid you mean to call composedTest()?`);
|
||||
throw new Error(`test.extend() accepts fixtures object, not a test object.\nDid you mean to call mergeTests()?`);
|
||||
const fixturesWithLocation: FixturesWithLocation = { fixtures, location };
|
||||
return new TestTypeImpl([...this.fixtures, fixturesWithLocation]).test;
|
||||
}
|
||||
|
@ -249,12 +249,12 @@ function throwIfRunningInsideJest() {
|
|||
|
||||
export const rootTestType = new TestTypeImpl([]);
|
||||
|
||||
export function composedTest(...tests: TestType<any, any>[]) {
|
||||
export function mergeTests(...tests: TestType<any, any>[]) {
|
||||
let result = rootTestType;
|
||||
for (const t of tests) {
|
||||
const testTypeImpl = (t as any)[testTypeSymbol] as TestTypeImpl;
|
||||
if (!testTypeImpl)
|
||||
throw new Error(`composedTest() accepts "test" functions as parameters.\nDid you mean to call test.extend() with fixtures instead?`);
|
||||
throw new Error(`mergeTests() accepts "test" functions as parameters.\nDid you mean to call test.extend() with fixtures instead?`);
|
||||
// Filter out common ancestor fixtures.
|
||||
const newFixtures = testTypeImpl.fixtures.filter(theirs => !result.fixtures.find(ours => ours.fixtures === theirs.fixtures));
|
||||
result = new TestTypeImpl([...result.fixtures, ...newFixtures]);
|
||||
|
|
|
@ -744,7 +744,7 @@ function renderApiCall(apiName: string, params: any) {
|
|||
export const test = _baseTest.extend<TestFixtures, WorkerFixtures>(playwrightFixtures);
|
||||
|
||||
export { defineConfig } from './common/configLoader';
|
||||
export { composedTest } from './common/testType';
|
||||
export { composedExpect } from './matchers/expect';
|
||||
export { mergeTests } from './common/testType';
|
||||
export { mergeExpects } from './matchers/expect';
|
||||
|
||||
export default test;
|
||||
|
|
|
@ -338,6 +338,6 @@ function computeArgsSuffix(matcherName: string, args: any[]) {
|
|||
|
||||
expectLibrary.extend(customMatchers);
|
||||
|
||||
export function composedExpect(...expects: any[]) {
|
||||
export function mergeExpects(...expects: any[]) {
|
||||
return expect;
|
||||
}
|
||||
|
|
|
@ -5328,7 +5328,7 @@ type MergedTestType<List> = TestType<MergedT<List>, MergedW<List>>;
|
|||
/**
|
||||
* Merges fixtures
|
||||
*/
|
||||
export function composedTest<List extends any[]>(...tests: List): MergedTestType<List>;
|
||||
export function mergeTests<List extends any[]>(...tests: List): MergedTestType<List>;
|
||||
|
||||
type MergedExpectMatchers<List> = List extends [Expect<infer M>, ...(infer Rest)] ? M & MergedExpectMatchers<Rest> : {};
|
||||
type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
|
||||
|
@ -5336,7 +5336,7 @@ type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
|
|||
/**
|
||||
* Merges expects
|
||||
*/
|
||||
export function composedExpect<List extends any[]>(...expects: List): MergedExpect<List>;
|
||||
export function mergeExpects<List extends any[]>(...expects: List): MergedExpect<List>;
|
||||
|
||||
// This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459
|
||||
export {};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { composedTest } from '@playwright/test';
|
||||
import { mergeTests } from '@playwright/test';
|
||||
import { test } from '@playwright/test';
|
||||
import type { CommonFixtures, CommonWorkerFixtures } from './commonFixtures';
|
||||
import { commonFixtures } from './commonFixtures';
|
||||
|
@ -26,7 +26,7 @@ import { testModeTest } from './testModeFixtures';
|
|||
|
||||
export const base = test;
|
||||
|
||||
export const baseTest = composedTest(base, coverageTest, platformTest, testModeTest)
|
||||
export const baseTest = mergeTests(base, coverageTest, platformTest, testModeTest)
|
||||
.extend<CommonFixtures, CommonWorkerFixtures>(commonFixtures)
|
||||
.extend<ServerFixtures, ServerWorkerOptions>(serverFixtures);
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { test as test1, expect as expect1, composedTest, composedExpect } from '@playwright/test';
|
||||
import { test as test1, expect as expect1, mergeTests, mergeExpects } from '@playwright/test';
|
||||
import type { Page } from '@playwright/test';
|
||||
import { test as test2, expect as expect2 } from 'playwright-test-plugin';
|
||||
|
||||
const test = composedTest(test1, test2);
|
||||
const expect = composedExpect(expect1, expect2);
|
||||
const test = mergeTests(test1, test2);
|
||||
const expect = mergeExpects(expect1, expect2);
|
||||
|
||||
test('sample test', async ({ page, plugin }) => {
|
||||
type IsPage = (typeof page) extends Page ? true : never;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { test as test1, expect as expect1, composedTest, composedExpect } from '@playwright/test';
|
||||
import { test as test1, expect as expect1, mergeTests, mergeExpects } from '@playwright/test';
|
||||
import { test as test2, expect as expect2 } from 'playwright-test-plugin';
|
||||
|
||||
const test = composedTest(test1, test2);
|
||||
const expect = composedExpect(expect1, expect2);
|
||||
const test = mergeTests(test1, test2);
|
||||
const expect = mergeExpects(expect1, expect2);
|
||||
|
||||
test('sample test', async ({ page, plugin }) => {
|
||||
await page.setContent(`<div>hello</div><span>world</span>`);
|
||||
|
|
|
@ -879,10 +879,10 @@ test('should suppport toHaveAttribute without optional value', async ({ runTSC }
|
|||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should support composedExpect (TSC)', async ({ runTSC }) => {
|
||||
test('should support mergeExpects (TSC)', async ({ runTSC }) => {
|
||||
const result = await runTSC({
|
||||
'a.spec.ts': `
|
||||
import { test, composedExpect, expect as baseExpect } from '@playwright/test';
|
||||
import { test, mergeExpects, expect as baseExpect } from '@playwright/test';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
const expect1 = baseExpect.extend({
|
||||
|
@ -897,7 +897,7 @@ test('should support composedExpect (TSC)', async ({ runTSC }) => {
|
|||
}
|
||||
});
|
||||
|
||||
const expect = composedExpect(expect1, expect2);
|
||||
const expect = mergeExpects(expect1, expect2);
|
||||
|
||||
test('custom matchers', async ({ page }) => {
|
||||
await expect(page).toBeAGoodPage(123);
|
||||
|
@ -914,10 +914,10 @@ test('should support composedExpect (TSC)', async ({ runTSC }) => {
|
|||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should support composedExpect', async ({ runInlineTest }) => {
|
||||
test('should support mergeExpects', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.spec.ts': `
|
||||
import { test, composedExpect, expect as baseExpect } from '@playwright/test';
|
||||
import { test, mergeExpects, expect as baseExpect } from '@playwright/test';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
const expect1 = baseExpect.extend({
|
||||
|
@ -932,7 +932,7 @@ test('should support composedExpect', async ({ runInlineTest }) => {
|
|||
}
|
||||
});
|
||||
|
||||
const expect = composedExpect(expect1, expect2);
|
||||
const expect = mergeExpects(expect1, expect2);
|
||||
|
||||
test('custom matchers', async ({ page }) => {
|
||||
await expect(page).toBeAGoodPage(123);
|
||||
|
|
|
@ -160,7 +160,7 @@ test('config should override options but not fixtures', async ({ runInlineTest }
|
|||
expect(result.output).toContain('fixture-config-fixture');
|
||||
});
|
||||
|
||||
test('composedTest should be able to merge', async ({ runInlineTest }) => {
|
||||
test('mergeTests should be able to merge', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
|
@ -168,7 +168,7 @@ test('composedTest should be able to merge', async ({ runInlineTest }) => {
|
|||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
import { test, expect, composedTest } from '@playwright/test';
|
||||
import { test, expect, mergeTests } from '@playwright/test';
|
||||
const base = test.extend({
|
||||
myFixture: 'abc',
|
||||
});
|
||||
|
@ -184,7 +184,7 @@ test('composedTest should be able to merge', async ({ runInlineTest }) => {
|
|||
fixture2: ({}, use) => use('fixture2'),
|
||||
});
|
||||
|
||||
const test3 = composedTest(test1, test2);
|
||||
const test3 = mergeTests(test1, test2);
|
||||
|
||||
test3('merged', async ({ param, fixture1, myFixture, fixture2 }) => {
|
||||
console.log('param-' + param);
|
||||
|
@ -202,7 +202,7 @@ test('composedTest should be able to merge', async ({ runInlineTest }) => {
|
|||
expect(result.output).toContain('fixture2-fixture2');
|
||||
});
|
||||
|
||||
test('test.extend should print nice message when used as composedTest', async ({ runInlineTest }) => {
|
||||
test('test.extend should print nice message when used as mergeTests', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.ts': `
|
||||
import { test as base, expect } from '@playwright/test';
|
||||
|
@ -215,14 +215,14 @@ test('test.extend should print nice message when used as composedTest', async ({
|
|||
});
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.passed).toBe(0);
|
||||
expect(result.output).toContain('Did you mean to call composedTest()?');
|
||||
expect(result.output).toContain('Did you mean to call mergeTests()?');
|
||||
});
|
||||
|
||||
test('composedTest should print nice message when used as extend', async ({ runInlineTest }) => {
|
||||
test('mergeTests should print nice message when used as extend', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.ts': `
|
||||
import { test as base, expect, composedTest } from '@playwright/test';
|
||||
const test3 = composedTest(base, {});
|
||||
import { test as base, expect, mergeTests } from '@playwright/test';
|
||||
const test3 = mergeTests(base, {});
|
||||
test3('test', () => {});
|
||||
`,
|
||||
});
|
||||
|
|
|
@ -84,7 +84,7 @@ test('can return anything from hooks', async ({ runTSC }) => {
|
|||
test('test.extend options should check types', async ({ runTSC }) => {
|
||||
const result = await runTSC({
|
||||
'helper.ts': `
|
||||
import { test as base, expect, composedTest } from '@playwright/test';
|
||||
import { test as base, expect, mergeTests } from '@playwright/test';
|
||||
export type Params = { foo: string };
|
||||
export const test = base;
|
||||
export const test1 = test.extend<Params>({ foo: [ 'foo', { option: true } ] });
|
||||
|
@ -100,7 +100,7 @@ test('test.extend options should check types', async ({ runTSC }) => {
|
|||
// @ts-expect-error
|
||||
bar: async ({ baz }, run) => { await run(42); }
|
||||
});
|
||||
export const test4 = composedTest(test1, testW);
|
||||
export const test4 = mergeTests(test1, testW);
|
||||
const test5 = test4.extend<{}, { hey: string, hey2: string }>({
|
||||
// @ts-expect-error
|
||||
hey: [async ({ foo }, use) => {
|
||||
|
|
|
@ -462,7 +462,7 @@ type MergedTestType<List> = TestType<MergedT<List>, MergedW<List>>;
|
|||
/**
|
||||
* Merges fixtures
|
||||
*/
|
||||
export function composedTest<List extends any[]>(...tests: List): MergedTestType<List>;
|
||||
export function mergeTests<List extends any[]>(...tests: List): MergedTestType<List>;
|
||||
|
||||
type MergedExpectMatchers<List> = List extends [Expect<infer M>, ...(infer Rest)] ? M & MergedExpectMatchers<Rest> : {};
|
||||
type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
|
||||
|
@ -470,7 +470,7 @@ type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
|
|||
/**
|
||||
* Merges expects
|
||||
*/
|
||||
export function composedExpect<List extends any[]>(...expects: List): MergedExpect<List>;
|
||||
export function mergeExpects<List extends any[]>(...expects: List): MergedExpect<List>;
|
||||
|
||||
// This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459
|
||||
export {};
|
||||
|
|
Загрузка…
Ссылка в новой задаче