diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 78d89b89d1..7e29ef87a2 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5236,7 +5236,7 @@ export interface ExpectMatcherUtils { stringify(object: unknown, maxDepth?: number, maxWidth?: number): string; } -type State = { +export type ExpectMatcherState = { isNot: boolean; promise: 'rejects' | 'resolves' | ''; utils: ExpectMatcherUtils; @@ -5268,7 +5268,7 @@ type MakeMatchers = { rejects: MakeMatchers, any, ExtendedMatchers>; } & IfAny, SpecificMatchers & ToUserMatcherObject>; -export type Expect = { +export type Expect = { (actual: T, messageOrOptions?: string | { message?: string }): MakeMatchers; soft: (actual: T, messageOrOptions?: string | { message?: string }) => MakeMatchers; poll: (actual: () => T | Promise, messageOrOptions?: string | { message?: string, timeout?: number, intervals?: number[] }) => BaseMatchers, T> & { @@ -5277,18 +5277,13 @@ export type Expect = { */ not: BaseMatchers, T>; }; - extend MatcherReturnType | Promise>>(matchers: MoreMatchers): Expect; + extend MatcherReturnType | Promise>>(matchers: MoreMatchers): Expect; configure: (configuration: { message?: string, timeout?: number, soft?: boolean, }) => Expect; - getState(): { - expand?: boolean; - isNot?: boolean; - promise?: string; - utils: any; - }; + getState(): ExpectMatcherState; not: Omit; } & AsymmetricMatchers; diff --git a/tests/playwright-test/expect.spec.ts b/tests/playwright-test/expect.spec.ts index 0167dd0e50..f725711943 100644 --- a/tests/playwright-test/expect.spec.ts +++ b/tests/playwright-test/expect.spec.ts @@ -713,7 +713,7 @@ test('should chain expect matchers and expose matcher utils (TSC)', async ({ run const result = await runTSC({ 'a.spec.ts': ` import { test, expect as baseExpect } from '@playwright/test'; - import type { Page, Locator } from '@playwright/test'; + import type { Page, Locator, ExpectMatcherState, Expect } from '@playwright/test'; function callLogText(log: string[] | undefined): string { if (!log) @@ -721,8 +721,15 @@ test('should chain expect matchers and expose matcher utils (TSC)', async ({ run return log.join('\\n'); } + const dummy: Expect = baseExpect; + const dummy2: Expect<{}> = baseExpect; + const expect = baseExpect.extend({ async toHaveAmount(locator: Locator, expected: string, options?: { timeout?: number }) { + // Make sure "this" is inferred as ExpectMatcherState. + const self: ExpectMatcherState = this; + const self2: ReturnType = self; + const baseAmount = locator.locator('.base-amount'); let pass: boolean; diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index ac89c360a4..5a8c5e5135 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -370,7 +370,7 @@ export interface ExpectMatcherUtils { stringify(object: unknown, maxDepth?: number, maxWidth?: number): string; } -type State = { +export type ExpectMatcherState = { isNot: boolean; promise: 'rejects' | 'resolves' | ''; utils: ExpectMatcherUtils; @@ -402,7 +402,7 @@ type MakeMatchers = { rejects: MakeMatchers, any, ExtendedMatchers>; } & IfAny, SpecificMatchers & ToUserMatcherObject>; -export type Expect = { +export type Expect = { (actual: T, messageOrOptions?: string | { message?: string }): MakeMatchers; soft: (actual: T, messageOrOptions?: string | { message?: string }) => MakeMatchers; poll: (actual: () => T | Promise, messageOrOptions?: string | { message?: string, timeout?: number, intervals?: number[] }) => BaseMatchers, T> & { @@ -411,18 +411,13 @@ export type Expect = { */ not: BaseMatchers, T>; }; - extend MatcherReturnType | Promise>>(matchers: MoreMatchers): Expect; + extend MatcherReturnType | Promise>>(matchers: MoreMatchers): Expect; configure: (configuration: { message?: string, timeout?: number, soft?: boolean, }) => Expect; - getState(): { - expand?: boolean; - isNot?: boolean; - promise?: string; - utils: any; - }; + getState(): ExpectMatcherState; not: Omit; } & AsymmetricMatchers;