Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
9109505
RFC: Migrate from tape to vitest
chrisgervang Jan 27, 2026
659c49f
RFC: Add multi-environment architecture and expanded implementation plan
chrisgervang Jan 27, 2026
ee46a47
RFC: Add @deck.gl/test-utils deprecation timeline
chrisgervang Jan 27, 2026
04b8519
chore(test): add vitest infrastructure
chrisgervang Jan 28, 2026
718a052
chore(test): add tape-to-vitest migration script
chrisgervang Jan 28, 2026
4949e46
chore(test): convert test files from tape to vitest
chrisgervang Jan 28, 2026
d632932
chore(test): add TODO for typed array equality tester removal
chrisgervang Jan 28, 2026
541f0c1
chore(test): remove obsolete gpu-grid-layer test
chrisgervang Jan 28, 2026
3b187e2
chore(test): convert spy.called to vitest toHaveBeenCalled()
chrisgervang Jan 29, 2026
fd05149
chore: ignore yarn engine checks for vitest dependencies
chrisgervang Jan 29, 2026
8c1954a
chore(test): remove unused describe imports from vitest conversions
chrisgervang Jan 29, 2026
47e1d61
chore: ignore vite.config.local.mjs in eslint
chrisgervang Jan 29, 2026
14d3c7c
chore(test): convert t.pass() to console.log() in vitest migration
chrisgervang Jan 29, 2026
f14ccae
chore(test): handle test.skip and test.only in vitest migration
chrisgervang Jan 29, 2026
9e75ff6
fix(test): preserve assertion message in assert callback conversion
chrisgervang Jan 29, 2026
c2955bb
chore(test): handle expression body arrow functions in migration
chrisgervang Jan 29, 2026
2f77513
fix(ci): install Playwright browsers and use headless project
chrisgervang Jan 29, 2026
c8eef73
fix(test): exclude tests that were not in original CI suite
chrisgervang Jan 29, 2026
cfffba1
chore(test): restructure test commands with vitest projects
chrisgervang Jan 30, 2026
b0280a0
docs(rfc): update vitest migration RFC with implementation details
chrisgervang Jan 30, 2026
84ff56c
fix(test): convert makeSpy to vi.spyOn for browser compatibility
chrisgervang Jan 30, 2026
4a35838
fix(test): convert spy.restore/reset to mockRestore/mockReset
chrisgervang Jan 30, 2026
f2402ce
fix(test): convert spy.called to toHaveBeenCalled matcher
chrisgervang Jan 30, 2026
e95ae27
fix(test): handle nested t.test() conversion in migration script
chrisgervang Jan 30, 2026
d616d74
fix(test): address diff comment issues
chrisgervang Jan 30, 2026
cc69f73
chore(test): add manual fix skip list to migration script
chrisgervang Jan 30, 2026
6161023
fix(test): convert spy.callCount to toHaveBeenCalledTimes
chrisgervang Jan 30, 2026
fd9930c
fix(test): pass message to expect assertions for better error messages
chrisgervang Jan 30, 2026
8fce5f5
fix(test): convert spy.callCount to toHaveBeenCalledTimes in terrain …
chrisgervang Jan 30, 2026
4766b53
chore(test): exclude tests that were commented out on master
chrisgervang Jan 30, 2026
7054272
feat(test): add browser commands for vitest test runner
chrisgervang Jan 30, 2026
a9edc69
feat(test): add interaction and render test specs for vitest
chrisgervang Jan 30, 2026
b1e947f
docs: update CONTRIBUTING and RFC with vitest migration progress
chrisgervang Jan 30, 2026
a4ffad0
chore(deps): add image comparison dependencies for vitest
chrisgervang Jan 30, 2026
facc654
fix(scripts): remove unused fullCall variable in migration script
chrisgervang Jan 30, 2026
354485a
fix(test): add await detection for testLayerAsync and exclude failing…
chrisgervang Jan 30, 2026
a14cd26
fix(test): rename jupyter-widget utility file to not have .spec suffix
chrisgervang Jan 30, 2026
ed053cc
fix(test-utils): use mockRestore instead of mockClear for spy cleanup
chrisgervang Jan 30, 2026
cea4d17
chore(test): reduce verbose logging and use TAP for CI
chrisgervang Feb 1, 2026
8bcb3ee
RFC: Migrate from tape to vitest
chrisgervang Jan 27, 2026
d44d9d5
RFC: Add multi-environment architecture and expanded implementation plan
chrisgervang Jan 27, 2026
237a9f6
RFC: Add @deck.gl/test-utils deprecation timeline
chrisgervang Jan 27, 2026
7750fed
RFC: Update CLI commands and finalize Phase 4 discovery outcome
chrisgervang Jan 30, 2026
a30500c
fix(test-utils): enable es2022 for top-level await support
chrisgervang Feb 2, 2026
5e4683f
chore: merge chr/tape-to-vitest into chr/vitest-setup
chrisgervang Feb 2, 2026
d5a9bbf
feat(test-utils): add backward compatibility for tape/probe.gl users
chrisgervang Feb 2, 2026
c711bb8
fix(vitest): pre-bundle dependencies to prevent CI flakiness
chrisgervang Feb 2, 2026
6c04566
ci: split test steps for better visibility
chrisgervang Feb 3, 2026
ad34130
ci: use npx for vitest commands
chrisgervang Feb 3, 2026
16b3e9d
fix(test-utils): make spy framework initialization lazy
chrisgervang Feb 4, 2026
305668e
fix(test-utils): enable test-utils import in Node with NullDevice fal…
chrisgervang Feb 4, 2026
beb5176
feat(test-utils): add Injectable Spy API for framework-agnostic testing
chrisgervang Feb 4, 2026
ae7e43f
RFC: Migrate from tape to vitest
chrisgervang Jan 27, 2026
b4d166d
RFC: Add multi-environment architecture and expanded implementation plan
chrisgervang Jan 27, 2026
8c8ed22
RFC: Add @deck.gl/test-utils deprecation timeline
chrisgervang Jan 27, 2026
ec43806
RFC: Update CLI commands and finalize Phase 4 discovery outcome
chrisgervang Jan 30, 2026
bb7a6a5
RFC: Add injectable spy API, Phase 5 outcome, and Phase 7
chrisgervang Feb 4, 2026
5443914
Merge branch 'origin/chr/tape-to-vitest' into chr/vitest-setup
chrisgervang Feb 4, 2026
e8aa70c
chore(test): add createSpy to all testLayer calls (migration script o…
chrisgervang Feb 4, 2026
2ab06f0
chore(test): separate render tests into dedicated vitest project
chrisgervang Feb 5, 2026
a6acf0c
chore(test): fix test-render script and add separate entry points
chrisgervang Feb 5, 2026
4f7be42
chore(test-utils): add vi.spyOn default to vitest entry point
chrisgervang Feb 5, 2026
1f8ff88
chore(test): update migration script to use @deck.gl/test-utils/vitest
chrisgervang Feb 5, 2026
5002217
chore(test): migrate unit tests to @deck.gl/test-utils/vitest
chrisgervang Feb 5, 2026
329e6cc
chore(test): update core-layers.node.spec.ts to use vitest entry
chrisgervang Feb 5, 2026
8250c0f
chore(test): remove old tape/probe.gl test entry points
chrisgervang Feb 5, 2026
f067e09
chore(test): convert interaction tests to native vitest browser mode
chrisgervang Feb 6, 2026
de68ae4
chore(test): include interaction tests in headless project
chrisgervang Feb 6, 2026
875b0c4
chore(test): convert render tests to native vitest with test.each
chrisgervang Feb 6, 2026
c406bc3
chore(test): fix render test layer loading and use tap reporter
chrisgervang Feb 6, 2026
0eb3d30
chore(test): add views, effects, and useDevicePixels support to rende…
chrisgervang Feb 6, 2026
c84c896
chore(test): fix render test timeouts with absolute URLs and new Deck…
chrisgervang Feb 6, 2026
959390b
chore(test): add skip support for render tests and skip timeout tests
chrisgervang Feb 7, 2026
4b88f59
RFC: Migrate from tape to vitest
chrisgervang Jan 27, 2026
16437f1
RFC: Add multi-environment architecture and expanded implementation plan
chrisgervang Jan 27, 2026
4579dfb
RFC: Add @deck.gl/test-utils deprecation timeline
chrisgervang Jan 27, 2026
f860847
RFC: Update CLI commands and finalize Phase 4 discovery outcome
chrisgervang Jan 30, 2026
7119e0f
RFC: Add injectable spy API, Phase 5 outcome, and Phase 7
chrisgervang Feb 4, 2026
0a646af
Merge remote-tracking branch 'origin/chr/tape-to-vitest' into chr/vit…
chrisgervang Feb 7, 2026
f8a9a0b
fix(test): fix collision-filter-effect test expectation
chrisgervang Feb 7, 2026
d127bda
fix(test-utils): make @probe.gl/test-utils a required peer dependency
chrisgervang Feb 7, 2026
ac1293a
fix(test): use mockClear instead of mockReset for spy.reset conversion
chrisgervang Feb 7, 2026
119252b
chore(test): use @deck.gl/test-utils/vitest entry point for all spec …
chrisgervang Feb 7, 2026
0c3fa68
fix(test): correctly convert t.throws regex matchers to toThrow()
chrisgervang Feb 7, 2026
972be68
chore(test): add tap-spec formatter for prettier test output
chrisgervang Feb 16, 2026
2b7bf5e
chore(ci): upload render test failure images as artifacts
chrisgervang Feb 16, 2026
394fe75
chore(test): update golden images for mvt-layer and post-process-effects
chrisgervang Feb 27, 2026
6becbcd
RFC: Migrate from tape to vitest
chrisgervang Jan 27, 2026
d2f2f23
RFC: Add multi-environment architecture and expanded implementation plan
chrisgervang Jan 27, 2026
8a60964
RFC: Add @deck.gl/test-utils deprecation timeline
chrisgervang Jan 27, 2026
c8e9bd9
RFC: Update CLI commands and finalize Phase 4 discovery outcome
chrisgervang Jan 30, 2026
ed2dece
RFC: Add injectable spy API, Phase 5 outcome, and Phase 7
chrisgervang Feb 4, 2026
a999c4b
Merge branch 'chr/tape-to-vitest' into chr/vitest-setup
chrisgervang Feb 27, 2026
2763739
chore(test): restore coverage TODO and run migration script
chrisgervang Feb 27, 2026
754737e
fix(test): add dblclick support to browser emulateInput command
chrisgervang Feb 27, 2026
907474f
chore(test): replace tap-spec with vitest default reporter
chrisgervang Feb 27, 2026
6b9de2f
fix(test): improve modifier key handling for dblclick events
chrisgervang Feb 27, 2026
b2970ad
refactor(test): split render tests into individual spec files
chrisgervang Feb 27, 2026
3ab80db
fix(test): fix timeline render tests by reusing Deck instance
chrisgervang Feb 27, 2026
fe58fe9
fix(test): unskip scatterplot-transition-3 and transition-4 tests
chrisgervang Feb 27, 2026
7f083a7
revert(test): restore original arc-lnglat and gridcell-lnglat golden …
chrisgervang Feb 27, 2026
d81014e
Merge branch 'origin/chr/tape-to-vitest' into chr/vitest-setup
chrisgervang Feb 27, 2026
8619d9f
chore: remove --ignore-engines and add playwright postinstall
chrisgervang Feb 27, 2026
39e5275
feat(test): upgrade vitest from 2.x to 4.x
chrisgervang Feb 27, 2026
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
4 changes: 3 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ mapbox-gl.js
.docusaurus
examples/layer-browser/
test/apps/
bindings/
bindings/
# TODO: Remove once eslint-plugin-import supports vite 5.x (vitest brings vite 5.x, master uses 4.x)
examples/vite.config.local.mjs
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ module.exports = getESLintConfig({
'**/test/**/*.ts',
'**/scripts/**/*.js',
'*.config.js',
'*.config.ts',
'*.workspace.ts',
'*.config.local.js',
'*.config.local.mjs'
],
Expand Down
42 changes: 33 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,41 @@ jobs:
- name: Build packages
run: yarn build

- name: Run tests
run: |
yarn lint
yarn test ci
- name: Install Playwright browsers
run: npx playwright install chromium

- name: Lint
run: yarn lint

- name: Run Node tests
run: npx vitest run --project node --silent

- name: Coveralls
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6
- name: Run Headless browser tests
run: npx vitest run --project headless --silent

- name: Run Render/Interaction tests
run: yarn test-render

- name: Upload render test failure images
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fail-on-error: false

name: render-test-failures
path: |
test/render/golden-images/*-fail.png
test/render/golden-images/*-diff.png
if-no-files-found: ignore
retention-days: 7

- name: Run tape backward compatibility smoke test
run: yarn test-tape-compat

# TODO: Re-enable coverage once all tests run in a single vitest invocation
# - name: Coveralls
# uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}

test-website:
runs-on: ubuntu-22.04
permissions:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dist/
node_modules/
coverage/
test/**/*-failed.png
test/**/__screenshots__/
.nyc_output/
.reify-cache/

Expand Down
6 changes: 4 additions & 2 deletions .ocularrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ const config = {
},

entry: {
test: 'test/node.ts',
'test-browser': 'index.html',
// Tests now use vitest (yarn test, yarn test-headless, yarn test-render)
// Only tape-compat smoke test still uses ocular-test for backward compatibility testing
'tape-compat': 'test/smoke/tape-compat.ts',
// TODO: Migrate bench and size to vitest (Phase 7)
bench: 'test/bench/index.js',
'bench-browser': 'test/bench/browser.html',
size: 'test/size/import-nothing.js'
Expand Down
24 changes: 24 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,30 @@ yarn bootstrap
yarn test
```

## Running Tests

deck.gl uses [Vitest](https://vitest.dev/) with browser mode for testing. Tests are organized into three projects:

| Command | Description | Use Case |
|---------|-------------|----------|
| `yarn test` | Full test suite (node + headless browser + render tests) | CI validation |
| `yarn test-fast` | Lint + node smoke tests only | Pre-commit hook (fast) |
| `yarn test-headless` | Browser unit tests in headless Chromium | Quick browser test validation |
| `yarn test-browser` | Browser tests in headed Chromium + render tests | Local debugging with visible browser |
| `yarn test-ci` | Full suite with coverage | CI pipeline |

### Test Projects

- **node**: Fast smoke tests (`*.node.spec.ts`) - ~15 tests, runs in Node.js
- **headless**: Full unit tests (~618 tests) - runs in headless Chromium via Playwright
- **browser**: Same as headless but with visible browser window - useful for debugging but resource-intensive

### Notes

- The `test-browser` command runs in headed mode which consumes more resources. If tests timeout or fail to collect, use `test-headless` instead.
- Pre-commit hooks run `test-fast` for quick validation. Full test suite runs in CI.
- Render and interaction tests use golden image comparison and require the Playwright browser to be installed (`npx playwright install chromium`).

See [additional instructions](#troubleshooting) for Windows, Linux and Apple M1.

Run the website:
Expand Down
9 changes: 0 additions & 9 deletions index.html

This file was deleted.

13 changes: 12 additions & 1 deletion modules/test-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./vitest": {
"types": "./dist/vitest.d.ts",
"import": "./dist/vitest.js",
"require": "./dist/vitest.cjs"
}
},
"files": [
Expand All @@ -39,7 +44,13 @@
"@deck.gl/core": "~9.2.0",
"@luma.gl/core": "~9.2.6",
"@luma.gl/engine": "~9.2.6",
"@probe.gl/test-utils": "^4.1.1"
"@probe.gl/test-utils": "^4.1.1",
"vitest": "^2.1.0"
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're stuck on vitest 2 until we upgrade from node 18.

},
"peerDependenciesMeta": {
"vitest": {
"optional": true
}
Copy link

Choose a reason for hiding this comment

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

probe.gl peer dependency not marked as optional per RFC

Medium Severity

The RFC explicitly specifies @probe.gl/test-utils should be an optional peer dependency (like vitest is), but the implementation marks only vitest as optional. Users importing from @deck.gl/test-utils/vitest don't need probe.gl at all, yet they'll get npm/yarn peer dependency warnings. Additionally, the RFC called for a lazy dynamic import() of @probe.gl/test-utils in the backward-compat path, but tape.ts uses a static import {makeSpy} from '@probe.gl/test-utils'. Since index.ts statically imports from ./tape, even users who only need testInitializeLayer (no spies) will trigger the probe.gl import and fail if it's not installed.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

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

@probe.gl/test-utils peer dependency not marked optional

Medium Severity

The new ./vitest subpath export doesn't depend on @probe.gl/test-utils, yet it remains a required (non-optional) peer dependency. Users who only want the vitest entry point are still forced to install @probe.gl/test-utils. The peerDependenciesMeta marks vitest as optional but omits @probe.gl/test-utils, contradicting the RFC which specifies it should be optional.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

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

Probe.gl peer dependency not marked as optional

Medium Severity

The peerDependenciesMeta only marks vitest as optional, but the RFC explicitly states that @probe.gl/test-utils should also be marked optional. Consumers who only use @deck.gl/test-utils/vitest don't need @probe.gl/test-utils at all, yet package managers will warn about it being missing since it's listed as a required peer dependency. Adding "@probe.gl/test-utils": { "optional": true } to peerDependenciesMeta matches the RFC's design and prevents unnecessary installation warnings.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

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

@probe.gl/test-utils peer dependency not marked optional

Medium Severity

@probe.gl/test-utils remains a required peer dependency, but the new @deck.gl/test-utils/vitest entry point (vitest.ts) never imports it. Only the tape.ts entry point (used via the default @deck.gl/test-utils import) needs @probe.gl/test-utils. Users who exclusively use @deck.gl/test-utils/vitest will receive unnecessary peer dependency warnings. The peerDependenciesMeta only marks vitest as optional, but @probe.gl/test-utils needs the same treatment.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

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

Peer dependency not marked optional per RFC design

Medium Severity

The peerDependenciesMeta only marks vitest as optional but does not mark @probe.gl/test-utils as optional. The RFC explicitly specifies @probe.gl/test-utils should be "optional": true in peerDependenciesMeta. Users who only use the @deck.gl/test-utils/vitest entry point don't need @probe.gl/test-utils at all, but will receive peer dependency warnings because it's listed as a required peer dependency.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

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

Probe.gl peer dependency not marked as optional

Medium Severity

@probe.gl/test-utils is a required peer dependency but the RFC specifies it as optional. Only vitest is in peerDependenciesMeta with optional: true. Users who only import from @deck.gl/test-utils/vitest (which never touches probe.gl) will get unnecessary peer dependency warnings from npm/yarn about missing @probe.gl/test-utils. Both @probe.gl/test-utils and vitest need to be optional since each entry point only requires one of them.

Fix in Cursor Fix in Web

},
"gitHead": "13ace64fc2cee08c133afc882fc307253489a4e4"
}
5 changes: 5 additions & 0 deletions modules/test-utils/src/generate-layer-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

// TODO: Refactor to use vitest's test.each() so each test case becomes a separate
// vitest test. This would allow vitest to show individual test case names in output
// instead of running all cases inside a single test() block. Currently test case
// titles are only visible via console.log() in onBeforeUpdate callbacks.

import {_count as count, Layer} from '@deck.gl/core';

import type {DefaultProps} from '@deck.gl/core';
Expand Down
42 changes: 42 additions & 0 deletions modules/test-utils/src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

// Type declarations for browser test driver functions injected by @probe.gl/test-utils

interface BrowserTestDriverDiffOptions {
goldenImage: string;
region?: {x: number; y: number; width: number; height: number};
saveOnFail?: boolean;
saveAs?: string;
threshold?: number;
createDiffImage?: boolean;
tolerance?: number;
includeAA?: boolean;
includeEmpty?: boolean;
platform?: string;
}

interface BrowserTestDriverDiffResult {
headless: boolean;
match: string | number;
matchPercentage: string;
success: boolean;
error: Error | string | null;
}

interface BrowserTestDriverInputEvent {
type: string;
[key: string]: any;
}

declare global {
interface Window {
browserTestDriver_emulateInput(event: BrowserTestDriverInputEvent): Promise<void>;
browserTestDriver_captureAndDiffScreen(
options: BrowserTestDriverDiffOptions
): Promise<BrowserTestDriverDiffResult>;
}
}

export {};
10 changes: 3 additions & 7 deletions modules/test-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ export {toLowPrecision} from './utils/precision';
export {gl, device} from './utils/setup-gl';

// Utilities for update tests (lifecycle tests)
export {
testLayer,
testLayerAsync,
testInitializeLayer,
testInitializeLayerAsync
} from './lifecycle-test';
// Uses ./tape which wraps ./lifecycle-test with @probe.gl/test-utils default
export {testLayer, testLayerAsync, testInitializeLayer, testInitializeLayerAsync} from './tape';
export {generateLayerTests} from './generate-layer-tests';

// Basic utility for rendering multiple scenes (could go into "deck.gl/core")
Expand All @@ -23,6 +19,6 @@ export {SnapshotTestRunner} from './snapshot-test-runner';
// A utility that emulates input events
export {InteractionTestRunner} from './interaction-test-runner';

export type {LayerTestCase} from './lifecycle-test';
export type {LayerTestCase} from './tape';
export type {SnapshotTestCase} from './snapshot-test-runner';
export type {InteractionTestCase} from './interaction-test-runner';
2 changes: 1 addition & 1 deletion modules/test-utils/src/interaction-test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class InteractionTestRunner extends TestRunner<InteractionTestCase, {}> {
});

for (const event of testCase.events) {
if (event.wait) {
if ('wait' in event) {
await sleep(event.wait);
} else {
await window.browserTestDriver_emulateInput(event);
Expand Down
Loading