@tracelane/playwright 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOTICE ADDED
@@ -0,0 +1,19 @@
1
+ rrweb-stack
2
+ Copyright 2026 Cubenest
3
+
4
+ This product includes software developed by:
5
+ - PostHog (https://posthog.com) — vendored rrweb fork, bundled (via esbuild) into
6
+ the in-page recorder injected by this Reporter / fixture:
7
+ @posthog/rrweb 0.0.34 (MIT License)
8
+ @posthog/rrweb-types 0.0.24 (MIT License)
9
+ Forked from upstream rrweb-io/rrweb 2.0.0-alpha.17. Re-exported through
10
+ @cubenest/rrweb-core.
11
+ - rrweb contributors (https://github.com/rrweb-io/rrweb) — console-record plugin:
12
+ @rrweb/rrweb-plugin-console-record 2.0.0-alpha.20 (MIT License) — bundled into
13
+ the in-page recorder.
14
+
15
+ The rrweb player + report assets are inlined by @tracelane/report; see that
16
+ package's NOTICE.
17
+
18
+ This product is licensed under the Apache License, Version 2.0.
19
+ See the LICENSE file for details.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ <img src="https://raw.githubusercontent.com/Cubenest/rrweb-stack/main/assets/brand/sub-tracelane.svg" height="40" alt="tracelane">
2
+
3
+ # @tracelane/playwright
4
+
5
+ > The recorder for your Playwright tests. A self-contained HTML report on every failure — replay the run with rrweb, inspect the console + failed-network panels, attach to any bug tracker. No SaaS, no dashboard, no signup, no cloud.
6
+
7
+ [![npm](https://img.shields.io/npm/v/@tracelane/playwright.svg)](https://www.npmjs.com/package/@tracelane/playwright)
8
+ [![downloads](https://img.shields.io/npm/dw/@tracelane/playwright.svg)](https://www.npmjs.com/package/@tracelane/playwright)
9
+ [![license](https://img.shields.io/npm/l/@tracelane/playwright.svg)](https://github.com/Cubenest/rrweb-stack/blob/main/LICENSE)
10
+ [![CI](https://github.com/Cubenest/rrweb-stack/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Cubenest/rrweb-stack/actions/workflows/ci.yml)
11
+
12
+ Docs: <https://tracelane.cubenest.in>
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ npm install --save-dev @tracelane/playwright
18
+ ```
19
+
20
+ `@playwright/test` (>= 1.40) is a peer dependency — you already have it.
21
+
22
+ ## Wire it (two edits)
23
+
24
+ **1. Register the reporter** in `playwright.config.ts`:
25
+
26
+ ```ts
27
+ import { defineConfig } from '@playwright/test';
28
+
29
+ export default defineConfig({
30
+ reporter: [
31
+ ['list'],
32
+ ['@tracelane/playwright', { mode: 'failed', outDir: './tracelane-reports' }],
33
+ ],
34
+ });
35
+ ```
36
+
37
+ **2. Use tracelane's `test`/`expect`** in your specs (a drop-in for `@playwright/test`):
38
+
39
+ ```ts
40
+ import { test, expect } from '@tracelane/playwright/fixture';
41
+
42
+ test('checkout', async ({ page }) => {
43
+ await page.goto('/checkout');
44
+ await expect(page.getByRole('heading')).toHaveText('Order complete');
45
+ });
46
+ ```
47
+
48
+ That's it. The fixture is `auto` — every test in files that import this `test` is recorded; nothing else to wire per-test.
49
+
50
+ Run your suite. On a failing test you get a single `.html` file at `./tracelane-reports/<spec>--<title>--<project>-<ts>.html` — open it in any browser, fully offline. Replay the run with [rrweb-player](https://www.rrweb.io), inspect the console + failed-network panels, attach to your bug tracker, archive it forever.
51
+
52
+ ## How it works
53
+
54
+ - **The fixture** owns the recording. It is the only place with a live `page` + `testInfo`, so it injects the rrweb bundle (via `context.addInitScript`, so fresh pages and post-navigation documents are covered), starts the recorder before your test body, and — after it — builds + writes the report. It reuses `@tracelane/core`'s recorder and `@tracelane/report`'s HTML builder.
55
+ - **The reporter** owns config + the end-of-run summary. By design it never touches `page`.
56
+ - **Failed-network capture** uses CDP on Chromium (4xx/5xx responses and no-response failures are surfaced into the report's network panel). On Firefox/WebKit it degrades silently to rrweb + console.
57
+ - **Parallel-safe**: report filenames are namespaced by the Playwright **project name** and carry a millisecond timestamp. Different projects are isolated by name; parallel workers *within one project* share the project-name segment and rely on the timestamp (plus spec + title) to stay distinct.
58
+ - **Coexists** with Playwright's own `trace` — keep `trace: 'on-first-retry'` if you like; tracelane writes a separate, self-contained artifact.
59
+
60
+ ## Options
61
+
62
+ | Option | Default | Notes |
63
+ | --- | --- | --- |
64
+ | `mode` | `'failed'` | `'failed'` writes a report only on failure; `'all'` writes one for every test. Overridable with `TRACELANE_MODE`. |
65
+ | `outDir` | `'./tracelane-reports'` | Where reports are written. Overridable with `TRACELANE_OUT_DIR`. |
66
+ | `captureNetwork` | `true` | CDP failed-network capture (Chromium-only). |
67
+
68
+ > The reporter and the fixture both resolve options independently; the env vars (`TRACELANE_MODE`, `TRACELANE_OUT_DIR`) are the reliable way to keep them in lockstep across the two when you need a non-default `outDir`.
69
+
70
+ ## What this is NOT
71
+
72
+ - Not a SaaS. There is no upload, no signup, no dashboard, no telemetry. The artifact is a single HTML file on your filesystem.
73
+ - Not a replacement for Playwright's trace viewer — it's a complementary, self-contained replay you can hand to anyone with a browser, no `npx playwright show-trace` required.
74
+
75
+ ## License
76
+
77
+ Apache-2.0. See [`NOTICE`](./NOTICE) for bundled third-party software (the rrweb fork + console plugin).
@@ -0,0 +1,21 @@
1
+ import { expect } from '@playwright/test';
2
+ import type { Page, TestInfo } from '@playwright/test';
3
+ /** Loads the rrweb bundle; injectable so unit tests can pass a stub. */
4
+ export type BundleLoader = () => string;
5
+ /**
6
+ * The fixture implementation, factored out so it is unit-testable without the
7
+ * Playwright runner. `bundleLoader` defaults to reading the package's built
8
+ * dist/rrweb-bundle.js; tests pass a stub to avoid the on-disk dependency.
9
+ */
10
+ export declare function tracelaneFixture({ page }: {
11
+ page: Page;
12
+ }, use: () => Promise<void>, testInfo: TestInfo, bundleLoader?: BundleLoader): Promise<void>;
13
+ /**
14
+ * A drop-in replacement for `@playwright/test`'s `test`, with an `auto` tracelane
15
+ * fixture that records every test and writes a report on failure.
16
+ */
17
+ export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
18
+ tracelane: void;
19
+ }, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
20
+ export { expect };
21
+ //# sourceMappingURL=fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAWA,OAAO,EAAgB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKvD,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC;AAIxC;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,EACxB,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACxB,QAAQ,EAAE,QAAQ,EAClB,YAAY,GAAE,YAAkC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;GAGG;AAEH,eAAO,MAAM,IAAI;eAA4B,IAAI;wGAO/C,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,50 @@
1
+ // The auto-fixture (P1 PRD §B.2). Importing `{ test }` from this module and
2
+ // using it in place of `@playwright/test`'s `test` opts every test into the
3
+ // recorder lifecycle automatically — no per-test wiring. The fixture is `auto`
4
+ // (runs even when not explicitly requested) and `box`ed (hidden from the
5
+ // Playwright trace/reporter UI so it doesn't clutter the run).
6
+ //
7
+ // The fixture straddles `use()`: it starts capture BEFORE the test body runs,
8
+ // yields with `use()`, then finalizes + writes the report AFTER. This is the
9
+ // only place with a live `page` + `testInfo`, which is why the report build
10
+ // lives here (the Reporter, Task 11, owns only config + summary).
11
+ import { test as base, expect } from '@playwright/test';
12
+ import { loadRrwebBundle } from '@tracelane/core';
13
+ import { resolveOptions } from './options.js';
14
+ import { runFinalize, runStart } from './playwright-session.js';
15
+ const defaultBundleLoader = () => loadRrwebBundle(import.meta.url);
16
+ /**
17
+ * The fixture implementation, factored out so it is unit-testable without the
18
+ * Playwright runner. `bundleLoader` defaults to reading the package's built
19
+ * dist/rrweb-bundle.js; tests pass a stub to avoid the on-disk dependency.
20
+ */
21
+ export async function tracelaneFixture({ page }, use, testInfo, bundleLoader = defaultBundleLoader) {
22
+ const options = resolveOptions({});
23
+ const rrwebBundle = bundleLoader();
24
+ let session;
25
+ try {
26
+ session = await runStart({ page, options, rrwebBundle });
27
+ // Run the test body.
28
+ await use();
29
+ }
30
+ finally {
31
+ if (session) {
32
+ await runFinalize(session, { page, testInfo, options, rrwebBundle });
33
+ }
34
+ }
35
+ }
36
+ /**
37
+ * A drop-in replacement for `@playwright/test`'s `test`, with an `auto` tracelane
38
+ * fixture that records every test and writes a report on failure.
39
+ */
40
+ // biome-ignore lint/suspicious/noConfusingVoidType: a `void` fixture value is Playwright's idiom for an auto-fixture that yields nothing via use()
41
+ export const test = base.extend({
42
+ tracelane: [
43
+ async ({ page }, use, testInfo) => {
44
+ await tracelaneFixture({ page }, use, testInfo);
45
+ },
46
+ { auto: true, scope: 'test', box: true },
47
+ ],
48
+ });
49
+ export { expect };
50
+ //# sourceMappingURL=fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,yEAAyE;AACzE,+DAA+D;AAC/D,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,kEAAkE;AAElE,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAuB,WAAW,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAKrF,MAAM,mBAAmB,GAAiB,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEjF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAE,IAAI,EAAkB,EACxB,GAAwB,EACxB,QAAkB,EAClB,eAA6B,mBAAmB;IAEhD,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,YAAY,EAAE,CAAC;IACnC,IAAI,OAAmC,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACzD,qBAAqB;QACrB,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,WAAW,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,mJAAmJ;AACnJ,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAsB;IACnD,SAAS,EAAE;QACT,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE;YAChC,MAAM,gBAAgB,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClD,CAAC;QACD,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE;KACzC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { TraceLaneReporter, default } from './reporter.js';
2
+ export { test, expect, tracelaneFixture } from './fixture.js';
3
+ export type { BundleLoader } from './fixture.js';
4
+ export { createPlaywrightExecutor } from './playwright-executor.js';
5
+ export { DEFAULT_OUT_DIR, resolveOptions } from './options.js';
6
+ export type { ResolvedOptions, TraceLaneOptions } from './options.js';
7
+ export { isPassed, mapStatus } from './result-status.js';
8
+ export { runFinalize, runStart, runTracelaneSession } from './playwright-session.js';
9
+ export type { FinalizeInput, StartInput, StartedSession } from './playwright-session.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACrF,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ // Public API surface for @tracelane/playwright.
2
+ //
3
+ // Two entry points cover the common usage:
4
+ // - the Reporter (default export here + the ./reporter subpath) goes in
5
+ // playwright.config.ts: `reporter: [['@tracelane/playwright', { mode }]]`;
6
+ // - the fixture (./fixture subpath, re-exported here) replaces
7
+ // `@playwright/test`'s test: `import { test, expect } from '@tracelane/playwright'`.
8
+ // The Reporter (config + summary). Default export so the string form
9
+ // `['@tracelane/playwright', opts]` resolves it.
10
+ export { TraceLaneReporter, default } from './reporter.js';
11
+ // The auto-fixture (records every test, writes a report on failure).
12
+ export { test, expect, tracelaneFixture } from './fixture.js';
13
+ // Building blocks (useful for custom adapters / advanced wiring).
14
+ export { createPlaywrightExecutor } from './playwright-executor.js';
15
+ export { DEFAULT_OUT_DIR, resolveOptions } from './options.js';
16
+ export { isPassed, mapStatus } from './result-status.js';
17
+ export { runFinalize, runStart, runTracelaneSession } from './playwright-session.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,2CAA2C;AAC3C,0EAA0E;AAC1E,+EAA+E;AAC/E,iEAAiE;AACjE,yFAAyF;AAEzF,qEAAqE;AACrE,iDAAiD;AACjD,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE3D,qEAAqE;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAG9D,kEAAkE;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { Mode } from '@tracelane/core';
2
+ /** The default output directory for reports (matches @tracelane/wdio). */
3
+ export declare const DEFAULT_OUT_DIR = "./tracelane-reports";
4
+ type EnvLike = Record<string, string | undefined>;
5
+ /** User-supplied options (all optional; passed to the reporter and/or fixture). */
6
+ export interface TraceLaneOptions {
7
+ /**
8
+ * Capture mode (ADR-0005). `'failed'` (default) writes a report only on test
9
+ * failure; `'all'` writes one for every test. `TRACELANE_MODE` overrides this.
10
+ */
11
+ mode?: Mode;
12
+ /** Directory to write reports into. Default `'./tracelane-reports'`. `TRACELANE_OUT_DIR` overrides. */
13
+ outDir?: string;
14
+ /**
15
+ * Capture failed network requests via CDP (Chromium-only). Default `true`.
16
+ * Routed into the report's network panel through the rrweb console plugin.
17
+ *
18
+ * **Cross-process note**: reporter constructor options are not propagated to
19
+ * the fixture (they run in separate Playwright worker processes). Setting
20
+ * `captureNetwork: false` on the reporter has no effect on the fixture's CDP
21
+ * capture. To disable CDP capture in the fixture, set the env var:
22
+ * `TRACELANE_CAPTURE_NETWORK=false` before running Playwright.
23
+ */
24
+ captureNetwork?: boolean;
25
+ }
26
+ /** Fully-resolved options — every field present. */
27
+ export interface ResolvedOptions {
28
+ mode: Mode;
29
+ outDir: string;
30
+ captureNetwork: boolean;
31
+ }
32
+ /**
33
+ * Resolve user options into a fully-resolved shape, applying defaults and the
34
+ * `TRACELANE_MODE` / `TRACELANE_OUT_DIR` / `TRACELANE_CAPTURE_NETWORK` env
35
+ * overrides (env wins over config, matching @tracelane/core's resolveMode). An
36
+ * invalid `TRACELANE_MODE` is ignored. `env` is injectable for testing.
37
+ *
38
+ * `TRACELANE_CAPTURE_NETWORK=false` (case-insensitive) disables CDP network
39
+ * capture in the fixture. This is the cross-process mechanism for the
40
+ * `captureNetwork` option — reporter constructor options are not propagated to
41
+ * the fixture because they run in different Playwright worker processes.
42
+ */
43
+ export declare function resolveOptions(opts?: TraceLaneOptions, env?: EnvLike): ResolvedOptions;
44
+ export {};
45
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,0EAA0E;AAC1E,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAErD,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAElD,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,OAAO,CAAC;CACzB;AAWD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,IAAI,GAAE,gBAAqB,EAC3B,GAAG,GAAE,OAAsB,GAC1B,eAAe,CASjB"}
@@ -0,0 +1,37 @@
1
+ // User-facing options for the Playwright reporter + fixture, and resolveOptions
2
+ // which normalizes them into the fully-resolved shape the session consumes.
3
+ //
4
+ // The option names mirror @tracelane/wdio (mode, outDir) and the env contract
5
+ // mirrors @tracelane/core (TRACELANE_MODE) plus TRACELANE_OUT_DIR. MVP capture
6
+ // surface is rrweb + console (always on) + failed-network (captureNetwork,
7
+ // default on; Chromium-only at runtime — see playwright-session.ts).
8
+ /** The default output directory for reports (matches @tracelane/wdio). */
9
+ export const DEFAULT_OUT_DIR = './tracelane-reports';
10
+ function isMode(value) {
11
+ return value === 'failed' || value === 'all';
12
+ }
13
+ /** Read `process.env` defensively (no hard `@types/node` dependency). */
14
+ function defaultEnv() {
15
+ return globalThis.process?.env ?? {};
16
+ }
17
+ /**
18
+ * Resolve user options into a fully-resolved shape, applying defaults and the
19
+ * `TRACELANE_MODE` / `TRACELANE_OUT_DIR` / `TRACELANE_CAPTURE_NETWORK` env
20
+ * overrides (env wins over config, matching @tracelane/core's resolveMode). An
21
+ * invalid `TRACELANE_MODE` is ignored. `env` is injectable for testing.
22
+ *
23
+ * `TRACELANE_CAPTURE_NETWORK=false` (case-insensitive) disables CDP network
24
+ * capture in the fixture. This is the cross-process mechanism for the
25
+ * `captureNetwork` option — reporter constructor options are not propagated to
26
+ * the fixture because they run in different Playwright worker processes.
27
+ */
28
+ export function resolveOptions(opts = {}, env = defaultEnv()) {
29
+ const mode = isMode(env.TRACELANE_MODE) ? env.TRACELANE_MODE : (opts.mode ?? 'failed');
30
+ const outDir = env.TRACELANE_OUT_DIR ?? opts.outDir ?? DEFAULT_OUT_DIR;
31
+ const envCaptureNetwork = env.TRACELANE_CAPTURE_NETWORK;
32
+ const captureNetwork = envCaptureNetwork !== undefined
33
+ ? envCaptureNetwork.toLowerCase() !== 'false'
34
+ : (opts.captureNetwork ?? true);
35
+ return { mode, outDir, captureNetwork };
36
+ }
37
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,4EAA4E;AAC5E,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,qEAAqE;AAIrE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAiCrD,SAAS,MAAM,CAAC,KAAyB;IACvC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,KAAK,CAAC;AAC/C,CAAC;AAED,yEAAyE;AACzE,SAAS,UAAU;IACjB,OAAQ,UAA8C,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAyB,EAAE,EAC3B,MAAe,UAAU,EAAE;IAE3B,MAAM,IAAI,GAAS,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC;IACvE,MAAM,iBAAiB,GAAG,GAAG,CAAC,yBAAyB,CAAC;IACxD,MAAM,cAAc,GAClB,iBAAiB,KAAK,SAAS;QAC7B,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE,KAAK,OAAO;QAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC;IACpC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { CDPSession, Page } from '@playwright/test';
2
+ import type { BrowserExecutor } from '@tracelane/core';
3
+ /**
4
+ * Build a {@link BrowserExecutor} over a Playwright `Page`. Pass an optional
5
+ * `cdp` (`CDPSession`) to enable the CDP-backed network capture path on
6
+ * Chromium.
7
+ */
8
+ export declare function createPlaywrightExecutor(page: Page, cdp?: CDPSession): BrowserExecutor;
9
+ //# sourceMappingURL=playwright-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright-executor.d.ts","sourceRoot":"","sources":["../src/playwright-executor.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAQvD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,eAAe,CAmCtF"}
@@ -0,0 +1,52 @@
1
+ // Adapts a Playwright `Page` to @tracelane/core's `BrowserExecutor` (ADR-0004).
2
+ //
3
+ // THE SEAM (plan Task 5): core's `execute<T>(fn, ...args)` is VARIADIC — it
4
+ // `.toString()`-serializes `fn` and passes every positional arg through. But
5
+ // Playwright's `page.evaluate(pageFunction, arg)` takes exactly ONE serializable
6
+ // arg. We bridge the two by packing `{ body: fn.toString(), args }` into that
7
+ // single arg and, in-page, rebuilding the function from its source and
8
+ // `.apply()`-ing it to the unpacked args. This preserves the WDIO-style
9
+ // "self-contained fn + explicit args" contract that core relies on.
10
+ //
11
+ // CDP (network capture) is Chromium-only: it requires a CDPSession, obtained by
12
+ // the caller via `context.newCDPSession(page)` and passed in. Without it, `cdp`
13
+ // and `on` throw — the session degrades to rrweb+console (mirrors WDIO's
14
+ // degrade path). page.evaluate-based `execute` works on all browsers.
15
+ /**
16
+ * Build a {@link BrowserExecutor} over a Playwright `Page`. Pass an optional
17
+ * `cdp` (`CDPSession`) to enable the CDP-backed network capture path on
18
+ * Chromium.
19
+ */
20
+ export function createPlaywrightExecutor(page, cdp) {
21
+ return {
22
+ async execute(fn, ...args) {
23
+ return page.evaluate((packed) => {
24
+ // Rebuild the serialized fn in-page and apply the unpacked args. The
25
+ // body is `fn.toString()`, so `(body)` is a valid function expression.
26
+ // `new Function` (not global eval) reconstructs it — this is the
27
+ // documented adapter seam (PRD §A.4).
28
+ const f = new Function(`return (${packed.body}).apply(null, arguments[0]);`);
29
+ return f(packed.args);
30
+ }, { body: fn.toString(), args });
31
+ },
32
+ async executeAsync() {
33
+ // The recorder (ADR-0006) only ever uses `execute`; WebDriver-style async
34
+ // scripts have no analogue under Playwright (page.evaluate already awaits
35
+ // a returned Promise). Surface a clear error if anything reaches for it.
36
+ throw new Error('executeAsync is not used by the recorder under Playwright');
37
+ },
38
+ async cdp(domain, command, params) {
39
+ if (!cdp)
40
+ throw new Error('CDP not attached (Chromium-only network capture)');
41
+ // Playwright's CDPSession.send is strongly typed over the CDP method
42
+ // union; the BrowserExecutor surface is string-based, so cast at the seam.
43
+ return cdp.send(`${domain}.${command}`, params);
44
+ },
45
+ on(event, handler) {
46
+ if (!cdp)
47
+ throw new Error('CDP not attached (Chromium-only network capture)');
48
+ cdp.on(event, handler);
49
+ },
50
+ };
51
+ }
52
+ //# sourceMappingURL=playwright-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright-executor.js","sourceRoot":"","sources":["../src/playwright-executor.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,iFAAiF;AACjF,8EAA8E;AAC9E,uEAAuE;AACvE,wEAAwE;AACxE,oEAAoE;AACpE,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,yEAAyE;AACzE,sEAAsE;AAWtE;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAU,EAAE,GAAgB;IACnE,OAAO;QACL,KAAK,CAAC,OAAO,CAAI,EAA6B,EAAE,GAAG,IAAe;YAChE,OAAO,IAAI,CAAC,QAAQ,CAClB,CAAC,MAAM,EAAE,EAAE;gBACT,qEAAqE;gBACrE,uEAAuE;gBACvE,iEAAiE;gBACjE,sCAAsC;gBACtC,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC,WAAW,MAAM,CAAC,IAAI,8BAA8B,CAAC,CAAC;gBAC7E,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAM,CAAC;YAC7B,CAAC,EACD,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAC9B,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,YAAY;YAChB,0EAA0E;YAC1E,0EAA0E;YAC1E,yEAAyE;YACzE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,MAAc,EAAE,OAAe,EAAE,MAAgC;YACzE,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;YAC9E,qEAAqE;YACrE,2EAA2E;YAC3E,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,OAAO,EAAW,EAAE,MAAe,CAAC,CAAC;QACpE,CAAC;QAED,EAAE,CAAC,KAAa,EAAE,OAAkC;YAClD,IAAI,CAAC,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;YAC9E,GAAG,CAAC,EAAE,CAAC,KAAc,EAAE,OAAgB,CAAC,CAAC;QAC3C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { CDPSession, Page } from '@playwright/test';
2
+ import type { TestInfo } from '@playwright/test';
3
+ import { type Recorder } from '@tracelane/core';
4
+ import type { ResolvedOptions } from './options.js';
5
+ /** Inputs to start a capture session. */
6
+ export interface StartInput {
7
+ page: Page;
8
+ options: ResolvedOptions;
9
+ rrwebBundle: string;
10
+ }
11
+ /** The live handles a started session carries across the use() boundary. */
12
+ export interface StartedSession {
13
+ recorder: Recorder;
14
+ /** The Chromium CDP session, when network capture was attached (else undefined). */
15
+ cdp?: CDPSession;
16
+ /** Browser name (e.g. `chromium`) for the report header, when resolvable. */
17
+ browserName?: string;
18
+ /** Browser version for the report header, when resolvable. */
19
+ browserVersion?: string;
20
+ }
21
+ /** Inputs to finalize a session (report build/write). */
22
+ export interface FinalizeInput {
23
+ page: Page;
24
+ testInfo: TestInfo;
25
+ options: ResolvedOptions;
26
+ rrwebBundle: string;
27
+ }
28
+ /** Inject the rrweb bundle on the context, build the executor, start the recorder. */
29
+ export declare function runStart(input: StartInput): Promise<StartedSession>;
30
+ /** Finalize the recorder (apply mode policy), and write a report when one is due. */
31
+ export declare function runFinalize(session: StartedSession, input: FinalizeInput): Promise<void>;
32
+ /** Convenience: start a session, then immediately finalize it (start→finalize). */
33
+ export declare function runTracelaneSession(input: FinalizeInput & {
34
+ rrwebBundle: string;
35
+ }): Promise<void>;
36
+ //# sourceMappingURL=playwright-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright-session.d.ts","sourceRoot":"","sources":["../src/playwright-session.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,QAAQ,EAAwC,MAAM,iBAAiB,CAAC;AAEtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAIpD,yCAAyC;AACzC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,oFAAoF;IACpF,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAWD,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,sFAAsF;AACtF,wBAAsB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAsDzE;AAoBD,qFAAqF;AACrF,wBAAsB,WAAW,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB9F;AAED,mFAAmF;AACnF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,141 @@
1
+ // Per-test capture orchestration (P1 PRD §B.2). This is the only place with a
2
+ // live `page` + `testInfo`, so it owns the recorder lifecycle and the report
3
+ // build. It is split into runStart (inject bundle + start recorder) and
4
+ // runFinalize (finalize + write report) so the auto-fixture (Task 10) can
5
+ // straddle the `use()` boundary: start before the test body runs, finalize
6
+ // after. runTracelaneSession is a start→finalize convenience used in tests.
7
+ //
8
+ // rrweb is injected two ways: via context.addInitScript (so fresh pages /
9
+ // post-navigation documents get the bundle automatically) and via the
10
+ // recorder's own start() (which evals the bundle + installs the in-page buffer
11
+ // in the CURRENT document). The recorder then drains events Node-side on its
12
+ // poll loop and at finalize (ADR-0006).
13
+ import { attachNetworkCapture, createRecorder } from '@tracelane/core';
14
+ import { writeReport } from '@tracelane/report';
15
+ import { createPlaywrightExecutor } from './playwright-executor.js';
16
+ import { isPassed, mapStatus } from './result-status.js';
17
+ /** The Playwright browser-type name, when resolvable from the page's context. */
18
+ function browserNameOf(page) {
19
+ try {
20
+ return page.context().browser()?.browserType().name();
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ }
26
+ /** Inject the rrweb bundle on the context, build the executor, start the recorder. */
27
+ export async function runStart(input) {
28
+ const { page, options, rrwebBundle } = input;
29
+ const context = page.context();
30
+ // Inject on the context so newly-created / navigated documents get rrweb
31
+ // before any app script runs.
32
+ await context.addInitScript({ content: rrwebBundle });
33
+ const browserName = browserNameOf(page);
34
+ let browserVersion;
35
+ try {
36
+ browserVersion = context.browser()?.version();
37
+ }
38
+ catch {
39
+ browserVersion = undefined;
40
+ }
41
+ // CDP network capture is Chromium-only (P1 PRD §E.2). When opted in and the
42
+ // browser is Chromium, open a CDP session and attach the shared capture path;
43
+ // on Firefox/WebKit (no CDP) we silently degrade to rrweb + console.
44
+ let cdp;
45
+ if (options.captureNetwork && browserName === 'chromium') {
46
+ cdp = await context.newCDPSession(page);
47
+ }
48
+ // Once the CDP session is open it is ours to close. If anything after this
49
+ // point throws (attachNetworkCapture / recorder.start()), runStart never
50
+ // returns — so runFinalize, the only other detach site, never runs and the
51
+ // session would leak for the worker's lifetime. Detach here before rethrowing.
52
+ try {
53
+ if (cdp) {
54
+ await attachNetworkCapture(createPlaywrightExecutor(page, cdp));
55
+ }
56
+ const executor = createPlaywrightExecutor(page, cdp);
57
+ const recorder = createRecorder({
58
+ executor,
59
+ rrwebBundle,
60
+ mode: options.mode,
61
+ // MVP: in-page network plugin off; the CDP path above is the network
62
+ // channel. The recorder still captures rrweb + console on all browsers.
63
+ });
64
+ await recorder.start();
65
+ const session = { recorder };
66
+ if (cdp)
67
+ session.cdp = cdp;
68
+ if (browserName !== undefined)
69
+ session.browserName = browserName;
70
+ if (browserVersion !== undefined)
71
+ session.browserVersion = browserVersion;
72
+ return session;
73
+ }
74
+ catch (err) {
75
+ if (cdp) {
76
+ await cdp.detach().catch(() => {
77
+ /* page/context may already be closed */
78
+ });
79
+ }
80
+ throw err;
81
+ }
82
+ }
83
+ /** Compose the report metadata from Playwright's testInfo + resolved browser info. */
84
+ function buildMeta(testInfo, session) {
85
+ // TestInfo.titlePath is an Array<string> property (NOT a method) — it is the
86
+ // [project, file, ...describe titles, test title] chain. Join it for a
87
+ // human-readable report title.
88
+ const meta = {
89
+ title: testInfo.titlePath.join(' › '),
90
+ status: mapStatus((testInfo.status ?? 'failed')),
91
+ };
92
+ if (testInfo.file)
93
+ meta.spec = testInfo.file;
94
+ const error = testInfo.error?.stack ?? testInfo.error?.message;
95
+ if (error !== undefined)
96
+ meta.error = error;
97
+ if (typeof testInfo.duration === 'number')
98
+ meta.durationMs = testInfo.duration;
99
+ if (session.browserName !== undefined)
100
+ meta.browserName = session.browserName;
101
+ if (session.browserVersion !== undefined)
102
+ meta.browserVersion = session.browserVersion;
103
+ return meta;
104
+ }
105
+ /** Finalize the recorder (apply mode policy), and write a report when one is due. */
106
+ export async function runFinalize(session, input) {
107
+ const { testInfo, options } = input;
108
+ try {
109
+ const { shouldBuildReport, events } = await session.recorder.finalize({
110
+ passed: isPassed(testInfo),
111
+ });
112
+ if (!shouldBuildReport)
113
+ return;
114
+ writeReport({
115
+ outDir: options.outDir,
116
+ // project.name namespaces the filename so parallel projects/workers never
117
+ // collide (ADR-0006 action item #6).
118
+ cid: testInfo.project?.name,
119
+ events,
120
+ meta: buildMeta(testInfo, session),
121
+ });
122
+ }
123
+ finally {
124
+ // Always detach the CDP session so it doesn't leak past the test.
125
+ if (session.cdp) {
126
+ await session.cdp.detach().catch(() => {
127
+ /* page/context may already be closed */
128
+ });
129
+ }
130
+ }
131
+ }
132
+ /** Convenience: start a session, then immediately finalize it (start→finalize). */
133
+ export async function runTracelaneSession(input) {
134
+ const session = await runStart({
135
+ page: input.page,
136
+ options: input.options,
137
+ rrwebBundle: input.rrwebBundle,
138
+ });
139
+ await runFinalize(session, input);
140
+ }
141
+ //# sourceMappingURL=playwright-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright-session.js","sourceRoot":"","sources":["../src/playwright-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
2
+ import { type TraceLaneOptions } from './options.js';
3
+ /**
4
+ * tracelane's Playwright reporter. Pair it with the fixture
5
+ * (`import { test } from '@tracelane/playwright/fixture'`) — the fixture records
6
+ * + writes reports; this reporter validates config at startup.
7
+ */
8
+ export declare class TraceLaneReporter implements Reporter {
9
+ private failed;
10
+ constructor(opts?: TraceLaneOptions);
11
+ /** The fixture + Playwright own the run output; this reporter is silent. */
12
+ printsToStdio(): boolean;
13
+ onBegin(_config: FullConfig, _suite: Suite): void;
14
+ onTestBegin(_test: TestCase, _result: TestResult): void;
15
+ onTestEnd(test: TestCase, _result: TestResult): void;
16
+ onEnd(_result: FullResult): void;
17
+ }
18
+ export default TraceLaneReporter;
19
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,gBAAgB,EAAkB,MAAM,cAAc,CAAC;AAErE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,OAAO,CAAC,MAAM,CAAK;gBAEP,IAAI,GAAE,gBAAqB;IAiBvC,4EAA4E;IAC5E,aAAa,IAAI,OAAO;IAIxB,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI;IAIjD,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAIvD,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAOpD,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;CAKjC;AAED,eAAe,iBAAiB,CAAC"}