diff --git a/packages/html-reporter/src/testErrorView.tsx b/packages/html-reporter/src/testErrorView.tsx
index 06cfdfd45b..46e3f880c7 100644
--- a/packages/html-reporter/src/testErrorView.tsx
+++ b/packages/html-reporter/src/testErrorView.tsx
@@ -34,10 +34,10 @@ export const TestScreenshotErrorView: React.FC<{
}> = ({ errorPrefix, diff, errorSuffix }) => {
const prefixHtml = React.useMemo(() => ansiErrorToHtml(errorPrefix), [errorPrefix]);
const suffixHtml = React.useMemo(() => ansiErrorToHtml(errorSuffix), [errorSuffix]);
- return
+ return
;
};
diff --git a/packages/html-reporter/src/testResultView.tsx b/packages/html-reporter/src/testResultView.tsx
index b2e899ebfb..ed7037999e 100644
--- a/packages/html-reporter/src/testResultView.tsx
+++ b/packages/html-reporter/src/testResultView.tsx
@@ -107,7 +107,7 @@ export const TestResultView: React.FC<{
}
{diffs.map((diff, index) =>
-
+
)}
@@ -160,17 +160,23 @@ function classifyErrors(testErrors: string[], diffs: ImageDiff[]) {
continue;
if (!error.includes(diff.actual!.attachment.name))
continue;
- const index = error.search(/Expected:|Previous:|Received:/);
+
+ const lines = error.split('\n');
+ const index = lines.findIndex(line => line.match(/Expected:|Previous:|Received:/));
let errorPrefix;
if (index !== -1)
- errorPrefix = error.slice(0, index);
+ errorPrefix = lines.slice(0, index).join('\n');
else
- errorPrefix = error.split('\n')[0];
+ errorPrefix = lines[0];
- const callLog = error.indexOf('Call log:');
let errorSuffix;
- if (callLog !== -1)
- errorSuffix = error.slice(callLog);
+ const diffIndex = lines.findIndex(line => line.match(/ +Diff:/));
+ // Skip one empty line after the diff too.
+ if (diffIndex !== -1)
+ errorSuffix = lines.slice(diffIndex + 2).join('\n');
+ else
+ errorSuffix = lines.slice(1).join('\n');
+
screenshotError = { type: 'screenshot', diff, errorPrefix, errorSuffix };
}
}
diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts
index 4deb2f3de9..9382e0bb60 100644
--- a/tests/playwright-test/reporter-html.spec.ts
+++ b/tests/playwright-test/reporter-html.spec.ts
@@ -179,7 +179,7 @@ for (const useIntermediateMergeReport of [false] as const) {
await expect(page.locator('text=Image mismatch')).toBeVisible();
await expect(page.locator('text=Snapshot mismatch')).toHaveCount(0);
- await expect(page.getByTestId('test-result-image-mismatch-tabs').locator('div')).toHaveText([
+ await expect(page.getByTestId('test-screenshot-error-view').getByTestId('test-result-image-mismatch-tabs').locator('div')).toHaveText([
'Diff',
'Actual',
'Expected',
@@ -187,36 +187,40 @@ for (const useIntermediateMergeReport of [false] as const) {
'Slider',
]);
- const imageDiff = page.getByTestId('test-result-image-mismatch');
- await test.step('Diff', async () => {
- await expect(imageDiff.locator('img')).toHaveAttribute('alt', 'Diff');
- });
+ for (const testId of ['test-results-image-diff', 'test-screenshot-error-view']) {
+ await test.step(testId, async () => {
+ const imageDiff = page.getByTestId(testId).getByTestId('test-result-image-mismatch');
+ await test.step('Diff', async () => {
+ await expect(imageDiff.locator('img')).toHaveAttribute('alt', 'Diff');
+ });
- await test.step('Actual', async () => {
- await imageDiff.getByText('Actual', { exact: true }).click();
- await expect(imageDiff.locator('img')).toHaveAttribute('alt', 'Actual');
- });
+ await test.step('Actual', async () => {
+ await imageDiff.getByText('Actual', { exact: true }).click();
+ await expect(imageDiff.locator('img')).toHaveAttribute('alt', 'Actual');
+ });
- await test.step('Expected', async () => {
- await imageDiff.getByText('Expected', { exact: true }).click();
- await expect(imageDiff.locator('img')).toHaveAttribute('alt', 'Expected');
- });
+ await test.step('Expected', async () => {
+ await imageDiff.getByText('Expected', { exact: true }).click();
+ await expect(imageDiff.locator('img')).toHaveAttribute('alt', 'Expected');
+ });
- await test.step('Side by side', async () => {
- await imageDiff.getByText('Side by side').click();
- await expect(imageDiff.locator('img')).toHaveCount(2);
- await expect(imageDiff.locator('img').first()).toHaveAttribute('alt', 'Expected');
- await expect(imageDiff.locator('img').last()).toHaveAttribute('alt', 'Actual');
- await imageDiff.locator('img').last().click();
- await expect(imageDiff.locator('img').last()).toHaveAttribute('alt', 'Diff');
- });
+ await test.step('Side by side', async () => {
+ await imageDiff.getByText('Side by side').click();
+ await expect(imageDiff.locator('img')).toHaveCount(2);
+ await expect(imageDiff.locator('img').first()).toHaveAttribute('alt', 'Expected');
+ await expect(imageDiff.locator('img').last()).toHaveAttribute('alt', 'Actual');
+ await imageDiff.locator('img').last().click();
+ await expect(imageDiff.locator('img').last()).toHaveAttribute('alt', 'Diff');
+ });
- await test.step('Slider', async () => {
- await imageDiff.getByText('Slider', { exact: true }).click();
- await expect(imageDiff.locator('img')).toHaveCount(2);
- await expect(imageDiff.locator('img').first()).toHaveAttribute('alt', 'Expected');
- await expect(imageDiff.locator('img').last()).toHaveAttribute('alt', 'Actual');
- });
+ await test.step('Slider', async () => {
+ await imageDiff.getByText('Slider', { exact: true }).click();
+ await expect(imageDiff.locator('img')).toHaveCount(2);
+ await expect(imageDiff.locator('img').first()).toHaveAttribute('alt', 'Expected');
+ await expect(imageDiff.locator('img').last()).toHaveAttribute('alt', 'Actual');
+ });
+ });
+ }
});
test('should include multiple image diffs', async ({ runInlineTest, page, showReport }) => {
@@ -285,8 +289,14 @@ for (const useIntermediateMergeReport of [false] as const) {
await showReport();
await page.click('text=fails');
- await expect(page.locator('data-testid=test-result-image-mismatch')).toHaveCount(3);
- await expect(page.locator('text=Image mismatch:')).toHaveText([
+ await expect(page.getByTestId('test-screenshot-error-view').getByTestId('error-suffix')).toContainText([
+ `> 6 | await expect.soft(screenshot).toMatchSnapshot('expected.png');`,
+ `> 7 | await expect.soft(screenshot).toMatchSnapshot('expected.png');`,
+ `> 8 | await expect.soft(screenshot).toMatchSnapshot('expected.png');`,
+ ]);
+ const imageDiffs = page.getByTestId('test-results-image-diff');
+ await expect(imageDiffs.getByTestId('test-result-image-mismatch')).toHaveCount(3);
+ await expect(imageDiffs.getByText('Image mismatch:')).toHaveText([
'Image mismatch: expected.png',
'Image mismatch: expected-1.png',
'Image mismatch: expected-2.png',