👷 Migrate unit tests from Karma/Jasmine to Vitest - #4196
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
Bundles Sizes Evolution
|
319576e to
02e30e1
Compare
051c55a to
23d1a16
Compare
| }, | ||
|
|
||
| test: { | ||
| browser: { |
There was a problem hiding this comment.
Browser mode with Playwright. Locally it runs headless Chromium. On BrowserStack, Playwright connects to remote browsers via WebSocket (wss://cdp.browserstack.com/playwright), so the old browser versions (Chrome 63, Edge 80, etc.) are real browsers hosted by BrowserStack, not local Playwright binaries. The aliases mirror tsconfig.base.json so vitest resolves packages the same way TypeScript does.
| // AND so performance.timing.navigationStart remains accessible. | ||
| // When performance IS faked, @sinonjs/fake-timers replaces the object and our | ||
| // override silently fails (the fake performance.now() starts at 0). | ||
| vi.useFakeTimers({ |
There was a problem hiding this comment.
performance is excluded from toFake. If we fake it, performance.now() returns fake time but the browser's internal performance observer still uses real time. Breaks every perf-related test.
| mostRecent(): { args: Parameters<F>; returnValue: ReturnType<F> } | ||
| } | ||
|
|
||
| export function collectAsyncCalls<F extends (...args: any[]) => any>( |
There was a problem hiding this comment.
Vitest equivalent of the old Jasmine calls.all() pattern. Wraps a vi.fn() and resolves a promise once the expected number of calls is reached.
| /// <reference types="vite/client" /> | ||
| // Load all JSON schema files from the rum-events-format submodule. | ||
| // Uses Vite's import.meta.glob (replaces webpack's require.context). | ||
| const schemaModules = import.meta.glob('../../../rum-events-format/schemas/**/*.json', { eager: true }) |
There was a problem hiding this comment.
require.context → import.meta.glob. Same result, Vite API instead of webpack.
…convert new debugger specs to Vitest - Add @datadog/js-core/time alias to vitest.config.ts - Move time-related imports from @datadog/browser-core to @datadog/js-core/time across ~70 files - Convert display.spec.ts, probes.spec.ts (new from main) to Vitest - Re-convert deliveryApi.spec.ts and api.spec.ts from main (complete rewrite) - Fix allJsonSchemas.js require.context (removed .js/.d.ts, kept .ts with import.meta.glob) - Fix getTimeStamp → toTimeStamp rename - Fix getNavigationStart → getTimeOrigin rename - Remove supportPerformanceTimingEvent guard (removed on main)
…vite 7 compatibility Vitest brings vite 7.x which conflicts with @vitejs/plugin-react 6.x (requires vite 8). Pin to 5.2.0 via Yarn resolution for wxt compatibility.
Aliases were pointing to old directory names (packages/core/, packages/rum-core/, etc.) instead of the renamed directories (packages/browser-core/, packages/browser-rum-core/, etc.). Also adds the missing @datadog/js-core/time alias. The old paths worked by accident via yarn workspace symlink fallback.
# Conflicts: # packages/browser-rum-core/src/browser/locationChangeObservable.spec.ts # yarn.lock
Four spec files had Jasmine patterns after the merge with main: - addEventListener.spec.ts: jasmine.createSpy().and.throwError - cookieAccess.spec.ts: jasmine.createSpy().and.throwError - reportObservable.spec.ts: jasmine.Spy cast + .and.throwError - eventBridge.spec.ts: toBeTrue/toBeFalse/spyOn (new wildcard tests)
Main added instrumentConstructor utility (#4714) with Jasmine tests. Converted all patterns: jasmine.createSpy → vi.fn, jasmine.any → expect.any, .calls.mostRecent().args → .mock.calls, toBeTrue/toBeFalse → toBe(true/false), toHaveBeenCalledOnceWith → toHaveBeenCalledOnce + toHaveBeenCalledWith.
Vitest supports ctx.skip(condition, reason) to explain why a test is skipped. Added descriptive reasons to all 34 bare ctx.skip() calls across the test suite.
# Conflicts: # packages/browser-core/src/domain/contexts/accountContext.spec.ts # packages/browser-core/src/domain/contexts/tabContext.spec.ts # packages/browser-core/src/tools/abstractHooks.spec.ts # packages/browser-logs/src/domain/assembly.spec.ts # packages/browser-rum-core/src/domain/action/actionCollection.spec.ts # packages/browser-rum-core/src/domain/contexts/ciVisibilityContext.spec.ts # packages/browser-rum-core/src/domain/contexts/displayContext.spec.ts # packages/browser-rum-core/src/domain/contexts/pageStateHistory.spec.ts # packages/browser-rum-core/src/domain/contexts/sessionContext.spec.ts # packages/browser-rum-core/src/domain/contexts/sourceCodeContext.spec.ts # packages/browser-rum-core/src/domain/view/viewCollection.spec.ts # packages/browser-rum/src/boot/profilerApi.spec.ts
# Conflicts: # developer-extension/src/panel/flushEvents.spec.ts # package.json # packages/browser-core/src/browser/addEventListener.spec.ts # packages/browser-core/src/browser/cookieAccess.spec.ts # packages/browser-core/src/browser/pageMayExitObservable.spec.ts # packages/browser-core/src/browser/xhrObservable.spec.ts # packages/browser-core/src/domain/configuration/configuration.spec.ts # packages/browser-core/src/domain/context/storeContextManager.spec.ts # packages/browser-core/src/domain/report/reportObservable.spec.ts # packages/browser-debugger/src/domain/probes.spec.ts # packages/browser-rum-core/src/browser/locationChangeObservable.spec.ts # packages/browser-rum-core/src/browser/performanceObservable.spec.ts # packages/browser-rum-core/src/browser/viewportObservable.spec.ts # packages/browser-rum-core/src/domain/contexts/ciVisibilityContext.spec.ts # packages/browser-rum-core/src/domain/view/bfCacheSupport.spec.ts # packages/browser-rum-core/src/domain/view/viewMetrics/trackFirstContentfulPaint.spec.ts # packages/browser-rum/src/domain/deflate/deflateEncoder.spec.ts # packages/browser-rum/src/domain/record/trackers/trackFocus.spec.ts
CI has a newer eslint-plugin-unicorn version that supports this option. Local version didn't, causing the initial removal.
…Hook API changes - package.json: re-added vitest deps/scripts/resolutions on top of main's changes - allJsonSchemas.ts: updated glob path from submodule to node_modules/@datadog/rum-events-format - profiler.spec.ts: took main's removal of findTrackedSessionSpy, converted toBeTrue - tsconfig.default.json: removed jasmine types, added vitest.bs.config.ts exclusion - vitest configs: updated js-core/time alias to src/entries/time
# Conflicts: # package.json # packages/browser-rum-core/test/allJsonSchemas.js # packages/browser-rum/src/domain/profiling/profiler.spec.ts # tsconfig.default.json # yarn.lock
- Add toHaveLength() guards alongside expect.arrayContaining() where jasmine.arrayWithExactContents was converted (trackClickActions, configuration specs) - Convert bare return to ctx.skip() in serializeNode.stylesheet.spec.ts
- bs-wrapper: anchor failure regex to Vitest summary format (`/\d+ failed |/`) to avoid false positives from test console output like '3 failed retries' - registerCleanupTask: await async cleanup tasks instead of fire-and-forget - allJsonSchemas: throw if no schemas loaded (catches silent glob path breakage) - Remove dead browserstack.keepalive.ts (never wired into setupFiles) - Fix TaskContext → TestContext type import in stylesheet spec
- reportObservable: double-registration would fire spy twice silently - deliveryApi: double-logging of probe failures would go undetected - deflateEncoder: test named 'do not notify twice' now asserts count
Matches vitest.config.ts — prevents CJS modules that check `global` from silently breaking on BrowserStack only.
Resolves conflicts from js-core/assembly, js-core/util, js-core/monitor entry points and profiler transport extraction. Converts new spec files from Jasmine to Vitest API. Adds missing vitest aliases for new js-core subpath imports.
Resolves conflicts from createBatch API refactor (reportError string signature, forceFlush), prototype pollution guards in mergeInto, debugger init version tests, and dep bumps. Converts new Jasmine patterns to Vitest API in auto-merged files.
Resolves conflicts from endpointBuilder/intakeSites move to @datadog/js-core/transport. Adds js-core/transport alias to both vitest configs. Converts import paths in 8 spec files + test helper.
aa625fe to
4e06cf3
Compare
bs-wrapper.ts: ANSI escape codes from FORCE_COLOR broke failure detection — the regex /\d+ failed \|/ didn't match colored output like '9 failed\x1b[39m |'. Strip ANSI before matching. cookieAccess.spec.ts: CookieStore API tests crashed with TypeError when globalObject.cookieStore was undefined (Jasmine's pending() inside setup() skipped the enclosing it(), but Vitest doesn't). Added beforeEach ctx.skip for the CookieStore describe block.
Motivation
Karma is deprecated. This migrates the full unit test suite to Vitest 4.x with browser mode (Playwright).
Changes
Most of the diff is mechanical spec file replacements (
jasmine.createSpy()→vi.fn(), etc.). The interesting parts:mockClockhad to be rewritten because Vitest'svi.useFakeTimersfakesperformanceby default, which breaks every perf-related test. ThetoFakelist now explicitly excludes it.allJsonSchemaswas using webpack'srequire.contextto load schema files. Replaced with Vite'simport.meta.glob.BrowserStack needed
bs-local.comas server host because Safari replaces localhost with its own domain, breaking cookie access in vitest's iframe. Same issue we already have with ServiceWorker tests in E2E. Cookie tests are still skipped on Safari because this alone doesn't fully fix it.The
unit-bsCI job needs Playwright installed with system deps (--with-deps) and 4 CPUs to handle 5 concurrent remote browsers without timing out.vite@8.0.8is pinned in the developer extension because@vitejs/plugin-reactcan't resolvevite/internalin newer patch versions.3784 unit tests pass, 18628 BrowserStack tests across 5 browsers.
Test instructions
Checklist