diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96b0653fdb..579172773d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: with: node-version: 25 check-latest: true - - name: npm install + - name: Install dependencies run: npm i - name: Biome run: node --run biome:ci @@ -33,6 +33,8 @@ jobs: - name: Test run: node --run test timeout-minutes: 4 + - name: Visual regression test + run: node --run visual - name: Upload coverage uses: codecov/codecov-action@v5 with: diff --git a/.github/workflows/update-screenshots.yml b/.github/workflows/update-screenshots.yml new file mode 100644 index 0000000000..50fc57b1cb --- /dev/null +++ b/.github/workflows/update-screenshots.yml @@ -0,0 +1,56 @@ +name: Update Screenshots + +on: + pull_request: + types: [labeled] + workflow_dispatch: + +env: + AUTHOR_NAME: 'github-actions[bot]' + AUTHOR_EMAIL: '41898282+github-actions[bot]@users.noreply.github.com' + COMMIT_MESSAGE: | + Update screenshots + + Co-authored-by: ${{ github.actor }} + +jobs: + update-screenshots: + if: ${{ github.event.label.name == 'Update Screenshots' }} + runs-on: ubuntu-latest + + permissions: + contents: write + pull-requests: write + + # one at a time per branch + concurrency: + group: update-screenshots@${{ github.head_ref }} + cancel-in-progress: true + + steps: + - uses: actions/checkout@v5 + with: + ref: ${{ github.head_ref }} + - uses: actions/setup-node@v6 + with: + node-version: 25 + check-latest: true + - name: Remove label + run: gh pr edit --remove-label 'Update Screenshots' + env: + GH_TOKEN: ${{ github.token }} + - name: Install dependencies + run: npm i + - name: Install Playwright Browsers + run: npx playwright install chromium firefox + - name: Update screenshots + run: | + rm -r test/visual/__screenshots__ + node --run visual:update + - name: Push new screenshots + run: | + git config --global user.name "${{ env.AUTHOR_NAME }}" + git config --global user.email "${{ env.AUTHOR_EMAIL }}" + git add test/visual/__screenshots__/. + git diff-index --quiet HEAD || git commit -m "${{ env.COMMIT_MESSAGE }}" + git push diff --git a/.gitignore b/.gitignore index 202fe72c65..47ab83bf80 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ /lib /node_modules /package-lock.json -__screenshots__ +test/browser/**/__screenshots__ npm-debug.log **.orig diff --git a/package.json b/package.json index 3ed1917cef..811b6d9cae 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,10 @@ "preview": "vite preview", "build:website": "vite build", "build": "rolldown -c", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "vitest run --project browser --project node --coverage.reportsDirectory='./coverage/test'", + "test:watch": "vitest watch --project browser --project node", + "visual": "vitest run --project visual --coverage.reportsDirectory='./coverage/visual'", + "visual:update": "vitest run --project visual --update", "format": "biome format --write", "check": "biome check --error-on-warnings", "biome:ci": "biome ci --error-on-warnings", diff --git a/test/visual/__screenshots__/basicGrid.test.tsx/basic-grid-chromium-linux.png b/test/visual/__screenshots__/basicGrid.test.tsx/basic-grid-chromium-linux.png new file mode 100644 index 0000000000..b055c80eb5 Binary files /dev/null and b/test/visual/__screenshots__/basicGrid.test.tsx/basic-grid-chromium-linux.png differ diff --git a/test/visual/__screenshots__/basicGrid.test.tsx/basic-grid-firefox-linux.png b/test/visual/__screenshots__/basicGrid.test.tsx/basic-grid-firefox-linux.png new file mode 100644 index 0000000000..bcfa819d45 Binary files /dev/null and b/test/visual/__screenshots__/basicGrid.test.tsx/basic-grid-firefox-linux.png differ diff --git a/test/visual/basicGrid.test.tsx b/test/visual/basicGrid.test.tsx new file mode 100644 index 0000000000..efba45aca8 --- /dev/null +++ b/test/visual/basicGrid.test.tsx @@ -0,0 +1,54 @@ +import { page } from 'vitest/browser'; + +import { DataGrid, SelectColumn, type Column } from '../../src'; +import { getGrid } from '../browser/utils'; + +interface Row { + id: number; + name: string; +} + +const columns: readonly Column[] = [ + SelectColumn, + { + key: 'name', + name: 'Name', + renderSummaryCell(props) { + return props.row.name; + } + } +]; + +const rows: readonly Row[] = [ + { id: 1, name: 'Row 1' }, + { id: 2, name: 'Row 2' }, + { id: 3, name: 'Row 3' } +]; + +const topSummaryRows: readonly Row[] = [ + { id: 4, name: 'Top Summary Row 1' }, + { id: 5, name: 'Top Summary Row 2' } +]; + +const bottomSummaryRows: readonly Row[] = [ + { id: 6, name: 'Bottom Summary Row 1' }, + { id: 7, name: 'Bottom Summary Row 2' } +]; + +function rowKeyGetter(row: Row) { + return row.id; +} + +test('basic grid', async () => { + await page.render( + + ); + + await expect(getGrid()).toMatchScreenshot('basic-grid'); +}); diff --git a/vite.config.ts b/vite.config.ts index 9c3cf13f04..8512ec3602 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -137,6 +137,26 @@ export default defineConfig( setupFiles: ['test/setupBrowser.ts'] } }, + { + extends: true, + test: { + name: 'visual', + include: ['test/visual/*.test.*'], + browser: { + enabled: true, + provider: playwright({ + contextOptions: { + viewport + } + }), + instances: [{ browser: 'chromium' }, { browser: 'firefox' }], + viewport, + headless: true, + screenshotFailures: false + }, + setupFiles: ['test/setupBrowser.ts'] + } + }, { extends: true, test: {