# testing-e2e-error ## Purpose `TestingE2eError` is the structured error class thrown by every helper, fixture, and page object in `@suaveplan/testing-e2e`. Its shape mirrors `SuaveplanError` — `{ code, cause?, context? }` — but it does NOT extend it, because testing-infrastructure packages must stay free of any `@suaveplan/*` workspace dependency (rule #8 in `CLAUDE.md`). ## Features - `code` narrowed to `TestingE2eCode` (the literal union of `TESTING_E2E.*` strings) - Named subclasses (`ConfigError`, `NavigationError`, `WaitTimeoutError`, `FixtureError`, `AbortedError`) for targeted `instanceof` checks - Preserves `cause` via ES2022 `Error.cause` - Optional `context` for structured diagnostic fields ## Usage: Basic Example ```ts import { WaitTimeoutError, TESTING_E2E_ERROR_CODES } from "@suaveplan/testing-e2e"; throw new WaitTimeoutError( TESTING_E2E_ERROR_CODES.WAIT_TIMEOUT, "waitForNetworkIdle: network did not settle within 30000ms" ); ``` ## Usage: Advanced Example ```ts import { WaitTimeoutError, NavigationError, TestingE2eError, TESTING_E2E_ERROR_CODES, } from "@suaveplan/testing-e2e"; async function safeNavigate(url: string, page: Page): Promise { try { await page.goto(url, { timeout: 10_000 }); } catch (cause) { throw new NavigationError( TESTING_E2E_ERROR_CODES.NAVIGATION_FAILED, `navigation to ${url} failed`, { cause, context: { url } } ); } } try { await safeNavigate("https://example.com", page); } catch (err) { if (err instanceof TestingE2eError) { console.error(err.code, err.context, err.cause); } throw err; } ``` ## API Reference ### `class TestingE2eError extends Error` - `readonly code: TestingE2eCode` - `readonly context?: Readonly>` - `cause?: unknown` (from `Error.cause`) ### Subclasses - `ConfigError` — config-factory rejections - `NavigationError` — `page.goto` / routing failures - `WaitTimeoutError` — helper wait timeouts - `FixtureError` — fixture setup/teardown failures - `AbortedError` — signal-driven cancellations - `CloakLaunchError` — `cloakbrowser` launcher failures (binary missing, proxy invalid, generic launch failure) ### Cloak helpers - `classifyCloakError(err) → TestingE2eErrorCode` — pure synchronous classifier mapping raw errors thrown by `cloakbrowser` to one of the three `TESTING_E2E.CLOAK.*` codes. Returns `LAUNCH_FAILED` for any error the classifier does not specifically recognise. - `wrapCloakError(err, context?) → CloakLaunchError` — convenience wrapper used by every cloakbrowser-backed fixture. Classifies the raw error, appends a remediation hint where applicable (`npx cloakbrowser install` for binary issues, proxy verification for proxy errors), and preserves the original error via `Error.cause`. ## Implementation Notes The subclasses exist so callers can write `catch (err instanceof WaitTimeoutError)` in hot paths without a `switch` on `code`. They all share the same structural shape — the subclass is purely a type-narrowing aid, not a behavioural difference. The base class deliberately does not extend `SuaveplanError` — if the project ever relaxes the testing-infra dep rule, swapping the base is a one-line change and no caller breaks. ### Subclass Index `TestingE2eError` is the base class. Subclasses cover `ClipboardMockError`, `GeolocationMockError`, `PageObjectTimeoutError`, and `DialogDismissalError`. Every subclass sets its own code from `TESTING_E2E_CODES`, overrides `name`, and inherits wire-serialisation + OTel span-event behaviour from `SuaveplanError` so Playwright trace viewers see a consistent error shape.