chore: unify toHaveScreenshot error formatting
This commit is contained in:
parent
a2dec8da63
commit
aa3414af61
|
|
@ -152,7 +152,8 @@ export const TestResultView: React.FC<{
|
||||||
|
|
||||||
function classifyErrors(testErrors: string[], diffs: ImageDiff[]) {
|
function classifyErrors(testErrors: string[], diffs: ImageDiff[]) {
|
||||||
return testErrors.map(error => {
|
return testErrors.map(error => {
|
||||||
if (error.includes('Screenshot comparison failed:')) {
|
const firstLine = error.split('\n')[0];
|
||||||
|
if (firstLine.includes('toHaveScreenshot') || firstLine.includes('toMatchSnapshot')) {
|
||||||
const matchingDiff = diffs.find(diff => {
|
const matchingDiff = diffs.find(diff => {
|
||||||
const attachmentName = diff.actual?.attachment.name;
|
const attachmentName = diff.actual?.attachment.name;
|
||||||
return attachmentName && error.includes(attachmentName);
|
return attachmentName && error.includes(attachmentName);
|
||||||
|
|
|
||||||
|
|
@ -589,7 +589,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||||
return result.binary;
|
return result.binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _expectScreenshot(options: ExpectScreenshotOptions): Promise<{ actual?: Buffer, previous?: Buffer, diff?: Buffer, errorMessage?: string, log?: string[]}> {
|
async _expectScreenshot(options: ExpectScreenshotOptions): Promise<{ actual?: Buffer, previous?: Buffer, diff?: Buffer, errorMessage?: string, log?: string[], timeout?: number}> {
|
||||||
const mask = options?.mask ? options?.mask.map(locator => ({
|
const mask = options?.mask ? options?.mask.map(locator => ({
|
||||||
frame: (locator as Locator)._frame._channel,
|
frame: (locator as Locator)._frame._channel,
|
||||||
selector: (locator as Locator)._selector,
|
selector: (locator as Locator)._selector,
|
||||||
|
|
|
||||||
|
|
@ -1193,6 +1193,7 @@ scheme.PageExpectScreenshotResult = tObject({
|
||||||
errorMessage: tOptional(tString),
|
errorMessage: tOptional(tString),
|
||||||
actual: tOptional(tBinary),
|
actual: tOptional(tBinary),
|
||||||
previous: tOptional(tBinary),
|
previous: tOptional(tBinary),
|
||||||
|
timeout: tOptional(tNumber),
|
||||||
log: tOptional(tArray(tString)),
|
log: tOptional(tArray(tString)),
|
||||||
});
|
});
|
||||||
scheme.PageScreenshotParams = tObject({
|
scheme.PageScreenshotParams = tObject({
|
||||||
|
|
|
||||||
|
|
@ -674,11 +674,12 @@ export class Page extends SdkObject {
|
||||||
throw e;
|
throw e;
|
||||||
let errorMessage = e.message;
|
let errorMessage = e.message;
|
||||||
if (e instanceof TimeoutError && intermediateResult?.previous)
|
if (e instanceof TimeoutError && intermediateResult?.previous)
|
||||||
errorMessage = `Failed to take two consecutive stable screenshots. ${e.message}`;
|
errorMessage = `Failed to take two consecutive stable screenshots.`;
|
||||||
return {
|
return {
|
||||||
log: e.message ? [...metadata.log, e.message] : metadata.log,
|
log: e.message ? [...metadata.log, e.message] : metadata.log,
|
||||||
...intermediateResult,
|
...intermediateResult,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
|
...((e instanceof TimeoutError) ? { timeout: callTimeout } : {}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import type { Locator, Page } from 'playwright-core';
|
||||||
import type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page';
|
import type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page';
|
||||||
import { currentTestInfo } from '../common/globals';
|
import { currentTestInfo } from '../common/globals';
|
||||||
import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils';
|
import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils';
|
||||||
import { getComparator, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
import { getComparator, isString, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||||
import {
|
import {
|
||||||
addSuffixToFilePath,
|
addSuffixToFilePath,
|
||||||
trimLongString, callLogText,
|
trimLongString, callLogText,
|
||||||
|
|
@ -31,7 +31,7 @@ import path from 'path';
|
||||||
import { mime } from 'playwright-core/lib/utilsBundle';
|
import { mime } from 'playwright-core/lib/utilsBundle';
|
||||||
import type { TestInfoImpl } from '../worker/testInfo';
|
import type { TestInfoImpl } from '../worker/testInfo';
|
||||||
import type { ExpectMatcherState } from '../../types/test';
|
import type { ExpectMatcherState } from '../../types/test';
|
||||||
import type { MatcherResult } from './matcherHint';
|
import { matcherHint, type MatcherResult } from './matcherHint';
|
||||||
import type { FullProjectInternal } from '../common/config';
|
import type { FullProjectInternal } from '../common/config';
|
||||||
|
|
||||||
type NameOrSegments = string | string[];
|
type NameOrSegments = string | string[];
|
||||||
|
|
@ -250,16 +250,10 @@ class SnapshotHelper {
|
||||||
expected: Buffer | string | undefined,
|
expected: Buffer | string | undefined,
|
||||||
previous: Buffer | string | undefined,
|
previous: Buffer | string | undefined,
|
||||||
diff: Buffer | string | undefined,
|
diff: Buffer | string | undefined,
|
||||||
diffError: string | undefined,
|
header: string,
|
||||||
log: string[] | undefined,
|
diffError: string,
|
||||||
title = `${this.kind} comparison failed:`): ImageMatcherResult {
|
log: string[] | undefined): ImageMatcherResult {
|
||||||
const output = [
|
const output = [`${header}${indent(diffError, ' ')}`];
|
||||||
colors.red(title),
|
|
||||||
'',
|
|
||||||
];
|
|
||||||
if (diffError)
|
|
||||||
output.push(indent(diffError, ' '));
|
|
||||||
|
|
||||||
if (expected !== undefined) {
|
if (expected !== undefined) {
|
||||||
// Copy the expectation inside the `test-results/` folder for backwards compatibility,
|
// Copy the expectation inside the `test-results/` folder for backwards compatibility,
|
||||||
// so that one can upload `test-results/` directory and have all the data inside.
|
// so that one can upload `test-results/` directory and have all the data inside.
|
||||||
|
|
@ -338,7 +332,9 @@ export function toMatchSnapshot(
|
||||||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return helper.handleDifferent(received, expected, undefined, result.diff, result.errorMessage, undefined);
|
const receiver = isString(received) ? 'string' : 'Buffer';
|
||||||
|
const header = matcherHint(this, undefined, 'toMatchSnapshot', receiver, undefined, undefined);
|
||||||
|
return helper.handleDifferent(received, expected, undefined, result.diff, header, result.errorMessage, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toHaveScreenshotStepTitle(
|
export function toHaveScreenshotStepTitle(
|
||||||
|
|
@ -410,13 +406,16 @@ export async function toHaveScreenshot(
|
||||||
if (helper.updateSnapshots === 'none' && !hasSnapshot)
|
if (helper.updateSnapshots === 'none' && !hasSnapshot)
|
||||||
return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false);
|
return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false);
|
||||||
|
|
||||||
|
const receiver = locator ? 'locator' : 'page';
|
||||||
if (!hasSnapshot) {
|
if (!hasSnapshot) {
|
||||||
// Regenerate a new screenshot by waiting until two screenshots are the same.
|
// Regenerate a new screenshot by waiting until two screenshots are the same.
|
||||||
const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions);
|
const { actual, previous, diff, errorMessage, log, timeout } = await page._expectScreenshot(expectScreenshotOptions);
|
||||||
// We tried re-generating new snapshot but failed.
|
// We tried re-generating new snapshot but failed.
|
||||||
// This can be due to e.g. spinning animation, so we want to show it as a diff.
|
// This can be due to e.g. spinning animation, so we want to show it as a diff.
|
||||||
if (errorMessage)
|
if (errorMessage) {
|
||||||
return helper.handleDifferent(actual, undefined, previous, diff, undefined, log, errorMessage);
|
const header = matcherHint(this, locator, 'toHaveScreenshot', receiver, undefined, undefined, timeout);
|
||||||
|
return helper.handleDifferent(actual, undefined, previous, diff, header, errorMessage, log);
|
||||||
|
}
|
||||||
|
|
||||||
// We successfully generated new screenshot.
|
// We successfully generated new screenshot.
|
||||||
return helper.handleMissing(actual!);
|
return helper.handleMissing(actual!);
|
||||||
|
|
@ -427,7 +426,7 @@ export async function toHaveScreenshot(
|
||||||
// - regular matcher (i.e. not a `.not`)
|
// - regular matcher (i.e. not a `.not`)
|
||||||
// - perhaps an 'all' flag to update non-matching screenshots
|
// - perhaps an 'all' flag to update non-matching screenshots
|
||||||
expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath);
|
expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath);
|
||||||
const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions);
|
const { actual, previous, diff, errorMessage, log, timeout } = await page._expectScreenshot(expectScreenshotOptions);
|
||||||
|
|
||||||
if (!errorMessage)
|
if (!errorMessage)
|
||||||
return helper.handleMatching();
|
return helper.handleMatching();
|
||||||
|
|
@ -440,7 +439,8 @@ export async function toHaveScreenshot(
|
||||||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, errorMessage, log);
|
const header = matcherHint(this, undefined, 'toHaveScreenshot', receiver, undefined, undefined, timeout);
|
||||||
|
return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFileSync(aPath: string, content: Buffer | string) {
|
function writeFileSync(aPath: string, content: Buffer | string) {
|
||||||
|
|
|
||||||
|
|
@ -2193,6 +2193,7 @@ export type PageExpectScreenshotResult = {
|
||||||
errorMessage?: string,
|
errorMessage?: string,
|
||||||
actual?: Binary,
|
actual?: Binary,
|
||||||
previous?: Binary,
|
previous?: Binary,
|
||||||
|
timeout?: number,
|
||||||
log?: string[],
|
log?: string[],
|
||||||
};
|
};
|
||||||
export type PageScreenshotParams = {
|
export type PageScreenshotParams = {
|
||||||
|
|
|
||||||
|
|
@ -1501,6 +1501,7 @@ Page:
|
||||||
errorMessage: string?
|
errorMessage: string?
|
||||||
actual: binary?
|
actual: binary?
|
||||||
previous: binary?
|
previous: binary?
|
||||||
|
timeout: number?
|
||||||
log:
|
log:
|
||||||
type: array?
|
type: array?
|
||||||
items: string
|
items: string
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,9 @@ for (const useIntermediateMergeReport of [true, false] as const) {
|
||||||
await expect(page.locator('text=Image mismatch')).toHaveCount(1);
|
await expect(page.locator('text=Image mismatch')).toHaveCount(1);
|
||||||
await expect(page.locator('text=Snapshot mismatch')).toHaveCount(0);
|
await expect(page.locator('text=Snapshot mismatch')).toHaveCount(0);
|
||||||
await expect(page.locator('.chip-header', { hasText: 'Screenshots' })).toHaveCount(0);
|
await expect(page.locator('.chip-header', { hasText: 'Screenshots' })).toHaveCount(0);
|
||||||
await expect(page.getByTestId('test-result-image-mismatch-tabs').locator('div')).toHaveText([
|
const errorChip = page.getByTestId('test-screenshot-error-view');
|
||||||
|
await expect(errorChip).toContainText('Failed to take two consecutive stable screenshots.');
|
||||||
|
await expect(errorChip.getByTestId('test-result-image-mismatch-tabs').locator('div')).toHaveText([
|
||||||
'Diff',
|
'Diff',
|
||||||
'Actual',
|
'Actual',
|
||||||
'Previous',
|
'Previous',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue