diff --git a/packages/playwright-core/src/utils/comparators.ts b/packages/playwright-core/src/utils/comparators.ts index 7f64df240c..c848200d66 100644 --- a/packages/playwright-core/src/utils/comparators.ts +++ b/packages/playwright-core/src/utils/comparators.ts @@ -109,26 +109,27 @@ function validateBuffer(buffer: Buffer, mimeType: string): void { function compareText(actual: Buffer | string, expectedBuffer: Buffer): ComparatorResult { if (typeof actual !== 'string') return { errorMessage: 'Actual result should be a string' }; - const expected = expectedBuffer.toString('utf-8'); + let expected = expectedBuffer.toString('utf-8'); if (expected === actual) return null; - const diffs = diff.diffChars(expected, actual); - return { - errorMessage: diff_prettyTerminal(diffs), - }; -} + // Eliminate '\\ No newline at end of file' + if (!actual.endsWith('\n')) + actual += '\n'; + if (!expected.endsWith('\n')) + expected += '\n'; -function diff_prettyTerminal(diffs: Diff.Change[]): string { - const result = diffs.map(part => { - const text = part.value; - if (part.added) - return colors.green(text); - else if (part.removed) - return colors.reset(colors.strikethrough(colors.red(text))); - else - return text; + const lines = diff.createPatch('file', expected, actual, undefined, undefined, { context: 5 }).split('\n'); + const coloredLines = lines.slice(4).map(line => { + if (line.startsWith('-')) + return colors.red(line); + if (line.startsWith('+')) + return colors.green(line); + if (line.startsWith('@@')) + return colors.dim(line); + return line; }); - return result.join(''); + const errorMessage = coloredLines.join('\n'); + return { errorMessage }; } function resizeImage(image: ImageData, size: { width: number, height: number }): ImageData { diff --git a/tests/playwright-test/golden.spec.ts b/tests/playwright-test/golden.spec.ts index 340851e384..bf3dbb8880 100644 --- a/tests/playwright-test/golden.spec.ts +++ b/tests/playwright-test/golden.spec.ts @@ -58,7 +58,8 @@ test('should work with non-txt extensions', async ({ runInlineTest }) => { ` }); expect(result.exitCode).toBe(1); - expect(result.output).toContain(`1,2,34`); + expect(result.rawOutput).toContain(colors.red('-1,2,3')); + expect(result.rawOutput).toContain(colors.green('+1,2,4')); }); @@ -202,8 +203,8 @@ Line7`, }); expect(result.exitCode).toBe(1); expect(result.output).toContain('Line1'); - expect(result.rawOutput).toContain('Line2' + colors.green('2')); - expect(result.rawOutput).toContain('line' + colors.reset(colors.strikethrough(colors.red('1'))) + colors.green('2')); + expect(result.rawOutput).toContain(colors.red('-Line2')); + expect(result.rawOutput).toContain(colors.green('+Line22')); expect(result.output).toContain('Line3'); expect(result.output).toContain('Line5'); expect(result.output).toContain('Line7'); diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index 63d4c34a28..4b294126b9 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -916,7 +916,7 @@ for (const useIntermediateMergeReport of [true, false] as const) { ])); }); - test('should strikethrough textual diff', async ({ runInlineTest, showReport, page }) => { + test('should highlight textual diff', async ({ runInlineTest, showReport, page }) => { const result = await runInlineTest({ 'helper.ts': ` import { test as base } from '@playwright/test'; @@ -940,36 +940,8 @@ for (const useIntermediateMergeReport of [true, false] as const) { await showReport(); await page.click('text="is a test"'); - await expect(page.locator('.test-error-view').getByText('old')).toHaveCSS('text-decoration', 'line-through solid rgb(205, 49, 49)'); - await expect(page.locator('.test-error-view').getByText('new', { exact: true })).toHaveCSS('text-decoration', 'none solid rgb(0, 188, 0)'); - }); - - test('should strikethrough textual diff with commonalities', async ({ runInlineTest, showReport, page }) => { - const result = await runInlineTest({ - 'helper.ts': ` - import { test as base } from '@playwright/test'; - export * from '@playwright/test'; - export const test = base.extend({ - auto: [ async ({}, run, testInfo) => { - testInfo.snapshotSuffix = ''; - await run(); - }, { auto: true } ] - }); - `, - 'a.spec.js-snapshots/snapshot.txt': `oldcommon`, - 'a.spec.js': ` - const { test, expect } = require('./helper'); - test('is a test', ({}) => { - expect('newcommon').toMatchSnapshot('snapshot.txt'); - }); - ` - }, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' }); - expect(result.exitCode).toBe(1); - await showReport(); - await page.click('text="is a test"'); - await expect(page.locator('.test-error-view').getByText('old')).toHaveCSS('text-decoration', 'line-through solid rgb(205, 49, 49)'); - await expect(page.locator('.test-error-view').getByText('new', { exact: true })).toHaveCSS('text-decoration', 'none solid rgb(0, 188, 0)'); - await expect(page.locator('.test-error-view').getByText('common Expected:')).toHaveCSS('text-decoration', 'none solid rgb(36, 41, 47)'); + await expect(page.locator('.test-error-view').getByText('-old')).toHaveCSS('color', 'rgb(205, 49, 49)'); + await expect(page.locator('.test-error-view').getByText('+new', { exact: true })).toHaveCSS('color', 'rgb(0, 188, 0)'); }); test('should highlight inline textual diff in toHaveText', async ({ runInlineTest, showReport, page }) => {