Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,18 @@ jobs:
run: npx playwright install chromium firefox

- name: Test
run: node --run test
run: node --run test:ci
timeout-minutes: 4

- name: Visual regression test
run: node --run visual

- name: Upload test failure artifacts
if: failure()
uses: actions/upload-artifact@v7
with:
name: test-artifacts
path: |
test/browser/**/__screenshots__/**
test/browser/**/__traces__/**
.vitest-attachments/test/**/*
test/**/__screenshots__/**
test/**/__traces__/**
.vitest-attachments/test/**
if-no-files-found: ignore

- name: Upload coverage
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,9 @@ jobs:
run: npx playwright install chromium firefox

- name: Test
run: node --run test
run: node --run test:ci
timeout-minutes: 4

- name: Visual regression test
run: node --run visual

- name: Update version
run: |
git config user.name "${{ github.actor }}"
Expand Down
20 changes: 6 additions & 14 deletions .github/workflows/update-screenshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ on:
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' || github.event_name == 'workflow_dispatch' }}
Expand Down Expand Up @@ -46,12 +38,12 @@ jobs:
run: npx playwright install chromium firefox
- name: Update screenshots
run: |
rm -r test/visual/__screenshots__
node --run visual:update
rm -r test/**/screenshots/**
node --run test:ci: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 config user.name "${{ github.actor }}"
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
git add "test/**/screenshots/**"
git diff-index --quiet HEAD || git commit -m "Update screenshots"
git push
10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
/.cache
/.claude
/coverage
/dist
/lib
/node_modules
/package-lock.json
test/browser/**/__screenshots__

npm-debug.log
**.orig
.idea
.vitest-attachments

__traces__
# Vitest
/.vitest-attachments
/coverage
/test/**/__screenshots__
/test/**/__traces__
/test/**/screenshots/**/*-win32.png
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the win32.png line so I'm not inconvenienced when testing things locally

2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ website/ # demo site (Vite + TanStack Router)
- Browser tests use `vitest/browser` + Playwright. `test/setupBrowser.ts` configures `page.render()` via `vitest-browser-react` and registers custom locators via `locators.extend()` — prefer `page.getGrid()`, `page.getCell({ name })`, `page.getRow()`, `page.getHeaderCell()`, `page.getSelectedCell()`, etc. over raw `page.getByRole()`.
- Test helpers in `test/browser/utils.tsx`: `setup()`, `getRowWithCell()`, `getCellsAtRowIndex()`, `validateCellPosition()`, `scrollGrid()`, `tabIntoGrid()`, `testCount()`, `testRowCount()`.
- `test/failOnConsole.ts` fails tests on unexpected console warnings/errors.
- **Never run visual regression tests locally** — screenshots are CI-only and environment-dependent.
- **Never run visual regression tests** — screenshots are environment-dependent so visual regression tests must run in CI only.

## Validation

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
"preview": "vite preview",
"build:website": "vite build",
"build": "rolldown -c",
"test": "vitest run --project browser --project node --coverage.reportsDirectory='./coverage/test'",
"test": "vitest run --project browser --project node",
"test:watch": "vitest watch --project browser --project node",
"visual": "vitest run --project visual --coverage.reportsDirectory='./coverage/visual'",
"visual:update": "vitest run --project visual --update",
"test:ci": "vitest run",
"test:ci:update": "vitest run --project visual --update",
"format": "oxfmt",
"format:check": "oxfmt --check",
"eslint": "eslint --max-warnings 0 --cache --cache-location .cache/eslint --cache-strategy content",
Expand Down
49 changes: 35 additions & 14 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,31 @@ const dragFill: BrowserCommand<[from: string, to: string]> = async ({ page, ifra
await page.mouse.up();
};

const actionTimeout = 2000;
const viewport = { width: 1920, height: 1080 } as const;
const playwrightOptions: PlaywrightProviderOptions = {
actionTimeout,
contextOptions: {
viewport
}
};

// vitest modifies the instance objects, so we cannot rely on static objects
// https://github.com/vitest-dev/vitest/issues/9877
function getInstances(): BrowserInstanceOption[] {
const opts: PlaywrightProviderOptions = {
actionTimeout: 2000,
contextOptions: {
viewport
}
};

return [
{
browser: 'chromium',
provider: playwright({
...opts,
...playwrightOptions,
launchOptions: {
channel: 'chromium'
}
})
},
{
browser: 'firefox',
provider: playwright(opts),
provider: playwright(playwrightOptions),
// TODO: remove when FF tests are stable
fileParallelism: false
}
Expand All @@ -74,6 +75,7 @@ export default defineConfig(
base: '/react-data-grid/',
cacheDir: '.cache/vite',
clearScreen: false,
define: isTest ? { __IS_CI__: JSON.stringify(isCI) } : {},
build: {
modulePreload: { polyfill: false },
sourcemap: true,
Expand Down Expand Up @@ -107,15 +109,20 @@ export default defineConfig(
},
restoreMocks: true,
sequence: {
shuffle: true
shuffle: {
files: false,
tests: true
}
},
expect: {
poll: {
timeout: actionTimeout
}
},
slowTestThreshold: 1000,
projects: [
{
extends: true,
define: {
__IS_CI__: JSON.stringify(isCI)
},
test: {
name: 'browser',
include: ['browser/**/*.test.*'],
Expand All @@ -141,7 +148,21 @@ export default defineConfig(
viewport,
headless: true,
ui: false,
screenshotFailures: false
expect: {
toMatchScreenshot: {
resolveScreenshotPath({
root,
testFileDirectory,
testFileName,
arg,
browserName,
platform,
ext
}) {
return `${root}/${testFileDirectory}/screenshots/${testFileName}/${arg}-${browserName}-${platform}${ext}`;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can properly differentiate between failure screenshots and test screenshots.
So now we can capture screenshots failures in visual tests as well.
https://vitest.dev/config/browser/expect.html#browser-expect-tomatchscreenshot-resolvescreenshotpath

}
}
}
},
setupFiles: ['test/setupBrowser.ts', 'test/failOnConsole.ts']
}
Expand Down