Skip to content

👷 Run BrowserStack unit tests with Vitest (webdriverio provider) - #5136

Draft
thomas-lebeau wants to merge 6 commits into
thomas.lebeau/vitest-wipfrom
thomas.lebeau/vitest-wdio-bs-spike
Draft

thomas-lebeau wants to merge 6 commits into
thomas.lebeau/vitest-wipfrom
thomas.lebeau/vitest-wdio-bs-spike

Conversation

@thomas-lebeau

@thomas-lebeau thomas-lebeau commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

Every previous Vitest attempt stalled on BrowserStack: Vitest's default Playwright provider can't pick exact browser versions or drive real Android devices, and Vitest's client needs Chrome 87+ / Safari 15.4+, while our unit matrix is Chrome 80, Edge 80, Firefox 78, Safari 14 and Android Chrome.

This PR moves unit-bs to Vitest using the webdriverio provider, which reaches that exact matrix on real BrowserStack devices. Stacked on #5135. The Karma BrowserStack config is still in the repo (unused) so reverting is a one-line change; it is deleted in a follow-up PR.

Changes

  • yarn test:unit:bs (CI unit-bs matrix) runs vitest run --config test/unit-vitest/vite.bs.config.ts.
  • test/unit-vitest/vite.bs.config.ts: webdriverio provider against hub.browserstack.com:
    • W3C Selenium (seleniumVersion: 4.0.0) on desktop browsers: BrowserStack otherwise serves Chrome 80 through Selenium 2.53, which rejects the window resize Vitest sends before each file. Viewport errors are non-fatal anyway.
    • WebDriver keepalive (+ idleTimeout: 300): Vitest talks to the page over its own WebSocket, so BrowserStack otherwise kills the session as idle.
    • Downlevel to ES2020: Vitest's browser client ships ||=/??=. A plugin transpiles dependency JS and routes Vitest's prebuilt /__vitest__/ assets through the Vite pipeline (@oxc-project/runtime for injected helpers).
    • Polyfills for the orchestrator and tester pages: Object.hasOwn, Array.prototype.at, … (from 👷 Migrate unit tests to Vitest #4874), a same-origin BroadcastChannel (Safari < 15.4) and AggregateError (Firefox < 79).
    • bs-local.com for Safari only (BrowserStack rewrites localhost there); other browsers keep localhost, a secure context needed by secure cookie tests.
    • Page error reporter to the terminal (Safari on BrowserStack exposes no console logs).
    • verbose reporter (the BrowserStack wrapper kills silent runs), per-browser JUnit file, no coverage, same exclusions as karma.bs.conf.js.
  • trackRuntimeError.spec: stop() resolved to window.stop(), which made Firefox 78 reload the test iframe; it now unsubscribes from the observable.
  • webdriverio 9 → 10: v9's bundled undici 6 fails every request on Node 26 (UND_ERR_INVALID_ARG).

Results

All five unit-bs jobs pass the full suite. Job durations (CI Visibility, minutes, single run):

Job Karma avg / p50 / p90 (other PRs, last 14 days) Vitest (this PR)
unit-bs Chrome 80 3.19 / 2.98 / 4.28 5.42
unit-bs Android Chrome 3.04 / 2.81 / 3.95 6.62
unit-bs Edge 80 3.10 / 2.87 / 4.03 4.45 (on retry, see below)
unit-bs Firefox 78 3.13 / 3.04 / 3.79 3.97
unit-bs Safari 14 5.25 / 5.33 / 6.51 3.67

Open issues

  • Reliability: Vitest doesn't reconnect a lost browser (Karma had browserDisconnectTolerance). We saw one BrowserStack tunnel drop and one Edge connect timeout. Planned: bs-wrapper.ts exits with a dedicated code on these infrastructure errors + GitLab retry: exit_codes on unit-bs.
  • Speed: Chrome 80 and Android are 2–3.5 min slower than Karma (single runs; to be confirmed and investigated, likely modules served one by one through the tunnel).

⚠️ Written with an AI agent (Claude Code).

Test instructions

Needs BS_USERNAME / BS_ACCESS_KEY (e.g. in .env):

BS_BROWSER=safari-desktop yarn test:unit:bs

BS_BROWSER is one of edge, firefox, safari-desktop, chrome-desktop, chrome-mobile.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum Salesforce N/A 188.06 KiB N/A N/A N/A
Rum 188.04 KiB 188.04 KiB 0 B 0.00% ✅
Rum-salesforce Profiler N/A 8.35 KiB N/A N/A N/A
Rum Profiler 8.35 KiB 8.35 KiB 0 B 0.00% ✅
Rum-salesforce Recorder N/A 32.04 KiB N/A N/A N/A
Rum Recorder 32.04 KiB 32.04 KiB 0 B 0.00% ✅
Logs 59.44 KiB 59.44 KiB 0 B 0.00% ✅
Rum Slim 145.83 KiB 145.83 KiB 0 B 0.00% ✅
Worker 22.96 KiB 22.96 KiB 0 B 0.00% ✅
Rum Shopify N/A 218.48 KiB N/A N/A N/A
Rum-shopify Profiler N/A 8.35 KiB N/A N/A N/A
Rum-shopify Recorder N/A 4.85 KiB N/A N/A N/A

@thomas-lebeau
thomas-lebeau added this pull request to stack #5137 October 13, 2026 15:42
@datadog-prod-us1-3

datadog-prod-us1-3 Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Tests

✅ All CI checks and tests passed.

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 78.16% (-0.04%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 9db56ed | Docs | View more details | Give us feedback!

@thomas-lebeau
thomas-lebeau force-pushed the thomas.lebeau/vitest-wdio-bs-spike branch 3 times, most recently from 8d63fc5 to 8ad2817 Compare October 14, 2026 11:22
@thomas-lebeau
thomas-lebeau force-pushed the thomas.lebeau/vitest-wdio-bs-spike branch from 8ad2817 to 80c77b4 Compare October 14, 2026 11:54
@thomas-lebeau thomas-lebeau changed the title ✅ [spike] Run Vitest unit tests on BrowserStack with the webdriverio provider 👷 Run BrowserStack unit tests with Vitest (webdriverio provider) Oct 14, 2026
Spike: check whether Vitest Browser Mode can cover our full BrowserStack
matrix (Chrome 80, Edge 80, Firefox 78, Safari 14, Android Chrome), which
the playwright provider can't.

- vite.bs.config.ts: webdriverio provider against hub.browserstack.com,
  with a WebDriver keepalive (Vitest uses its own WebSocket, so
  BrowserStack otherwise kills the session as idle)
- downlevel dependencies and Vitest's static client assets to ES2020
- polyfills (Object.hasOwn, BroadcastChannel, ...) for orchestrator and
  tester pages
- serve from bs-local.com so Safari can reach the server
- report page errors to the terminal (Safari exposes no console logs)
- webdriverio 9 -> 10 (v9's bundled undici 6 breaks on Node 26)

browser-core results: all 72 files pass on Chrome 80, Edge 80, Safari 14
and Android Chrome; Firefox 78 passes 71/72 (trackRuntimeError.spec.ts
triggers an iframe reload when run as a whole).
Point `yarn test:unit:bs` (CI `unit-bs` matrix) at the webdriverio
BrowserStack config, to see where the approach stands on the full suite.

- verbose reporter, so the BrowserStack wrapper doesn't kill silent runs,
  and a per-browser junit file in test-report/unit-bs
- no coverage on BrowserStack
- same exclusions as karma.bs.conf.js (developer extension everywhere,
  Angular on Chrome/Edge 80 and Firefox 78)

Files stay isolated (one iframe per file): running without isolation
currently fails 151 tests (state leaking across files, shim gaps).
BrowserStack served Chrome 80 through Selenium 2.53 (JSON Wire protocol),
which rejects the `POST /window/rect` Vitest sends before each test file.
Also make a failed viewport resize non-fatal.
- trackRuntimeError.spec: `stop()` resolved to `window.stop()`, which made
  Firefox 78 reload the Vitest test iframe. Unsubscribe from the observable
  instead.
- polyfill AggregateError (Firefox < 79), used by Vitest to report errors
- only serve from bs-local.com on Safari: other browsers need `localhost`
  (a secure context) for `secure` cookies (cookieAccess.spec on Android)
@thomas-lebeau
thomas-lebeau force-pushed the thomas.lebeau/vitest-wdio-bs-spike branch from 80c77b4 to 840afce Compare October 15, 2026 14:37

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant