fix(test runner): fix types to allow calling custom matchers on expect.poll (#32407)
The `'should support custom matchers'` test asserts that the functionality works, but it was a type error. This PR updates the types so that it's allowed. Closes https://github.com/microsoft/playwright/issues/32408 --------- Signed-off-by: Simon Knott <info@simonknott.de> Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
This commit is contained in:
parent
5c2e9962b4
commit
f62f85ba51
14
packages/playwright/types/test.d.ts
vendored
14
packages/playwright/types/test.d.ts
vendored
|
|
@ -6567,15 +6567,17 @@ type MakeMatchers<R, T, ExtendedMatchers> = {
|
||||||
rejects: MakeMatchers<Promise<R>, any, ExtendedMatchers>;
|
rejects: MakeMatchers<Promise<R>, any, ExtendedMatchers>;
|
||||||
} & IfAny<T, AllMatchers<R, T>, SpecificMatchers<R, T> & ToUserMatcherObject<ExtendedMatchers, T>>;
|
} & IfAny<T, AllMatchers<R, T>, SpecificMatchers<R, T> & ToUserMatcherObject<ExtendedMatchers, T>>;
|
||||||
|
|
||||||
export type Expect<ExtendedMatchers = {}> = {
|
type PollMatchers<R, T, ExtendedMatchers> = {
|
||||||
<T = unknown>(actual: T, messageOrOptions?: string | { message?: string }): MakeMatchers<void, T, ExtendedMatchers>;
|
|
||||||
soft: <T = unknown>(actual: T, messageOrOptions?: string | { message?: string }) => MakeMatchers<void, T, ExtendedMatchers>;
|
|
||||||
poll: <T = unknown>(actual: () => T | Promise<T>, messageOrOptions?: string | { message?: string, timeout?: number, intervals?: number[] }) => BaseMatchers<Promise<void>, T> & {
|
|
||||||
/**
|
/**
|
||||||
* If you know how to test something, `.not` lets you test its opposite.
|
* If you know how to test something, `.not` lets you test its opposite.
|
||||||
*/
|
*/
|
||||||
not: BaseMatchers<Promise<void>, T>;
|
not: PollMatchers<R, T, ExtendedMatchers>;
|
||||||
};
|
} & BaseMatchers<R, T> & ToUserMatcherObject<ExtendedMatchers, T>;
|
||||||
|
|
||||||
|
export type Expect<ExtendedMatchers = {}> = {
|
||||||
|
<T = unknown>(actual: T, messageOrOptions?: string | { message?: string }): MakeMatchers<void, T, ExtendedMatchers>;
|
||||||
|
soft: <T = unknown>(actual: T, messageOrOptions?: string | { message?: string }) => MakeMatchers<void, T, ExtendedMatchers>;
|
||||||
|
poll: <T = unknown>(actual: () => T | Promise<T>, messageOrOptions?: string | { message?: string, timeout?: number, intervals?: number[] }) => PollMatchers<Promise<void>,T, ExtendedMatchers>
|
||||||
extend<MoreMatchers extends Record<string, (this: ExpectMatcherState, receiver: any, ...args: any[]) => MatcherReturnType | Promise<MatcherReturnType>>>(matchers: MoreMatchers): Expect<ExtendedMatchers & MoreMatchers>;
|
extend<MoreMatchers extends Record<string, (this: ExpectMatcherState, receiver: any, ...args: any[]) => MatcherReturnType | Promise<MatcherReturnType>>>(matchers: MoreMatchers): Expect<ExtendedMatchers & MoreMatchers>;
|
||||||
configure: (configuration: {
|
configure: (configuration: {
|
||||||
message?: string,
|
message?: string,
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,10 @@ test('should poll predicate', async ({ runInlineTest }) => {
|
||||||
test('should compile', async ({ runTSC }) => {
|
test('should compile', async ({ runTSC }) => {
|
||||||
const result = await runTSC({
|
const result = await runTSC({
|
||||||
'a.spec.ts': `
|
'a.spec.ts': `
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect as baseExpect } from '@playwright/test';
|
||||||
|
const expect = baseExpect.extend({
|
||||||
|
toBeWithinRange() { return { message: () => "is within range", pass: true }; },
|
||||||
|
})
|
||||||
test('should poll sync predicate', async ({ page }) => {
|
test('should poll sync predicate', async ({ page }) => {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
test.expect.poll(() => ++i).toBe(3);
|
test.expect.poll(() => ++i).toBe(3);
|
||||||
|
|
@ -57,6 +60,7 @@ test('should compile', async ({ runTSC }) => {
|
||||||
return ++i;
|
return ++i;
|
||||||
}).toBe(3);
|
}).toBe(3);
|
||||||
test.expect.poll(() => Promise.resolve(++i)).toBe(3);
|
test.expect.poll(() => Promise.resolve(++i)).toBe(3);
|
||||||
|
expect.poll(() => Promise.resolve(++i)).toBeWithinRange();
|
||||||
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
await test.expect.poll(() => page.locator('foo')).toBeEnabled();
|
await test.expect.poll(() => page.locator('foo')).toBeEnabled();
|
||||||
|
|
@ -172,7 +176,9 @@ test('should support .not predicate', async ({ runInlineTest }) => {
|
||||||
test('should support custom matchers', async ({ runInlineTest }) => {
|
test('should support custom matchers', async ({ runInlineTest }) => {
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
'a.spec.ts': `
|
'a.spec.ts': `
|
||||||
expect.extend({
|
import { test, expect as baseExpect } from '@playwright/test';
|
||||||
|
|
||||||
|
const expect = baseExpect.extend({
|
||||||
toBeWithinRange(received, floor, ceiling) {
|
toBeWithinRange(received, floor, ceiling) {
|
||||||
const pass = received >= floor && received <= ceiling;
|
const pass = received >= floor && received <= ceiling;
|
||||||
if (pass) {
|
if (pass) {
|
||||||
|
|
@ -191,10 +197,9 @@ test('should support custom matchers', async ({ runInlineTest }) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
import { test, expect } from '@playwright/test';
|
|
||||||
test('should poll', async () => {
|
test('should poll', async () => {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
await test.expect.poll(() => ++i).toBeWithinRange(3, Number.MAX_VALUE);
|
await expect.poll(() => ++i).toBeWithinRange(3, Number.MAX_VALUE);
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
|
|
|
||||||
14
utils/generate_types/overrides-test.d.ts
vendored
14
utils/generate_types/overrides-test.d.ts
vendored
|
|
@ -405,15 +405,17 @@ type MakeMatchers<R, T, ExtendedMatchers> = {
|
||||||
rejects: MakeMatchers<Promise<R>, any, ExtendedMatchers>;
|
rejects: MakeMatchers<Promise<R>, any, ExtendedMatchers>;
|
||||||
} & IfAny<T, AllMatchers<R, T>, SpecificMatchers<R, T> & ToUserMatcherObject<ExtendedMatchers, T>>;
|
} & IfAny<T, AllMatchers<R, T>, SpecificMatchers<R, T> & ToUserMatcherObject<ExtendedMatchers, T>>;
|
||||||
|
|
||||||
export type Expect<ExtendedMatchers = {}> = {
|
type PollMatchers<R, T, ExtendedMatchers> = {
|
||||||
<T = unknown>(actual: T, messageOrOptions?: string | { message?: string }): MakeMatchers<void, T, ExtendedMatchers>;
|
|
||||||
soft: <T = unknown>(actual: T, messageOrOptions?: string | { message?: string }) => MakeMatchers<void, T, ExtendedMatchers>;
|
|
||||||
poll: <T = unknown>(actual: () => T | Promise<T>, messageOrOptions?: string | { message?: string, timeout?: number, intervals?: number[] }) => BaseMatchers<Promise<void>, T> & {
|
|
||||||
/**
|
/**
|
||||||
* If you know how to test something, `.not` lets you test its opposite.
|
* If you know how to test something, `.not` lets you test its opposite.
|
||||||
*/
|
*/
|
||||||
not: BaseMatchers<Promise<void>, T>;
|
not: PollMatchers<R, T, ExtendedMatchers>;
|
||||||
};
|
} & BaseMatchers<R, T> & ToUserMatcherObject<ExtendedMatchers, T>;
|
||||||
|
|
||||||
|
export type Expect<ExtendedMatchers = {}> = {
|
||||||
|
<T = unknown>(actual: T, messageOrOptions?: string | { message?: string }): MakeMatchers<void, T, ExtendedMatchers>;
|
||||||
|
soft: <T = unknown>(actual: T, messageOrOptions?: string | { message?: string }) => MakeMatchers<void, T, ExtendedMatchers>;
|
||||||
|
poll: <T = unknown>(actual: () => T | Promise<T>, messageOrOptions?: string | { message?: string, timeout?: number, intervals?: number[] }) => PollMatchers<Promise<void>, T, ExtendedMatchers>;
|
||||||
extend<MoreMatchers extends Record<string, (this: ExpectMatcherState, receiver: any, ...args: any[]) => MatcherReturnType | Promise<MatcherReturnType>>>(matchers: MoreMatchers): Expect<ExtendedMatchers & MoreMatchers>;
|
extend<MoreMatchers extends Record<string, (this: ExpectMatcherState, receiver: any, ...args: any[]) => MatcherReturnType | Promise<MatcherReturnType>>>(matchers: MoreMatchers): Expect<ExtendedMatchers & MoreMatchers>;
|
||||||
configure: (configuration: {
|
configure: (configuration: {
|
||||||
message?: string,
|
message?: string,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue