chore(expect): more consistent display of expect timeout error messages (#36543)
infra / docs & lint (push) Waiting to run Details
infra / Lint snippets (push) Waiting to run Details
Check client side changes / Check (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (18, macos-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (18, ubuntu-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (18, windows-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (20, ubuntu-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (22, ubuntu-latest) (push) Waiting to run Details
tests others / Stress - ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests others / Stress - ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
tests others / Stress - ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests others / WebView2 (push) Waiting to run Details
tests others / time library - ${{ matrix.clock }} (frozen) (push) Waiting to run Details
tests others / time library - ${{ matrix.clock }} (realtime) (push) Waiting to run Details
tests others / time test runner - ${{ matrix.clock }} (frozen) (push) Waiting to run Details
tests others / time test runner - ${{ matrix.clock }} (realtime) (push) Waiting to run Details
tests others / legacy progress timeouts (push) Waiting to run Details
tests others / Electron - ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests others / Electron - ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
tests others / Electron - ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 18, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 20, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 22, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 24, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (firefox, 18, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (webkit, 18, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (chromium tip-of-tree) (ubuntu-22.04) (push) Waiting to run Details
tests 1 / Test Runner (18, macos-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, macos-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, windows-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, windows-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (20, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (20, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (22, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (22, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (24, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (24, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Web Components (push) Waiting to run Details
tests 1 / VSCode Extension (push) Waiting to run Details
tests 1 / Installation Test ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests 1 / Installation Test ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
tests 1 / Installation Test ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, ubuntu-24.04) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, ubuntu-24.04) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, ubuntu-24.04) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-13-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-13-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-14-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-14-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-13-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-13-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-14-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-14-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-13-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-13-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-14-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-14-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-15-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-15-xlarge) (push) Waiting to run Details
tests 2 / Windows (chromium) (push) Waiting to run Details
tests 2 / Windows (firefox) (push) Waiting to run Details
tests 2 / Windows (webkit) (push) Waiting to run Details
tests 2 / Installation Test ${{ matrix.os }} (${{ matrix.node_version }}) (20, ubuntu-latest) (push) Waiting to run Details
tests 2 / Installation Test ${{ matrix.os }} (${{ matrix.node_version }}) (22, ubuntu-latest) (push) Waiting to run Details
tests 2 / Installation Test ${{ matrix.os }} (${{ matrix.node_version }}) (24, ubuntu-latest) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (chromium, macos-14-xlarge) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (chromium, ubuntu-24.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (chromium, windows-latest) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (firefox, macos-14-xlarge) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (firefox, ubuntu-24.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (firefox, windows-latest) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, macos-14-xlarge) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, ubuntu-22.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, ubuntu-24.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, windows-latest) (push) Waiting to run Details
tests 2 / Transport (driver) (push) Waiting to run Details
tests 2 / Transport (service) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (chromium, chromium-tip-of-tree, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (chromium, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (firefox, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (webkit, ubuntu-24.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome-beta, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome-beta, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome-beta, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-beta, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-beta, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-beta, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-dev, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-dev, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-dev, windows-latest) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (, macos-13) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (, windows-latest) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (--headed, macos-13) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (--headed, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (--headed, windows-latest) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree headless-shell-${{ matrix.os }} (ubuntu-22.04) (push) Waiting to run Details
tests 2 / Firefox Beta ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests 2 / Firefox Beta ${{ matrix.os }} (ubuntu-22.04) (push) Waiting to run Details
tests 2 / Firefox Beta ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests 2 / build-playwright-driver (push) Waiting to run Details
tests 2 / Test channel=chromium (macos-latest) (push) Waiting to run Details
tests 2 / Test channel=chromium (ubuntu-latest) (push) Waiting to run Details
tests 2 / Test channel=chromium (windows-latest) (push) Waiting to run Details
tests Video / Video Linux (chromium, ubuntu-22.04) (push) Waiting to run Details
tests Video / Video Linux (chromium, ubuntu-24.04) (push) Waiting to run Details
tests Video / Video Linux (firefox, ubuntu-22.04) (push) Waiting to run Details
tests Video / Video Linux (firefox, ubuntu-24.04) (push) Waiting to run Details
tests Video / Video Linux (webkit, ubuntu-22.04) (push) Waiting to run Details
tests Video / Video Linux (webkit, ubuntu-24.04) (push) Waiting to run Details
Internal Tests / trigger (push) Waiting to run Details

This commit is contained in:
Adam Gastineau 2025-07-16 06:03:33 -07:00 committed by GitHub
parent 04316f11cd
commit 8e4627826a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 285 additions and 112 deletions

View File

@ -15,7 +15,6 @@
*/
import { stringifyStackFrames } from 'playwright-core/lib/utils';
import { colors } from 'playwright-core/lib/utils';
import type { ExpectMatcherState } from '../../types/test';
import type { StackFrame } from '@protocol/channels';
@ -23,12 +22,16 @@ import type { Locator } from 'playwright-core';
export const kNoElementsFoundError = '<element(s) not found>';
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;
export function matcherHint(state: ExpectMatcherState, locator: Locator | undefined, matcherName: string, expression: any, actual: any, matcherOptions: any, timeout: number | undefined, expectedReceivedString?: string, preventExtraStatIndent: boolean = false) {
let header = state.utils.matcherHint(matcherName, expression, actual, matcherOptions).replace(/ \/\/ deep equality/, '') + ' failed\n\n';
// Extra space added after locator and timeout to match Jest's received/expected output
const extraSpace = preventExtraStatIndent ? '' : ' ';
if (locator)
header += `Locator: ${String(locator)}\n`;
header += `Locator: ${extraSpace}${String(locator)}\n`;
if (expectedReceivedString)
header += `${expectedReceivedString}\n`;
if (timeout)
header += `Timeout: ${extraSpace}${timeout}ms\n`;
return header;
}

View File

@ -262,7 +262,7 @@ export function toHaveClass(
return toEqual.call(this, 'toHaveClass', locator, 'Locator', async (isNot, timeout) => {
const expectedText = serializeExpectedTextValues(expected);
return await locator._expect('to.have.class.array', { expectedText, isNot, timeout });
}, expected, options);
}, expected, options, true);
} else {
return toMatchText.call(this, 'toHaveClass', locator, 'Locator', async (isNot, timeout) => {
const expectedText = serializeExpectedTextValues([expected]);
@ -283,7 +283,7 @@ export function toContainClass(
return toEqual.call(this, 'toContainClass', locator, 'Locator', async (isNot, timeout) => {
const expectedText = serializeExpectedTextValues(expected);
return await locator._expect('to.contain.class.array', { expectedText, isNot, timeout });
}, expected, options);
}, expected, options, true);
} else {
if (isRegExp(expected))
throw new Error(`"expected" argument in toContainClass cannot be a RegExp value`);

View File

@ -60,9 +60,9 @@ export async function toBeTruthy(
printedReceived = `Received: ${notFound ? kNoElementsFoundError : received}`;
}
const message = () => {
const header = matcherHint(this, receiver, matcherName, 'locator', arg, matcherOptions, timedOut ? timeout : undefined);
const header = matcherHint(this, receiver, matcherName, 'locator', arg, matcherOptions, timedOut ? timeout : undefined, `${printedExpected}\n${printedReceived}`);
const logText = callLogText(log);
return `${header}${printedExpected}\n${printedReceived}${logText}`;
return `${header}${logText}`;
};
return {
message,

View File

@ -35,6 +35,7 @@ export async function toEqual<T>(
query: (isNot: boolean, timeout: number) => Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }>,
expected: T,
options: { timeout?: number, contains?: boolean } = {},
messagePreventExtraStatIndent?: boolean
): Promise<MatcherResult<any, any>> {
expectTypes(receiver, [receiverType], matcherName);
@ -87,9 +88,9 @@ export async function toEqual<T>(
);
}
const message = () => {
const header = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
const details = printedDiff || `${printedExpected}\n${printedReceived}`;
return `${header}${details}${callLogText(log)}`;
const header = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined, details, messagePreventExtraStatIndent);
return `${header}${callLogText(log)}`;
};
// Passing the actual and expected objects so that a custom reporter
// could access them, for example in order to display a custom visual diff,

View File

@ -42,9 +42,9 @@ export async function toHaveURLWithPredicate(
throw new Error(
[
// Always display `expected` in expectation place
matcherHint(this, undefined, matcherName, expression, undefined, matcherOptions),
matcherHint(this, undefined, matcherName, expression, undefined, matcherOptions, undefined, undefined, true),
`${colors.bold('Matcher error')}: ${EXPECTED_COLOR('expected')} value must be a string, regular expression, or predicate`,
this.utils.printWithType('Expected', expected, this.utils.printExpected,),
this.utils.printWithType('Expected', expected, this.utils.printExpected),
].join('\n\n'),
);
}
@ -118,7 +118,7 @@ function toHaveURLMessage(
promise: state.promise,
};
const receivedString = received || '';
const messagePrefix = matcherHint(state, undefined, matcherName, expression, undefined, matcherOptions, didTimeout ? timeout : undefined);
const messagePrefix = matcherHint(state, undefined, matcherName, expression, undefined, matcherOptions, didTimeout ? timeout : undefined, undefined, true);
let printedReceived: string | undefined;
let printedExpected: string | undefined;

View File

@ -92,12 +92,15 @@ export async function toMatchAriaSnapshot(
const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: expected, isNot: this.isNot, timeout });
const typedReceived = received as MatcherReceived | typeof kNoElementsFoundError;
const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
const matcherHintWithExpect = (expectedReceivedString: string) => {
return matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined, expectedReceivedString);
};
const notFound = typedReceived === kNoElementsFoundError;
if (notFound) {
return {
pass: this.isNot,
message: () => messagePrefix + `Expected: ${this.utils.printExpected(expected)}\nReceived: ${EXPECTED_COLOR('<element not found>')}` + callLogText(log),
message: () => matcherHintWithExpect(`Expected: ${this.utils.printExpected(expected)}\nReceived: ${EXPECTED_COLOR('<element not found>')}`) + callLogText(log),
name: 'toMatchAriaSnapshot',
expected,
};
@ -106,15 +109,13 @@ export async function toMatchAriaSnapshot(
const receivedText = typedReceived.raw;
const message = () => {
if (pass) {
if (notFound)
return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + callLogText(log);
const printedReceived = printReceivedStringContainExpectedSubstring(receivedText, receivedText.indexOf(expected), expected.length);
return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${printedReceived}` + callLogText(log);
const receivedString = notFound ? receivedText : printReceivedStringContainExpectedSubstring(receivedText, receivedText.indexOf(expected), expected.length);
const expectedReceivedString = `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${receivedString}`;
return matcherHintWithExpect(expectedReceivedString) + callLogText(log);
} else {
const labelExpected = `Expected`;
if (notFound)
return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + callLogText(log);
return messagePrefix + this.utils.printDiffOrStringify(expected, receivedText, labelExpected, 'Received', false) + callLogText(log);
const expectedReceivedString = notFound ? `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` : this.utils.printDiffOrStringify(expected, receivedText, labelExpected, 'Received', false);
return matcherHintWithExpect(expectedReceivedString) + callLogText(log);
}
};

View File

@ -302,7 +302,7 @@ export function toMatchSnapshot(
return helper.handleMatching();
const receiver = isString(received) ? 'string' : 'Buffer';
const header = matcherHint(this, undefined, 'toMatchSnapshot', receiver, undefined, undefined);
const header = matcherHint(this, undefined, 'toMatchSnapshot', receiver, undefined, undefined, undefined);
return helper.handleDifferent(received, expected, undefined, result.diff, header, result.errorMessage, undefined, this._stepInfo);
}

View File

@ -51,7 +51,7 @@ export async function toMatchText(
) {
// Same format as jest's matcherErrorMessage
throw new Error([
matcherHint(this, receiverType === 'Locator' ? receiver as Locator : undefined, matcherName, options.receiverLabel ?? receiver, expected, matcherOptions),
matcherHint(this, receiverType === 'Locator' ? receiver as Locator : undefined, matcherName, options.receiverLabel ?? receiver, expected, matcherOptions, undefined, undefined, true),
`${colors.bold('Matcher error')}: ${EXPECTED_COLOR('expected',)} value must be a string or regular expression`,
this.utils.printWithType('Expected', expected, this.utils.printExpected)
].join('\n\n'));
@ -71,7 +71,6 @@ export async function toMatchText(
const stringSubstring = options.matchSubstring ? 'substring' : 'string';
const receivedString = received || '';
const messagePrefix = matcherHint(this, receiverType === 'Locator' ? receiver as Locator : undefined, matcherName, options.receiverLabel ?? 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
const notFound = received === kNoElementsFoundError;
let printedReceived: string | undefined;
@ -109,7 +108,8 @@ export async function toMatchText(
const message = () => {
const resultDetails = printedDiff ? printedDiff : printedExpected + '\n' + printedReceived;
return messagePrefix + resultDetails + callLogText(log);
const hints = matcherHint(this, receiverType === 'Locator' ? receiver as Locator : undefined, matcherName, options.receiverLabel ?? 'locator', undefined, matcherOptions, timedOut ? timeout : undefined, resultDetails, true);
return hints + callLogText(log);
};
return {

View File

@ -55,7 +55,12 @@ test.describe('toBeChecked', () => {
await page.setContent('<input type=checkbox></input>');
const locator = page.locator('input');
const error = await expect(locator).toBeChecked({ timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toBeChecked()`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toBeChecked() failed
Locator: locator('input')
Expected: checked
Received: unchecked
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toBeChecked" with timeout 1000ms`);
});
@ -75,7 +80,12 @@ test.describe('toBeChecked', () => {
await page.setContent('<input type=checkbox checked></input>');
const locator = page.locator('input');
const error = await expect(locator).not.toBeChecked({ timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toBeChecked()`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toBeChecked() failed
Locator: locator('input')
Expected: not checked
Received: checked
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toBeChecked" with timeout 1000ms`);
expect(stripAnsi(error.message)).toContain(`locator resolved to <input checked type="checkbox"/>`);
});
@ -84,7 +94,12 @@ test.describe('toBeChecked', () => {
await page.setContent('<input type=checkbox checked></input>');
const locator = page.locator('input');
const error = await expect(locator).toBeChecked({ checked: false, timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toBeChecked({ checked: false })`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toBeChecked({ checked: false }) failed
Locator: locator('input')
Expected: unchecked
Received: checked
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toBeChecked" with timeout 1000ms`);
expect(stripAnsi(error.message)).toContain(`locator resolved to <input checked type="checkbox"/>`);
});
@ -93,7 +108,12 @@ test.describe('toBeChecked', () => {
await page.setContent('<input type=checkbox></input>');
const locator = page.locator('input');
const error = await expect(locator).toBeChecked({ indeterminate: true, timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toBeChecked({ indeterminate: true })`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toBeChecked({ indeterminate: true }) failed
Locator: locator('input')
Expected: indeterminate
Received: unchecked
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toBeChecked" with timeout 1000ms`);
});
@ -101,7 +121,12 @@ test.describe('toBeChecked', () => {
await page.setContent('<div>no inputs here</div>');
const locator2 = page.locator('input2');
const error = await expect(locator2).not.toBeChecked({ timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toBeChecked()`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toBeChecked() failed
Locator: locator('input2')
Expected: not checked
Received: <element(s) not found>
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toBeChecked" with timeout 1000ms`);
expect(stripAnsi(error.message)).toContain(`- waiting for locator(\'input2\')`);
});
@ -439,7 +464,12 @@ test.describe('toBeHidden', () => {
await page.setContent('<div></div>');
const locator = page.locator('button');
const error = await expect(locator).not.toBeHidden({ timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toBeHidden()`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toBeHidden() failed
Locator: locator('button')
Expected: not hidden
Received: <element(s) not found>
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toBeHidden" with timeout 1000ms`);
});

View File

@ -27,18 +27,20 @@ test('toMatchText-based assertions should have matcher result', async ({ page })
expect.soft(e.matcherResult).toEqual({
actual: 'Text content',
expected: /Text2/,
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toHaveText(expected)`),
message: expect.stringContaining(`expect(locator).toHaveText(expected) failed`),
name: 'toHaveText',
pass: false,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).toHaveText(expected)
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).toHaveText(expected) failed
Locator: locator('#node')
Expected pattern: /Text2/
Received string: \"Text content\"
Timeout: 1ms
Call log`);
}
@ -49,17 +51,19 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 'Text content',
expected: /Text/,
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).not.toHaveText(expected)`),
message: expect.stringContaining(`expect(locator).not.toHaveText(expected) failed`),
name: 'toHaveText',
pass: true,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).not.toHaveText(expected)
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).not.toHaveText(expected) failed
Locator: locator('#node')
Expected pattern: not /Text/
Received string: \"Text content\"
Timeout: 1ms
Call log`);
}
@ -75,18 +79,20 @@ test('toBeTruthy-based assertions should have matcher result', async ({ page })
expect.soft(e.matcherResult).toEqual({
actual: '<element(s) not found>',
expected: 'visible',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toBeVisible()`),
message: expect.stringContaining(`expect(locator).toBeVisible() failed`),
name: 'toBeVisible',
pass: false,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).toBeVisible()
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).toBeVisible() failed
Locator: locator('#node2')
Locator: locator('#node2')
Expected: visible
Received: <element(s) not found>
Timeout: 1ms
Call log`);
}
@ -97,20 +103,21 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 'visible',
expected: 'visible',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).not.toBeVisible()`),
message: expect.stringContaining(`expect(locator).not.toBeVisible() failed`),
name: 'toBeVisible',
pass: true,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).not.toBeVisible()
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).not.toBeVisible() failed
Locator: locator('#node')
Locator: locator('#node')
Expected: not visible
Received: visible
Call log`);
Timeout: 1ms
Call log`);
}
});
@ -123,18 +130,20 @@ test('toEqual-based assertions should have matcher result', async ({ page }) =>
expect.soft(e.matcherResult).toEqual({
actual: 0,
expected: 1,
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toHaveCount(expected)`),
message: expect.stringContaining(`expect(locator).toHaveCount(expected) failed`),
name: 'toHaveCount',
pass: false,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).toHaveCount(expected)
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).toHaveCount(expected) failed
Locator: locator('#node2')
Locator: locator('#node2')
Expected: 1
Received: 0
Timeout: 1ms
Call log`);
}
@ -144,18 +153,20 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 1,
expected: 1,
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).not.toHaveCount(expected)`),
message: expect.stringContaining(`expect(locator).not.toHaveCount(expected) failed`),
name: 'toHaveCount',
pass: true,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).not.toHaveCount(expected)
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).not.toHaveCount(expected) failed
Locator: locator('#node')
Locator: locator('#node')
Expected: not 1
Received: 1
Timeout: 1ms
Call log`);
}
@ -173,18 +184,20 @@ test('toBeChecked({ checked }) should have expected', async ({ page }) => {
expect.soft(e.matcherResult).toEqual({
actual: 'unchecked',
expected: 'checked',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toBeChecked()`),
message: expect.stringContaining(`expect(locator).toBeChecked() failed`),
name: 'toBeChecked',
pass: false,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).toBeChecked()
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).toBeChecked() failed
Locator: locator('#unchecked')
Locator: locator('#unchecked')
Expected: checked
Received: unchecked
Timeout: 1ms
Call log`);
}
@ -195,18 +208,20 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 'checked',
expected: 'checked',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).not.toBeChecked()`),
message: expect.stringContaining(`expect(locator).not.toBeChecked() failed`),
name: 'toBeChecked',
pass: true,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).not.toBeChecked()
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).not.toBeChecked() failed
Locator: locator('#checked')
Locator: locator('#checked')
Expected: not checked
Received: checked
Timeout: 1ms
Call log`);
}
@ -217,18 +232,20 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 'checked',
expected: 'unchecked',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toBeChecked({ checked: false })`),
message: expect.stringContaining(`expect(locator).toBeChecked({ checked: false }) failed`),
name: 'toBeChecked',
pass: false,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).toBeChecked({ checked: false })
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).toBeChecked({ checked: false }) failed
Locator: locator('#checked')
Locator: locator('#checked')
Expected: unchecked
Received: checked
Timeout: 1ms
Call log`);
}
@ -239,18 +256,20 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 'unchecked',
expected: 'unchecked',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).not.toBeChecked({ checked: false })`),
message: expect.stringContaining(`expect(locator).not.toBeChecked({ checked: false }) failed`),
name: 'toBeChecked',
pass: true,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).not.toBeChecked({ checked: false })
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).not.toBeChecked({ checked: false }) failed
Locator: locator('#unchecked')
Locator: locator('#unchecked')
Expected: not unchecked
Received: unchecked
Timeout: 1ms
Call log`);
}
@ -261,18 +280,20 @@ Call log`);
expect.soft(e.matcherResult).toEqual({
actual: 'unchecked',
expected: 'indeterminate',
message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toBeChecked({ indeterminate: true })`),
message: expect.stringContaining(`expect(locator).toBeChecked({ indeterminate: true }) failed`),
name: 'toBeChecked',
pass: false,
log: expect.any(Array),
timeout: 1,
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: Timed out 1ms waiting for expect(locator).toBeChecked({ indeterminate: true })
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(locator).toBeChecked({ indeterminate: true }) failed
Locator: locator('#unchecked')
Locator: locator('#unchecked')
Expected: indeterminate
Received: unchecked
Timeout: 1ms
Call log`);
}
@ -295,7 +316,7 @@ test('toHaveScreenshot should populate matcherResult', async ({ page, server, is
log: expect.any(Array),
});
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(page).toHaveScreenshot(expected)
expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(page).toHaveScreenshot(expected) failed
23362 pixels (ratio 0.10 of all image pixels) are different.
`);

View File

@ -68,7 +68,12 @@ test.describe('toHaveCount', () => {
await page.setContent('<div><span></span></div>');
const locator = page.locator('span');
const error = await expect(locator).toHaveCount(0, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveCount(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveCount(expected) failed
Locator: locator('span')
Expected: 0
Received: 1
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveCount" with timeout 1000ms`);
});
@ -76,7 +81,12 @@ test.describe('toHaveCount', () => {
await page.setContent('<div><span></span></div>');
const locator = page.locator('span');
const error = await expect(locator).not.toHaveCount(1, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toHaveCount(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toHaveCount(expected) failed
Locator: locator('span')
Expected: not 1
Received: 1
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toHaveCount" with timeout 1000ms`);
});
});
@ -109,7 +119,12 @@ test.describe('toHaveJSProperty', () => {
await page.$eval('div', e => (e as any).foo = 'string');
const locator = page.locator('div');
const error = await expect(locator).toHaveJSProperty('foo', 'error', { timeout: 200 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 200ms waiting for expect(locator).toHaveJSProperty(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveJSProperty(expected) failed
Locator: locator('div')
Expected: "error"
Received: "string"
Timeout: 200ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveJSProperty" with timeout 200ms`);
});
@ -125,7 +140,12 @@ test.describe('toHaveJSProperty', () => {
await page.$eval('div', e => (e as any).foo = 2021);
const locator = page.locator('div');
const error = await expect(locator).toHaveJSProperty('foo', 1, { timeout: 200 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 200ms waiting for expect(locator).toHaveJSProperty(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveJSProperty(expected) failed
Locator: locator('div')
Expected: 1
Received: 2021
Timeout: 200ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveJSProperty" with timeout 200ms`);
});
@ -141,7 +161,12 @@ test.describe('toHaveJSProperty', () => {
await page.$eval('div', e => (e as any).foo = false);
const locator = page.locator('div');
const error = await expect(locator).toHaveJSProperty('foo', true, { timeout: 200 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 200ms waiting for expect(locator).toHaveJSProperty(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveJSProperty(expected) failed
Locator: locator('div')
Expected: true
Received: false
Timeout: 200ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveJSProperty" with timeout 200ms`);
});
@ -157,7 +182,12 @@ test.describe('toHaveJSProperty', () => {
await page.$eval('div', e => (e as any).foo = false);
const locator = page.locator('div');
const error = await expect(locator).toHaveJSProperty('foo', true, { timeout: 200 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 200ms waiting for expect(locator).toHaveJSProperty(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveJSProperty(expected) failed
Locator: locator('div')
Expected: true
Received: false
Timeout: 200ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveJSProperty" with timeout 200ms`);
});
@ -211,7 +241,12 @@ test.describe('toHaveClass', () => {
await page.setContent('<div class="bar baz"></div>');
const locator = page.locator('div');
const error = await expect(locator).toHaveClass('foo bar baz', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveClass(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveClass(expected) failed
Locator: locator('div')
Expected string: "foo bar baz"
Received string: "bar baz"
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveClass" with timeout 1000ms`);
});
@ -225,7 +260,8 @@ test.describe('toHaveClass', () => {
await page.setContent('<div class="foo"></div><div class="bar"></div><div class="bar"></div>');
const locator = page.locator('div');
const error = await expect(locator).toHaveClass(['foo', 'bar', /[a-z]az/], { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveClass(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveClass(expected) failed`);
expect(stripAnsi(error.message)).toContain(`Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveClass" with timeout 1000ms`);
});
});
@ -251,7 +287,12 @@ test.describe('toContainClass', () => {
await page.setContent('<div class="bar baz"></div>');
const locator = page.locator('div');
const error = await expect(locator).toContainClass('does-not-exist', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toContainClass(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toContainClass(expected) failed
Locator: locator('div')
Expected string: "does-not-exist"
Received string: "bar baz"
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toContainClass" with timeout 1000ms`);
});
@ -268,7 +309,8 @@ test.describe('toContainClass', () => {
await page.setContent('<div class="foo"></div><div class="bar"></div><div class="bar"></div>');
const locator = page.locator('div');
const error = await expect(locator).toContainClass(['foo', 'bar', 'baz'], { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toContainClass(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toContainClass(expected) failed`);
expect(stripAnsi(error.message)).toContain(`Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toContainClass" with timeout 1000ms`);
});
});
@ -282,7 +324,11 @@ test.describe('toHaveTitle', () => {
test('fail', async ({ page }) => {
await page.setContent('<title>Bye</title>');
const error = await expect(page).toHaveTitle('Hello', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(page).toHaveTitle(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(page).toHaveTitle(expected) failed
Expected string: "Hello"
Received string: "Bye"
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveTitle" with timeout 1000ms`);
});
});
@ -296,7 +342,11 @@ test.describe('toHaveURL', () => {
test('fail string', async ({ page }) => {
await page.goto('data:text/html,<div>A</div>');
const error = await expect(page).toHaveURL('wrong', { timeout: 1000 }).catch(e => e);
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
expect(stripAnsi(error.message)).toContain(`expect(page).toHaveURL(expected) failed
Expected string: "wrong"
Received string: "data:text/html,<div>A</div>"
Timeout: 1000ms`);
expect(stripVTControlCharacters(error.message)).toContain('Expected string: "wrong"\nReceived string: "data:text/html,<div>A</div>"');
});
@ -352,12 +402,22 @@ test.describe('toHaveAttribute', () => {
const locator = page.locator('#node');
{
const error = await expect(locator).toHaveAttribute('disabled', '', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveAttribute(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveAttribute(expected) failed
Locator: locator('#node')
Expected string: ""
Received string: serializes to the same string
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveAttribute" with timeout 1000ms`);
}
{
const error = await expect(locator).toHaveAttribute('disabled', /.*/, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveAttribute(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveAttribute(expected) failed
Locator: locator('#node')
Expected pattern: /.*/
Received string: ""
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveAttribute" with timeout 1000ms`);
}
await expect(locator).not.toHaveAttribute('disabled', '');
@ -371,12 +431,22 @@ test.describe('toHaveAttribute', () => {
await expect(locator).toHaveAttribute('checked', /.*/);
{
const error = await expect(locator).not.toHaveAttribute('checked', '', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toHaveAttribute(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toHaveAttribute(expected) failed
Locator: locator('#node')
Expected string: not ""
Received string: ""
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toHaveAttribute" with timeout 1000ms`);
}
{
const error = await expect(locator).not.toHaveAttribute('checked', /.*/, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toHaveAttribute(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toHaveAttribute(expected) failed
Locator: locator('#node')
Expected pattern: not /.*/
Received string: ""
Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toHaveAttribute" with timeout 1000ms`);
}
});

View File

@ -20,25 +20,45 @@ import { test, expect } from './pageTest';
test('should print timed out error message', async ({ page }) => {
await page.setContent('<div id=node>Text content</div>');
const error = await expect(page.locator('no-such-thing')).toHaveText('hey', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed
Locator: locator('no-such-thing')
Expected string: "hey"
Received: <element(s) not found>
Timeout: 1000ms`);
});
test('should print timed out error message when value does not match', async ({ page }) => {
await page.setContent('<div id=node>Text content</div>');
const error = await expect(page.locator('div')).toHaveText('hey', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed
Locator: locator('div')
Expected string: "hey"
Received string: "Text content"
Timeout: 1000ms`);
});
test('should print timed out error message with impossible timeout', async ({ page }) => {
await page.setContent('<div id=node>Text content</div>');
const error = await expect(page.locator('no-such-thing')).toHaveText('hey', { timeout: 1 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1ms waiting for expect(locator).toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed
Locator: locator('no-such-thing')
Expected string: "hey"
Received: <element(s) not found>
Timeout: 1ms`);
});
test('should print timed out error message when value does not match with impossible timeout', async ({ page }) => {
await page.setContent('<div id=node>Text content</div>');
const error = await expect(page.locator('div')).toHaveText('hey', { timeout: 1 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1ms waiting for expect(locator).toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed
Locator: locator('div')
Expected string: "hey"
Received string: "Text content"
Timeout: 1ms`);
});
test('should have timeout error name', async ({ page }) => {
@ -67,7 +87,12 @@ test('should timeout during first locator handler check', async ({ page, server
await page.addLocatorHandler(page.locator('div'), async locator => {});
await page.setContent(`<div>hello</div><span>bye</span>`);
const error = await expect(page.locator('span')).toHaveText('bye', { timeout: 3000 }).catch(e => e);
expect(error.message).toContain('Timed out 3000ms waiting for');
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed
Locator: locator('span')
Expected string: "bye"
Received string: ""
Timeout: 3000ms`);
expect(error.message).toContain(`locator handler has finished, waiting for locator('div') to be hidden`);
expect(error.message).toContain(`locator resolved to visible <div>hello</div>`);
});

View File

@ -208,7 +208,8 @@ test.describe('toHaveText with array', () => {
await page.setContent('<div></div>');
const locator = page.locator('p');
const error = await expect(locator).not.toHaveText([], { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).not.toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).not.toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "not toHaveText" with timeout 1000ms`);
});
@ -226,7 +227,8 @@ test.describe('toHaveText with array', () => {
const locator = page.locator('div');
const error = await expect(locator).toHaveText(['Text 1', /Text \d/, 'Extra'], { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain('- "Extra"');
expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected)`);
expect(stripAnsi(error.message)).toContain(`Timeout: 1000ms`);
expect(stripAnsi(error.message)).toContain(`- Expect "toHaveText" with timeout 1000ms`);
expect(stripAnsi(error.message)).toContain('waiting for locator(\'div\')');
expect(stripAnsi(error.message)).toContain('locator resolved to 2 elements');

View File

@ -148,14 +148,16 @@ test('checked attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- checkbox [checked=false]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- checkbox [checked=mixed]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
@ -187,7 +189,8 @@ test('disabled attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- button [disabled=false]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
@ -219,7 +222,8 @@ test('expanded attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- button [expanded=false]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
@ -247,7 +251,8 @@ test('level attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- heading [level=3]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
@ -279,7 +284,8 @@ test('pressed attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- button [pressed=false]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
// Test for 'mixed' state
@ -295,7 +301,8 @@ test('pressed attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- button [pressed=true]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
@ -331,7 +338,8 @@ test('selected attribute', async ({ page }) => {
const e = await expect(page.locator('body')).toMatchAriaSnapshot(`
- row [selected=false]
`, { timeout: 1000 }).catch(e => e);
expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
}
{
@ -415,7 +423,7 @@ test('expected formatter', async ({ page }) => {
`, { timeout: 1 }).catch(e => e);
expect(stripAnsi(error.message)).toContain(`
Locator: locator('body')
Locator: locator('body')
- Expected - 2
+ Received + 3
@ -423,7 +431,8 @@ Locator: locator('body')
- - textbox "Wrong text"
+ - banner:
+ - heading "todos" [level=1]
+ - textbox "What needs to be done?"`);
+ - textbox "What needs to be done?"
Timeout: 1ms`);
});
test('should unpack escaped names', async ({ page }) => {
@ -716,7 +725,8 @@ test('should detect unexpected children: equal', async ({ page }) => {
- listitem: "Three"
`, { timeout: 1000 }).catch(e => e);
expect(e.message).toContain('Timed out 1000ms waiting');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
expect(stripAnsi(e.message)).toContain('+ - listitem: Two');
});
@ -755,7 +765,8 @@ test('should detect unexpected children: deep-equal', async ({ page }) => {
- listitem: 1.1
`, { timeout: 1000 }).catch(e => e);
expect(e.message).toContain('Timed out 1000ms waiting');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
expect(stripAnsi(e.message)).toContain('+ - listitem: \"1.2\"');
});
@ -779,7 +790,8 @@ test('should allow restoring contain mode inside deep-equal', async ({ page }) =
- listitem: 1.1
`, { timeout: 1000 }).catch(e => e);
expect(e.message).toContain('Timed out 1000ms waiting');
expect(stripAnsi(e.message)).toContain('expect(locator).toMatchAriaSnapshot(expected) failed');
expect(stripAnsi(e.message)).toContain('Timeout: 1000ms');
expect(stripAnsi(e.message)).toContain('+ - listitem: \"1.2\"');
await expect(page.locator('body')).toMatchAriaSnapshot(`

View File

@ -191,7 +191,8 @@ test('should respect timeout', async ({ runInlineTest }, testInfo) => {
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`Timed out 1ms waiting for`);
expect(result.output).toContain(`expect(locator).toMatchAriaSnapshot(expected) failed`);
expect(result.output).toContain('Timeout: 1ms');
});
test('should respect config.snapshotPathTemplate', async ({ runInlineTest }, testInfo) => {

View File

@ -48,7 +48,8 @@ test('should configure message', async ({ runInlineTest }) => {
expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0);
expect(result.output).toContain('Error: x-foo must be visible');
expect(result.output).toContain(`Timed out 1ms waiting for expect(locator).toBeVisible()`);
expect(result.output).toContain('expect(locator).toBeVisible() failed');
expect(result.output).toContain('Timeout: 1ms');
expect(result.output).toContain('Call log:');
});
@ -66,7 +67,8 @@ test('should prefer local message', async ({ runInlineTest }) => {
expect(result.passed).toBe(0);
expect(result.output).toContain('Error: overridden');
expect(result.output).toContain(`Timed out 1ms waiting for expect(locator).toBeVisible()`);
expect(result.output).toContain(`expect(locator).toBeVisible() failed`);
expect(result.output).toContain('Timeout: 1ms');
expect(result.output).toContain('Call log:');
});

View File

@ -67,7 +67,8 @@ test('should include custom expect message with web-first assertions', async ({
expect(result.passed).toBe(0);
expect(result.output).toContain('Error: x-foo must be visible');
expect(result.output).toContain(`Timed out 1ms waiting for expect(locator).toBeVisible()`);
expect(result.output).toContain('expect(locator).toBeVisible() failed');
expect(result.output).toContain('Timeout: 1ms');
expect(result.output).toContain('Call log:');
});
@ -548,7 +549,8 @@ test('should respect expect.timeout', async ({ runInlineTest }) => {
test('timeout', async ({ page }) => {
await page.goto('data:text/html,<div>A</div>');
const error = await expect(page).toHaveURL('data:text/html,<div>B</div>').catch(e => e);
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
expect(stripVTControlCharacters(error.message)).toContain('expect(page).toHaveURL(expected) failed');
expect(stripVTControlCharacters(error.message)).toContain('Timeout: 1000ms');
expect(error.message).toContain('data:text/html,<div>');
});
`,
@ -567,7 +569,8 @@ test('should support toHaveURL predicate', async ({ runInlineTest }) => {
test('predicate', async ({ page }) => {
await page.goto('data:text/html,<div>A</div>');
const error = await expect(page).toHaveURL(url => url === 'data:text/html,<div>B</div>').catch(e => e);
expect(stripVTControlCharacters(error.message)).toContain('Timed out 1000ms waiting for expect(page).toHaveURL(expected)');
expect(stripVTControlCharacters(error.message)).toContain('expect(page).toHaveURL(expected) failed');
expect(stripVTControlCharacters(error.message)).toContain('Timeout: 1000ms');
expect(error.message).toContain('data:text/html,<div>');
});
`,
@ -706,7 +709,7 @@ test('should not print timed out error message when test times out', async ({ ru
expect(result.exitCode).toBe(1);
const output = result.output;
expect(output).toContain('Test timeout of 3000ms exceeded');
expect(output).not.toContain('Timed out 5000ms waiting for expect');
expect(output).not.toContain('Timeout: 5000ms');
expect(output).toContain(`Error: expect(locator).toHaveText(expected)`);
});
@ -1020,7 +1023,8 @@ test('should respect timeout from configured expect when used outside of the tes
expect(code).toBe(1);
expect(stdout).toBe('');
expect(stripAnsi(stderr)).toContain('Timed out 10ms waiting for expect(locator).toBeAttached()');
expect(stripAnsi(stderr)).toContain('expect(locator).toBeAttached() failed');
expect(stripAnsi(stderr)).toContain('Timeout: 10ms');
});
test('should expose timeout to custom matchers', async ({ runInlineTest, runTSC }) => {

View File

@ -720,7 +720,8 @@ test('should run CT on changed deps', async ({ runWatchTest, writeFiles }) => {
await testProcess.waitForOutput(`src${path.sep}button.spec.tsx:4:11 pass`);
expect(testProcess.output).not.toContain(`src${path.sep}link.spec.tsx`);
await testProcess.waitForOutput(`Error: Timed out 1000ms waiting for expect(locator).toHaveText(expected)`);
await testProcess.waitForOutput(`Error: expect(locator).toHaveText(expected) failed`);
await testProcess.waitForOutput('Timeout: 1000ms');
await testProcess.waitForOutput('Waiting for file changes.');
});