👷 Migrate unit tests from Karma/Jasmine to Vitest#4196
👷 Migrate unit tests from Karma/Jasmine to Vitest#4196
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
Bundles Sizes Evolution
🚀 CPU Performance
🧠 Memory Performance
|
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.
| browser: { | ||
| enabled: true, | ||
| provider: playwright(), | ||
| // Use bs-local.com instead of localhost so Safari on BrowserStack can access cookies. |
There was a problem hiding this comment.
Safari on BrowserStack replaces localhost with bs-local.com, which breaks cookie access in vitest's iframe. Same issue we already have with ServiceWorker tests in E2E.
| }, DOM_MUTATION_OBSERVABLE_DURATION) | ||
| } | ||
| return () => | ||
| new Promise<void>((resolve) => { |
There was a problem hiding this comment.
Vitest doesn't support done() callbacks. Converted to new Promise<void>.
| import { SESSION_STORE_KEY } from './sessionStoreStrategy' | ||
|
|
||
| // Safari on BrowserStack cannot access cookies because vitest runs tests in an iframe | ||
| // and BrowserStack replaces localhost with bs-local.com, triggering Safari's ITP restrictions. |
There was a problem hiding this comment.
Safari on BrowserStack still can't access cookies in the vitest iframe even with bs-local.com. Skipped on Safari only, runs fine on the other 4 browsers.
| @@ -1,3 +1,4 @@ | |||
| import { vi, beforeEach, describe, expect, it } from 'vitest' | |||
There was a problem hiding this comment.
Typical spec migration. jasmine.createSpy() → vi.fn(), spyOn → vi.spyOn, etc. All 257 spec files follow this same pattern.
trackRuntimeError: Add preventDefault() listeners to suppress Vitest's unhandled error reporting. Tests intentionally throw errors that are handled by the SDK's own onerror instrumentation, but Vitest also catches them via addEventListener. preventDefault() marks them as handled without blocking window.onerror. taskQueue: Snapshot requestSpy.mock.calls.length before iterating in callAllActiveCallbacks. Vitest's mock.calls array grows live (unlike Jasmine's calls.count() snapshot), so callbacks that trigger scheduleNextRun caused an infinite loop.
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