89 lines
4.8 KiB
Markdown
89 lines
4.8 KiB
Markdown
# 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.
|