feat(testmu): hosted Chrome and Edge for the web engine with testmuBrowsers()
Merged
AM
6d ago+630+630+012345678901234567890123456789-18-18-01234567890123456789
What and why
testmuBrowsers()from@e2e-dev/testmu/web: aBrowserProviderthat runs web targets in TestMu AI (formerly LambdaTest) hosted Chrome and Edge over CDP (wss://cdp.lambdatest.com/puppeteer). Each worker slot gets one session.- One package per service: it ships in
@e2e-dev/testmunext totestmu().@e2e-dev/mobileand@e2e-dev/webare optional peers. The root entry never imports@e2e-dev/web, and./webnever imports@e2e-dev/mobileor agent-device, so a project with one engine loads and type-checks the entry it uses, withskipLibCheck: falsetoo.packages/testmu/tests/unit/entries.test.tspins it. - Session names (
e2e-<run id>-<target>-<slot>) and thee2eproject default come frompackages/testmu/src/dashboard.ts, shared withtestmu(), so a run's device and browser sessions sit in one build and can't drift. - Options are
browserName(Chromeby default, orMicrosoftEdge) andcapabilities.browserVersionis sent next tobrowserName; every other key goes intoLT:Options.user,accessKeyandnameare reserved. A nestedLT:Options, abrowserNameinsidecapabilities, a non-arraybrowserOptions, or a value JSON can't carry fails at config load. - Defaults:
platform: 'Windows 11'(the hub refuses a session without one),project: 'e2e',build: <run id>,idleTimeout: 600, and for Edge--user-data-dir=remote-debug-profile-edgeinbrowserOptions(without it the Edge CDP connect never completes). A user-set value wins. LT_USERNAMEandLT_ACCESS_KEYgo only into the CDP URL. Without them the lease fails before any session starts.- Docs:
integrations/testmu-browsersnext tointegrations/testmu, plus the browser, integrations, environment, security and skill references. - First written by @SahilSawLT in LambdaTest/e2e#4, and split out of #772 on review.
import type { E2EConfig } from 'e2e';
import { web } from '@e2e-dev/web';
import { testmuBrowsers } from '@e2e-dev/testmu/web';
export default {
targets: [
{
name: 'testmu-web',
engine: web({ browser: testmuBrowsers({ browserName: 'MicrosoftEdge', capabilities: { platform: 'Windows 10' } }), viewport: null }),
app: { url: 'https://staging.example.com' },
},
],
} satisfies E2EConfig;
Verified
Ran it locally: yes
Live on TestMu AI production on 2026-10-20, with run-1200-live.sh, which packs the branch into a clean project:
| Scenario | Result |
|---|---|
| Chrome, worker scope, defaults only | ✅ pass, 14.4 s including session start |
| Edge, worker scope, defaults only | ✅ pass, 13.2 s including session start |
| Bad access key | ✅ fails at connect: 401 Unauthorized, either Username or AccessKey is invalid |
browserVersion: '0.0' | ✅ fails at connect: 400 Could not find a valid browserVersionData |
After every scenario the script greps the log, report.json, summary.md, junit.xml, the traces and trace.md for the access key, raw, URL-encoded and base64. No hits.
After the move into @e2e-dev/testmu, packed e2e, @e2e-dev/web, @e2e-dev/mobile and @e2e-dev/testmu into clean projects under /tmp and installed them with npm:
| Project | Installed @e2e-dev/* | tsc, skipLibCheck: false |
|---|---|---|
web only: testmuBrowsers from @e2e-dev/testmu/web | testmu, web | ✅ |
mobile only: testmu from @e2e-dev/testmu | mobile, testmu | ✅ |
e2e run in the web-only project with a fake key reaches the hub through the packed ./web entry:
FAIL |testmu-web| tests/smoke.e2e.ts > opens example.com
ENGINE_FAILURE: browser connect failed: browserType.connectOverCDP: WebSocket error: wss://cdp.lambdatest.com/puppeteer 401 Unauthorized
{"status":401,"value":{"message":"...: Unauthorized, either Username or AccessKey is invalid"}}
The fake key and username appear nowhere under .e2e/ (raw, URL-encoded, base64). With no credentials:
ERROR infrastructure error ENGINE_FAILURE (launch)
browser provider "testmu-browsers" could not lease a browser: LT_USERNAME and LT_ACCESS_KEY are not set; set LT_USERNAME and LT_ACCESS_KEY to your TestMu AI username and access key in the environment `e2e run` starts in while preparing engine web for target "testmu-web"
Checklist
- Changeset added (
pnpm changeset) for any change to a published package, or the change is testbed, docs, or CI only. - Breaking change: none.
@e2e-dev/mobilebecomes an optional peer of@e2e-dev/testmu. - Docs updated in the same PR: the
docs/**/*.mdxpage for the behavior, andskills/e2e/if the skill describes it. - Contract change: n/a.
- Engine contract change (
e2e/engine): n/a.
🤖 Generated with Claude Code