diff --git a/packages/ui/node/reporter.ts b/packages/ui/node/reporter.ts index 8ad956bc37b7..b15857c18924 100644 --- a/packages/ui/node/reporter.ts +++ b/packages/ui/node/reporter.ts @@ -90,6 +90,14 @@ export default class HTMLReporter implements Reporter { promises.push(this.processAttachment(attachment)) } }) + task.artifacts.forEach((artifact) => { + const attachments = artifact.attachments + if (attachments) { + attachments.forEach((attachment) => { + promises.push(this.processAttachment(attachment)) + }) + } + }) } else { task.tasks.forEach(processAttachments) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb3b1918ccde..2ccb7e1aca5d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1540,6 +1540,9 @@ importers: '@testing-library/dom': specifier: ^10.4.1 version: 10.4.1 + '@vitest/browser-playwright': + specifier: workspace:* + version: link:../../packages/browser-playwright happy-dom: specifier: latest version: 20.1.0 diff --git a/test/ui/fixtures-browser/visual-regression.test.ts b/test/ui/fixtures-browser/visual-regression.test.ts new file mode 100644 index 000000000000..177d2459bb51 --- /dev/null +++ b/test/ui/fixtures-browser/visual-regression.test.ts @@ -0,0 +1,16 @@ +import { test } from 'vitest' +import { server } from 'vitest/browser' + +test('visual regression test', async ({ expect, onTestFinished }) => { + const screenshotName = 'visual-regression-screenshot.png' + + onTestFinished(async () => { + if (server.config.snapshotOptions.updateSnapshot !== 'none') { + await server.commands.removeFile(`fixtures-browser/${screenshotName}`) + } + }) + + await expect(expect(document.body).toMatchScreenshot(screenshotName)).rejects.toThrowError( + 'No existing reference screenshot found', + ) +}) diff --git a/test/ui/package.json b/test/ui/package.json index 07669c11632d..4688ad3a9862 100644 --- a/test/ui/package.json +++ b/test/ui/package.json @@ -10,6 +10,7 @@ }, "devDependencies": { "@testing-library/dom": "^10.4.1", + "@vitest/browser-playwright": "workspace:*", "happy-dom": "latest", "vitest": "workspace:*" } diff --git a/test/ui/test/html-report.spec.ts b/test/ui/test/html-report.spec.ts index f7c85e4bae79..9a4d4993bc24 100644 --- a/test/ui/test/html-report.spec.ts +++ b/test/ui/test/html-report.spec.ts @@ -66,7 +66,7 @@ test.describe('html report', () => { await page.goto(pageUrl) // dashboard - await expect(page.locator('[aria-labelledby=tests]')).toContainText('13 Pass 1 Fail 14 Total') + await expect(page.locator('[aria-labelledby=tests]')).toContainText('14 Pass 1 Fail 15 Total') // unhandled errors await expect(page.getByTestId('unhandled-errors')).toContainText( @@ -190,4 +190,23 @@ test.describe('html report', () => { await expect(annotations.last().getByRole('link')).toHaveAttribute('href', /data\/\w+/) await expect(annotations.nth(3).getByRole('link')).toHaveAttribute('href', /data\/\w+/) }) + + test('visual regression in the report tab', async ({ page }) => { + await page.goto(pageUrl) + + await test.step('attachments get processed', async () => { + const item = page.getByLabel('visual regression test') + await item.click({ force: true }) + await page.getByTestId('btn-report').click({ force: true }) + + const artifact = page.getByRole('note') + await expect(artifact).toHaveCount(1) + + await expect(artifact.getByRole('heading')).toContainText('Visual Regression') + await expect(artifact).toContainText('fixtures-browser/visual-regression.test.ts:13:3') + await expect(artifact.getByRole('tablist')).toHaveText('Reference') + await expect(artifact.getByRole('tabpanel').getByRole('link')).toHaveAttribute('href', /data\/\w+\.png/) + await expect(artifact.getByRole('tabpanel').getByRole('img')).toHaveAttribute('src', /data\/\w+\.png/) + }) + }) }) diff --git a/test/ui/test/ui.spec.ts b/test/ui/test/ui.spec.ts index f137759a4ceb..b15fcc473400 100644 --- a/test/ui/test/ui.spec.ts +++ b/test/ui/test/ui.spec.ts @@ -70,7 +70,7 @@ test.describe('ui', () => { await page.goto(pageUrl) // dashboard - await expect(page.locator('[aria-labelledby=tests]')).toContainText('13 Pass 1 Fail 14 Total') + await expect(page.locator('[aria-labelledby=tests]')).toContainText('14 Pass 1 Fail 15 Total') // unhandled errors await expect(page.getByTestId('unhandled-errors')).toContainText( @@ -212,7 +212,7 @@ test.describe('ui', () => { // match all files when no filter await page.getByPlaceholder('Search...').fill('') - await page.getByText('PASS (5)').click() + await page.getByText('PASS (6)').click() await expect(page.getByTestId('details-panel').getByText('fixtures/sample.test.ts', { exact: true })).toBeVisible() // match nothing @@ -289,6 +289,25 @@ test.describe('ui', () => { await expect(page.getByLabel(/fail/i)).not.toBeChecked() await expect(page.getByLabel(/skip/i)).not.toBeChecked() }) + + test('visual regression in the report tab', async ({ page }) => { + await page.goto(pageUrl) + + await test.step('attachments get processed', async () => { + const item = page.getByLabel('visual regression test') + await item.click({ force: true }) + await page.getByTestId('btn-report').click({ force: true }) + + const artifact = page.getByRole('note') + await expect(artifact).toHaveCount(1) + + await expect(artifact.getByRole('heading')).toContainText('Visual Regression') + await expect(artifact).toContainText('fixtures-browser/visual-regression.test.ts:13:3') + await expect(artifact.getByRole('tablist')).toHaveText('Reference') + await expect(artifact.getByRole('tabpanel').getByRole('link')).toHaveAttribute('href', /__vitest_attachment__\?path=.*?\.png/) + await expect(artifact.getByRole('tabpanel').getByRole('img')).toHaveAttribute('src', /__vitest_attachment__\?path=.*?\.png/) + }) + }) }) test.describe('standalone', () => { diff --git a/test/ui/vitest.config.ts b/test/ui/vitest.config.ts index 990367300149..873dea2869c9 100644 --- a/test/ui/vitest.config.ts +++ b/test/ui/vitest.config.ts @@ -1,11 +1,37 @@ +import { resolve } from 'node:path' +import { playwright } from '@vitest/browser-playwright' import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - dir: './fixtures', - environment: 'happy-dom', coverage: { reportOnFailure: true, }, + projects: [{ + extends: true, + test: { + name: 'fixtures', + dir: './fixtures', + environment: 'happy-dom', + }, + }, { + extends: true, + test: { + name: 'browser', + dir: './fixtures-browser', + browser: { + enabled: true, + headless: true, + provider: playwright(), + instances: [{ browser: 'chromium' }], + screenshotFailures: false, + expect: { + toMatchScreenshot: { + resolveScreenshotPath: ({ root, testFileDirectory, arg, ext }) => resolve(root, testFileDirectory, `${arg}${ext}`), + }, + }, + }, + }, + }], }, })