From 2d5c7c67075d231c53c2177bc0d88bcf736e801a Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 22 May 2024 16:57:21 -0700 Subject: [PATCH] Switch matchers to the new timeout --- .../playwright/src/common/expectBundle.ts | 2 + packages/playwright/src/matchers/expect.ts | 19 ++++--- .../playwright/src/matchers/matcherHint.ts | 4 +- packages/playwright/src/matchers/matchers.ts | 56 +++++++++---------- .../playwright/src/matchers/toBeTruthy.ts | 7 +-- packages/playwright/src/matchers/toEqual.ts | 7 +-- .../src/matchers/toMatchSnapshot.ts | 10 ++-- .../playwright/src/matchers/toMatchText.ts | 12 ++-- packages/playwright/types/test.d.ts | 1 + utils/generate_types/overrides-test.d.ts | 1 + 10 files changed, 63 insertions(+), 56 deletions(-) diff --git a/packages/playwright/src/common/expectBundle.ts b/packages/playwright/src/common/expectBundle.ts index 40c6256dd0..506606414b 100644 --- a/packages/playwright/src/common/expectBundle.ts +++ b/packages/playwright/src/common/expectBundle.ts @@ -16,6 +16,8 @@ export const expect: typeof import('../../bundles/expect/node_modules/expect/build').expect = require('./expectBundleImpl').expect; export type ExpectMatcherContext = import('../../bundles/expect/node_modules/expect/build').MatcherContext; +export const EXPECTED_COLOR: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').EXPECTED_COLOR = require('./expectBundleImpl').EXPECTED_COLOR; export const INVERTED_COLOR: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').INVERTED_COLOR = require('./expectBundleImpl').INVERTED_COLOR; export const RECEIVED_COLOR: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').RECEIVED_COLOR = require('./expectBundleImpl').RECEIVED_COLOR; +export const matcherErrorMessage: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').matcherErrorMessage = require('./expectBundleImpl').matcherErrorMessage; export const printReceived: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').printReceived = require('./expectBundleImpl').printReceived; diff --git a/packages/playwright/src/matchers/expect.ts b/packages/playwright/src/matchers/expect.ts index 79816a8d7a..8995120240 100644 --- a/packages/playwright/src/matchers/expect.ts +++ b/packages/playwright/src/matchers/expect.ts @@ -49,7 +49,7 @@ import { toPass } from './matchers'; import { toMatchSnapshot, toHaveScreenshot, toHaveScreenshotStepTitle } from './toMatchSnapshot'; -import type { Expect } from '../../types/test'; +import type { Expect, ExpectMatcherState } from '../../types/test'; import { currentTestInfo, currentExpectTimeout, setCurrentExpectConfigureTimeout } from '../common/globals'; import { filteredStackTrace, trimLongString } from '../util'; import { @@ -131,9 +131,16 @@ function createExpect(info: ExpectMetaInfo) { return (matchers: any) => { const wrappedMatchers: any = {}; Object.entries(matchers).forEach(([name, matcher]) => { - wrappedMatchers[name] = function (...args: any[]) { - this.timeout = currentExpectTimeout({}); - return (matcher as any).call(this, ...args); + wrappedMatchers[name] = function(...args: any[]) { + const { isNot, promise, utils, expand } = this; + const newThis: ExpectMatcherState = { + isNot, + promise, + utils, + expand, + timeout: currentExpectTimeout({}) + }; + return (matcher as any).call(newThis, ...args); }; }); expectLibrary.extend(wrappedMatchers); @@ -178,8 +185,6 @@ function createExpect(info: ExpectMetaInfo) { return expectInstance; } -export const expect: Expect<{}> = createExpect({}); - expectLibrary.setState({ expand: false }); const customAsyncMatchers = { @@ -351,7 +356,7 @@ function computeArgsSuffix(matcherName: string, args: any[]) { return value ? `(${value})` : ''; } -expectLibrary.extend(customMatchers); +export const expect: Expect<{}> = createExpect({}).extend(customMatchers); export function mergeExpects(...expects: any[]) { return expect; diff --git a/packages/playwright/src/matchers/matcherHint.ts b/packages/playwright/src/matchers/matcherHint.ts index 2db79cbf6f..e8aba2bbff 100644 --- a/packages/playwright/src/matchers/matcherHint.ts +++ b/packages/playwright/src/matchers/matcherHint.ts @@ -15,14 +15,14 @@ */ import { colors } from 'playwright-core/lib/utilsBundle'; -import type { ExpectMatcherContext } from './expect'; +import type { ExpectMatcherState } from '../../types/test'; import type { Locator } from 'playwright-core'; import type { StackFrame } from '@protocol/channels'; import { stringifyStackFrames } from 'playwright-core/lib/utils'; export const kNoElementsFoundError = ''; -export function matcherHint(state: ExpectMatcherContext, locator: Locator | undefined, matcherName: string, expression: any, actual: any, matcherOptions: any, timeout?: number) { +export function matcherHint(state: ExpectMatcherState, locator: Locator | undefined, matcherName: string, expression: any, actual: any, matcherOptions: any, timeout?: number) { let header = state.utils.matcherHint(matcherName, expression, actual, matcherOptions).replace(/ \/\/ deep equality/, '') + '\n\n'; if (timeout) header = colors.red(`Timed out ${timeout}ms waiting for `) + header; diff --git a/packages/playwright/src/matchers/matchers.ts b/packages/playwright/src/matchers/matchers.ts index 505fd24351..08ae8b6385 100644 --- a/packages/playwright/src/matchers/matchers.ts +++ b/packages/playwright/src/matchers/matchers.ts @@ -24,7 +24,7 @@ import { toExpectedTextValues, toMatchText } from './toMatchText'; import { constructURLBasedOnBaseURL, isRegExp, isString, isTextualMimeType, pollAgainstDeadline } from 'playwright-core/lib/utils'; import { currentTestInfo } from '../common/globals'; import { TestInfoImpl } from '../worker/testInfo'; -import type { ExpectMatcherContext } from './expect'; +import type { ExpectMatcherState } from '../../types/test'; import { takeFirst } from '../common/config'; interface LocatorEx extends Locator { @@ -36,7 +36,7 @@ interface APIResponseEx extends APIResponse { } export function toBeAttached( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { attached?: boolean, timeout?: number }, ) { @@ -50,7 +50,7 @@ export function toBeAttached( } export function toBeChecked( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { checked?: boolean, timeout?: number }, ) { @@ -64,7 +64,7 @@ export function toBeChecked( } export function toBeDisabled( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { timeout?: number }, ) { @@ -74,7 +74,7 @@ export function toBeDisabled( } export function toBeEditable( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { editable?: boolean, timeout?: number }, ) { @@ -88,7 +88,7 @@ export function toBeEditable( } export function toBeEmpty( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { timeout?: number }, ) { @@ -98,7 +98,7 @@ export function toBeEmpty( } export function toBeEnabled( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { enabled?: boolean, timeout?: number }, ) { @@ -112,7 +112,7 @@ export function toBeEnabled( } export function toBeFocused( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { timeout?: number }, ) { @@ -122,7 +122,7 @@ export function toBeFocused( } export function toBeHidden( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { timeout?: number }, ) { @@ -132,7 +132,7 @@ export function toBeHidden( } export function toBeVisible( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { visible?: boolean, timeout?: number }, ) { @@ -146,7 +146,7 @@ export function toBeVisible( } export function toBeInViewport( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, options?: { timeout?: number, ratio?: number }, ) { @@ -156,7 +156,7 @@ export function toBeInViewport( } export function toContainText( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp | (string | RegExp)[], options: { timeout?: number, useInnerText?: boolean, ignoreCase?: boolean } = {}, @@ -175,7 +175,7 @@ export function toContainText( } export function toHaveAccessibleDescription( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp, options?: { timeout?: number, ignoreCase?: boolean }, @@ -187,7 +187,7 @@ export function toHaveAccessibleDescription( } export function toHaveAccessibleName( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp, options?: { timeout?: number, ignoreCase?: boolean }, @@ -199,7 +199,7 @@ export function toHaveAccessibleName( } export function toHaveAttribute( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, name: string, expected: string | RegExp | undefined | { timeout?: number }, @@ -224,7 +224,7 @@ export function toHaveAttribute( } export function toHaveClass( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp | (string | RegExp)[], options?: { timeout?: number }, @@ -243,7 +243,7 @@ export function toHaveClass( } export function toHaveCount( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: number, options?: { timeout?: number }, @@ -254,7 +254,7 @@ export function toHaveCount( } export function toHaveCSS( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, name: string, expected: string | RegExp, @@ -267,7 +267,7 @@ export function toHaveCSS( } export function toHaveId( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp, options?: { timeout?: number }, @@ -279,7 +279,7 @@ export function toHaveId( } export function toHaveJSProperty( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, name: string, expected: any, @@ -291,7 +291,7 @@ export function toHaveJSProperty( } export function toHaveRole( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string, options?: { timeout?: number, ignoreCase?: boolean }, @@ -305,7 +305,7 @@ export function toHaveRole( } export function toHaveText( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp | (string | RegExp)[], options: { timeout?: number, useInnerText?: boolean, ignoreCase?: boolean } = {}, @@ -324,7 +324,7 @@ export function toHaveText( } export function toHaveValue( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: string | RegExp, options?: { timeout?: number }, @@ -336,7 +336,7 @@ export function toHaveValue( } export function toHaveValues( - this: ExpectMatcherContext, + this: ExpectMatcherState, locator: LocatorEx, expected: (string | RegExp)[], options?: { timeout?: number }, @@ -348,7 +348,7 @@ export function toHaveValues( } export function toHaveTitle( - this: ExpectMatcherContext, + this: ExpectMatcherState, page: Page, expected: string | RegExp, options: { timeout?: number } = {}, @@ -361,7 +361,7 @@ export function toHaveTitle( } export function toHaveURL( - this: ExpectMatcherContext, + this: ExpectMatcherState, page: Page, expected: string | RegExp, options?: { ignoreCase?: boolean, timeout?: number }, @@ -376,7 +376,7 @@ export function toHaveURL( } export async function toBeOK( - this: ExpectMatcherContext, + this: ExpectMatcherState, response: APIResponseEx ) { const matcherName = 'toBeOK'; @@ -398,7 +398,7 @@ export async function toBeOK( } export async function toPass( - this: ExpectMatcherContext, + this: ExpectMatcherState, callback: () => any, options: { intervals?: number[]; diff --git a/packages/playwright/src/matchers/toBeTruthy.ts b/packages/playwright/src/matchers/toBeTruthy.ts index 1da531a6fb..0941ab7a63 100644 --- a/packages/playwright/src/matchers/toBeTruthy.ts +++ b/packages/playwright/src/matchers/toBeTruthy.ts @@ -17,12 +17,11 @@ import { expectTypes, callLogText } from '../util'; import { kNoElementsFoundError, matcherHint } from './matcherHint'; import type { MatcherResult } from './matcherHint'; -import { currentExpectTimeout } from '../common/globals'; -import type { ExpectMatcherContext } from './expect'; +import type { ExpectMatcherState } from '../../types/test'; import type { Locator } from 'playwright-core'; export async function toBeTruthy( - this: ExpectMatcherContext, + this: ExpectMatcherState, matcherName: string, receiver: Locator, receiverType: string, @@ -39,7 +38,7 @@ export async function toBeTruthy( promise: this.promise, }; - const timeout = currentExpectTimeout(options); + const timeout = options.timeout ?? this.timeout; const { matches, log, timedOut, received } = await query(!!this.isNot, timeout); const notFound = received === kNoElementsFoundError ? received : undefined; const actual = matches ? expected : unexpected; diff --git a/packages/playwright/src/matchers/toEqual.ts b/packages/playwright/src/matchers/toEqual.ts index 9dbf30ec5b..29d3fd4866 100644 --- a/packages/playwright/src/matchers/toEqual.ts +++ b/packages/playwright/src/matchers/toEqual.ts @@ -17,8 +17,7 @@ import { expectTypes, callLogText } from '../util'; import { matcherHint } from './matcherHint'; import type { MatcherResult } from './matcherHint'; -import { currentExpectTimeout } from '../common/globals'; -import type { ExpectMatcherContext } from './expect'; +import type { ExpectMatcherState } from '../../types/test'; import type { Locator } from 'playwright-core'; // Omit colon and one or more spaces, so can call getLabelPrinter. @@ -26,7 +25,7 @@ const EXPECTED_LABEL = 'Expected'; const RECEIVED_LABEL = 'Received'; export async function toEqual( - this: ExpectMatcherContext, + this: ExpectMatcherState, matcherName: string, receiver: Locator, receiverType: string, @@ -42,7 +41,7 @@ export async function toEqual( promise: this.promise, }; - const timeout = currentExpectTimeout(options); + const timeout = options.timeout ?? this.timeout; const { matches: pass, received, log, timedOut } = await query(!!this.isNot, timeout); diff --git a/packages/playwright/src/matchers/toMatchSnapshot.ts b/packages/playwright/src/matchers/toMatchSnapshot.ts index 83d20d22aa..7a3242100e 100644 --- a/packages/playwright/src/matchers/toMatchSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchSnapshot.ts @@ -16,7 +16,7 @@ import type { Locator, Page } from 'playwright-core'; import type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page'; -import { currentTestInfo, currentExpectTimeout } from '../common/globals'; +import { currentTestInfo } from '../common/globals'; import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils'; import { getComparator, sanitizeForFilePath } from 'playwright-core/lib/utils'; import { @@ -30,7 +30,7 @@ import fs from 'fs'; import path from 'path'; import { mime } from 'playwright-core/lib/utilsBundle'; import type { TestInfoImpl } from '../worker/testInfo'; -import type { ExpectMatcherContext } from './expect'; +import type { ExpectMatcherState } from '../../types/test'; import type { MatcherResult } from './matcherHint'; import type { FullProjectInternal } from '../common/config'; @@ -291,7 +291,7 @@ class SnapshotHelper { } export function toMatchSnapshot( - this: ExpectMatcherContext, + this: ExpectMatcherState, received: Buffer | string, nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ImageComparatorOptions = {}, optOptions: ImageComparatorOptions = {} @@ -348,7 +348,7 @@ export function toHaveScreenshotStepTitle( } export async function toHaveScreenshot( - this: ExpectMatcherContext, + this: ExpectMatcherState, pageOrLocator: Page | Locator, nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {}, optOptions: ToHaveScreenshotOptions = {} @@ -380,7 +380,7 @@ export async function toHaveScreenshot( scale: helper.options.scale ?? 'css', style, isNot: !!this.isNot, - timeout: currentExpectTimeout(helper.options), + timeout: helper.options.timeout ?? this.timeout, comparator: helper.options.comparator, maxDiffPixels: helper.options.maxDiffPixels, maxDiffPixelRatio: helper.options.maxDiffPixelRatio, diff --git a/packages/playwright/src/matchers/toMatchText.ts b/packages/playwright/src/matchers/toMatchText.ts index 1d66ab8d68..8397e7e2b0 100644 --- a/packages/playwright/src/matchers/toMatchText.ts +++ b/packages/playwright/src/matchers/toMatchText.ts @@ -19,17 +19,17 @@ import type { ExpectedTextValue } from '@protocol/channels'; import { isRegExp, isString } from 'playwright-core/lib/utils'; import { expectTypes, callLogText } from '../util'; import { - type ExpectMatcherContext, printReceivedStringContainExpectedResult, printReceivedStringContainExpectedSubstring } from './expect'; +import { EXPECTED_COLOR, matcherErrorMessage } from '../common/expectBundle'; +import type { ExpectMatcherState } from '../../types/test'; import { kNoElementsFoundError, matcherHint } from './matcherHint'; import type { MatcherResult } from './matcherHint'; -import { currentExpectTimeout } from '../common/globals'; import type { Locator } from 'playwright-core'; export async function toMatchText( - this: ExpectMatcherContext, + this: ExpectMatcherState, matcherName: string, receiver: Locator, receiverType: string, @@ -49,9 +49,9 @@ export async function toMatchText( !(expected && typeof expected.test === 'function') ) { throw new Error( - this.utils.matcherErrorMessage( + matcherErrorMessage( matcherHint(this, receiver, matcherName, receiver, expected, matcherOptions), - `${this.utils.EXPECTED_COLOR( + `${EXPECTED_COLOR( 'expected', )} value must be a string or regular expression`, this.utils.printWithType('Expected', expected, this.utils.printExpected), @@ -59,7 +59,7 @@ export async function toMatchText( ); } - const timeout = currentExpectTimeout(options); + const timeout = options.timeout ?? this.timeout; const { matches: pass, received, log, timedOut } = await query(!!this.isNot, timeout); const stringSubstring = options.matchSubstring ? 'substring' : 'string'; diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 725689deef..136e504fcd 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -6513,6 +6513,7 @@ export type ExpectMatcherState = { isNot: boolean; promise: 'rejects' | 'resolves' | ''; utils: ExpectMatcherUtils; + expand: boolean; timeout: number; }; diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 0d1030f494..48f47052dc 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -361,6 +361,7 @@ export type ExpectMatcherState = { isNot: boolean; promise: 'rejects' | 'resolves' | ''; utils: ExpectMatcherUtils; + expand: boolean; timeout: number; };