# swap-testing-e2e-cloakbrowser ## Why `@playwright/test` ships a stock Chromium that is trivially fingerprinted as automation (`navigator.webdriver === true`, `HeadlessChrome` UA, missing `window.chrome`, GPU/canvas/audio leaks, CDP detection). E2E suites that exercise production-like flows against bot-aware infrastructure (Cloudflare Turnstile, reCAPTCHA v3, ShieldSquare, FingerprintJS, BrowserScan) either fail outright or skew metrics on the first request. [CloakBrowser](https://github.com/CloakHQ/cloakbrowser) (`cloakbrowser`, v0.3.28) is a real Chromium binary with 49 source-level C++ patches covering canvas, WebGL, audio, fonts, GPU, screen, WebRTC, network timing, automation signals, and CDP input behaviour. It is a drop-in replacement at the browser-launch layer: the returned object is a `playwright-core` `Browser` and works with every existing Playwright test, fixture, page-object, and helper without API changes. This proposal swaps every browser-launch call inside `@suaveplan/testing-e2e` to `cloakbrowser`, retains `@playwright/test` as the test runner (CloakBrowser does not provide one), and exposes the stealth-specific knobs (`humanize`, `proxy`, `geoip`, `launchPersistentContext`, extension support) as first-class API surface. ## What Changes - **ADDED:** `CLOAK_LAUNCH_FAILED`, `CLOAK_BINARY_MISSING`, `CLOAK_PROXY_INVALID` error codes + `CloakLaunchError` class + `classifyCloakError` helper that turns raw cloakbrowser errors into classified `TestingE2eError` instances with remediation hints. - **ADDED:** `@suaveplan/testing-e2e/cloakserve` subpath — `connectCloakServe(options, chromium?)` + `buildCloakServeUrl(options)` pair that wraps `chromium.connectOverCDP(...)` for the [cloakserve](https://github.com/CloakHQ/CloakBrowser#cdp-server-mode) CDP multiplexer. Strongly-typed query-parameter surface (`fingerprint`, `timezone`, `locale`, `platform`, GPU vendor / renderer, hardware concurrency, device memory, screen dimensions, `proxy`, `geoip`). Errors wrapped in `CloakLaunchError`. - **ADDED:** `@suaveplan/testing-e2e/presets` subpath — stealth presets matching the upstream README's "Recommended config for anti-bot sites" block. `STEALTH_DEFAULT_CLOAK`, `STEALTH_HEADED_CLOAK`, `stealthMax(proxy)`, `stealthMaxHeadless(proxy)`. - **ADDED:** `tests/no-disallowed.test.ts` rule against `waitForTimeout` / `wait_for_timeout`. Both forms emit CDP traffic that reCAPTCHA v3 / Enterprise behavioural scorers detect; the upstream README documents this explicitly. Test files excluded. - **ADDED:** `docker/` bundle — `Dockerfile.cloakserve` (extends `cloakhq/cloakbrowser`, adds the Kasada / Akamai font set, runs `cloakserve` on 9222), `Dockerfile.manager` (extends `cloakhq/cloakbrowser-manager`, exposes 8080 with a `cloakprofiles` named volume), `docker-compose.yml` binding both to `127.0.0.1` with the manager gated behind the `manager` compose profile, `.env.example` for pinned tags + `AUTH_TOKEN`, operator `README.md`. - **MODIFIED:** `extendedTest`'s `browser` fixture now launches via `cloakbrowser.launch()` instead of the stock Playwright chromium fixture. `freshPage` and any downstream fixture composition keep the same signature. The launcher is unit-test-injectable via the `launchBrowserWithCloak(opts, injectedLaunch?)` helper. - **MODIFIED:** `launchWithExtension` accepts an injectable `launchPersistentContext` function (default: cloakbrowser's). The legacy `chromium: BrowserType` parameter is removed. - **MODIFIED:** `packages/testing/testing-e2e/package.json` adds `cloakbrowser: ^0.3.28` as a direct dependency. (The dep is pinned in-package rather than added to `workspaces.catalogs.testing` to keep this change isolated from concurrent in-flight work that also touches the root catalog; promote to the testing catalog as a follow-up if other packages start consuming `cloakbrowser`.) - **MODIFIED:** Package description, README updated. **No public re-exports of cloakbrowser symbols** — per CLAUDE.md rule 4, consumers `import { launch } from "cloakbrowser"` directly when bypassing the fixture layer. ## Impact - **Affected specs:** `testing-e2e`. - **Affected code:** all six consumer packages currently importing from `@suaveplan/testing-e2e` continue to work unchanged — the browser launcher swap is transparent to existing tests because the returned `Browser` object is the same `playwright-core` `Browser` type. - **Binary footprint:** CI runners gain a ~200MB stealth Chromium download on first run (cached under `~/.cache/cloakbrowser/`). Acceptable: the alternative is `playwright install chromium` (~170MB) on every `@playwright/test` consumer. - **Out of scope:** Python flavour (`cloakbrowser` PyPI), `cloakserve` CDP multiplexer, `cloakbrowser-manager` Docker profile UI — none are consumed by the genesis monorepo today.