@glubean/browser 0.8.1 → 0.8.4

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.
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Shared evidence CDP session — the foundation for browser evidence capture.
3
+ *
4
+ * A single self-opened `createCDPSession` hosts **all** CDP-backed capabilities
5
+ * at once, instead of opening one session per capability:
6
+ *
7
+ * - **Network trace** (`Network` domain) — every in-page request as a Glubean
8
+ * trace event (see {@link ./network.ts}).
9
+ * - **Request mock** (`Fetch` domain) — fulfill matching requests with a canned
10
+ * response; non-matching requests are continued untouched.
11
+ * - **Emulation** (`Emulation` domain) — timezone / geolocation / viewport.
12
+ *
13
+ * The keystone spike disproved the "Fetch is near-exclusive" hypothesis: a
14
+ * self-opened session running `Fetch.enable`/`fulfillRequest` is stable **as
15
+ * long as the user has not enabled Puppeteer's own request interception**.
16
+ * Two coexistence hazards remain, each handled by a guardrail below:
17
+ *
18
+ * **Guardrail ① — viewport ownership.** Our `Emulation.setDeviceMetricsOverride`
19
+ * and Puppeteer's `page.setViewport()` both drive device metrics and clobber
20
+ * each other last-wins. When `emulate.viewport` is configured, Glubean is the
21
+ * sole owner: it applies the viewport last and blocks `page.setViewport()` with
22
+ * a clear error so the two never race.
23
+ *
24
+ * **Guardrail ② — Fetch double-open.** If the user turns on Puppeteer request
25
+ * interception (`page.setRequestInterception(true)`) while our `Fetch` mock is
26
+ * active, both stacks try to handle the same paused request and fulfillment
27
+ * conflicts. When mocks are enabled, Glubean owns `Fetch` and blocks
28
+ * `page.setRequestInterception(true)` with a clear error. When no mocks are
29
+ * configured we never enable `Fetch`, so the user's own interception is free.
30
+ *
31
+ * @module evidence
32
+ */
33
+ import type { CDPSession, Page } from "puppeteer-core";
34
+ import { type NetworkTracerOptions, type TraceFn } from "./network.js";
35
+ /**
36
+ * When screenshots are automatically captured into the evidence stream.
37
+ *
38
+ * - `"off"` — no automatic screenshots
39
+ * - `"on-failure"` — capture when a step or test fails (default)
40
+ * - `"every-step"` — capture after every action AND on failure
41
+ */
42
+ export type ScreenshotMode = "off" | "on-failure" | "every-step";
43
+ /**
44
+ * What triggered a screenshot capture.
45
+ *
46
+ * - `"step"` — post-action capture in every-step mode
47
+ * - `"failure"` — automatic capture on action or assertion failure
48
+ * - `"manual"` — explicit call to `page.captureScreenshot()`
49
+ */
50
+ export type ScreenshotTrigger = "step" | "failure" | "manual";
51
+ /** A screenshot captured into the evidence stream. */
52
+ export interface ScreenshotEntry {
53
+ /** Sequential number within this evidence session (1-based). */
54
+ seq: number;
55
+ /** Wall-clock ISO timestamp at capture time. */
56
+ ts: string;
57
+ /** Human-readable label (the action or assertion that triggered the capture). */
58
+ label: string;
59
+ /** What triggered this capture. */
60
+ trigger: ScreenshotTrigger;
61
+ /** Artifact ID when `ctx.saveArtifact` is available (SDK ≥ 0.13). */
62
+ artifactId?: string;
63
+ /** File path when falling back to direct file write. */
64
+ path?: string;
65
+ }
66
+ /**
67
+ * Screenshot capture options for the shared evidence session.
68
+ *
69
+ * The `shoot` delegate performs the actual I/O (screenshot + artifact save +
70
+ * `ctx.event()` emission); {@link EvidenceSession.captureShot} handles the
71
+ * mode / trigger policy, sequencing, and accumulation of entries.
72
+ */
73
+ export interface EvidenceScreenshotOptions {
74
+ /** Policy: which triggers result in a capture. */
75
+ mode: ScreenshotMode;
76
+ /**
77
+ * I/O delegate — takes the screenshot, saves the artifact, and emits
78
+ * the `browser:screenshot` evidence event. Returns an artifact reference
79
+ * for {@link ScreenshotEntry}. Called only when the mode/trigger policy allows.
80
+ *
81
+ * @param filename — suggested filename: `[FAIL-]NNN-label-ts.png`
82
+ * @param label — human label for the action/assertion
83
+ * @param trigger — what triggered this capture
84
+ */
85
+ shoot: (filename: string, label: string, trigger: ScreenshotTrigger) => Promise<{
86
+ artifactId?: string;
87
+ path?: string;
88
+ }>;
89
+ }
90
+ /** A single header as CDP's `Fetch.fulfillRequest` expects it. */
91
+ interface HeaderEntry {
92
+ name: string;
93
+ value: string;
94
+ }
95
+ /**
96
+ * A request-mock rule. Matching requests are fulfilled with a canned response;
97
+ * everything else is continued untouched.
98
+ */
99
+ export interface MockRule {
100
+ /**
101
+ * Match the request URL. A string matches by substring (`url.includes(...)`);
102
+ * a `RegExp` matches by `test(url)`.
103
+ */
104
+ url: string | RegExp;
105
+ /** Restrict to a single HTTP method (case-insensitive). Omit to match any. */
106
+ method?: string;
107
+ /** Response status code. @default 200 */
108
+ status?: number;
109
+ /** Extra response headers. */
110
+ headers?: Record<string, string>;
111
+ /**
112
+ * Response body. A string is sent verbatim; any other value is
113
+ * `JSON.stringify`-ed. The `content-type` is inferred (JSON vs plain text)
114
+ * unless `contentType` is set.
115
+ */
116
+ body?: unknown;
117
+ /** Explicit `content-type` header. Overrides the inferred value. */
118
+ contentType?: string;
119
+ }
120
+ /** Geolocation override. */
121
+ export interface GeolocationOverride {
122
+ latitude: number;
123
+ longitude: number;
124
+ /** Accuracy in meters. @default 0 (mirrors Puppeteer's `setGeolocation`). */
125
+ accuracy?: number;
126
+ }
127
+ /** Viewport / device-metrics override (owned solely by Glubean — see guardrail ①). */
128
+ export interface ViewportOverride {
129
+ width: number;
130
+ height: number;
131
+ /** @default 1 */
132
+ deviceScaleFactor?: number;
133
+ /** @default false */
134
+ mobile?: boolean;
135
+ }
136
+ /**
137
+ * Environment emulation applied on the shared evidence session.
138
+ *
139
+ * Timezone and geolocation are pure overrides with no Puppeteer conflict.
140
+ * Viewport is special: see guardrail ① — do **not** also call
141
+ * `page.setViewport()`, it will race with this override.
142
+ */
143
+ export interface EmulationOptions {
144
+ /** IANA timezone id, e.g. `"America/New_York"`. */
145
+ timezone?: string;
146
+ /** Geolocation override. */
147
+ geolocation?: GeolocationOverride;
148
+ /** Viewport / device metrics. Glubean becomes the sole viewport owner. */
149
+ viewport?: ViewportOverride;
150
+ }
151
+ /** Options for {@link EvidenceSession.attach}. */
152
+ export interface EvidenceSessionOptions {
153
+ /**
154
+ * Network-trace callback (`ctx.trace`). When omitted, the `Network` domain
155
+ * tracer is not attached.
156
+ */
157
+ trace?: TraceFn;
158
+ /** Network-trace filter configuration. Ignored when `trace` is omitted. */
159
+ network?: Pick<NetworkTracerOptions, "include" | "excludePaths" | "filter">;
160
+ /** Request-mock rules. When non-empty, the `Fetch` domain is enabled (guardrail ②). */
161
+ mocks?: MockRule[];
162
+ /** Environment emulation (timezone / geolocation / viewport). */
163
+ emulate?: EmulationOptions;
164
+ /**
165
+ * Screenshot capture policy and I/O delegate.
166
+ *
167
+ * When provided, {@link EvidenceSession.captureShot} becomes active and will
168
+ * call `screenshots.shoot` based on the configured mode and trigger.
169
+ * Omit (or set `mode: "off"`) to disable all automatic screenshot capture.
170
+ */
171
+ screenshots?: EvidenceScreenshotOptions;
172
+ }
173
+ /** A single CDP call: `{ method, params }`. Kept pure for testing. */
174
+ export interface CdpCall {
175
+ method: string;
176
+ params?: Record<string, unknown>;
177
+ }
178
+ /** @internal Does `rule` match the given request? */
179
+ export declare function matchMock(rule: MockRule, req: {
180
+ url: string;
181
+ method: string;
182
+ }): boolean;
183
+ /** @internal Find the first matching mock rule, or `undefined`. */
184
+ export declare function findMock(mocks: readonly MockRule[], req: {
185
+ url: string;
186
+ method: string;
187
+ }): MockRule | undefined;
188
+ /**
189
+ * @internal Build `Fetch.fulfillRequest` params from a rule.
190
+ *
191
+ * The body is always base64-encoded (as CDP requires). Content-type is inferred
192
+ * from the body kind unless `rule.contentType` is set. User headers win over the
193
+ * inferred content-type.
194
+ */
195
+ export declare function buildFulfillParams(rule: MockRule, requestId: string): {
196
+ requestId: string;
197
+ responseCode: number;
198
+ responseHeaders: HeaderEntry[];
199
+ body: string;
200
+ };
201
+ /**
202
+ * @internal Build the ordered list of `Emulation.*` CDP calls.
203
+ *
204
+ * Timezone and geolocation come first; the viewport override is applied **last**
205
+ * (guardrail ①) so it is the final word on device metrics at setup time.
206
+ */
207
+ export declare function buildEmulationCalls(emulate: EmulationOptions): CdpCall[];
208
+ /**
209
+ * @internal Replace `page[method]` with a guard, returning a restore function.
210
+ *
211
+ * `shouldBlock` decides, per call arguments, whether to throw the guard error.
212
+ * Blocked calls throw synchronously; allowed calls fall through to the original
213
+ * method (or resolve to `undefined` if there was none). Used to enforce
214
+ * guardrails ① (viewport) and ② (Fetch interception).
215
+ */
216
+ export declare function guardPageMethod(page: any, method: string, message: string, shouldBlock: (args: unknown[]) => boolean): () => void;
217
+ /**
218
+ * A single self-opened CDP session that hosts every CDP-backed evidence
219
+ * capability for one page. Create with {@link EvidenceSession.attach}; release
220
+ * with {@link EvidenceSession.detach}.
221
+ */
222
+ export declare class EvidenceSession {
223
+ private readonly _cdp;
224
+ private readonly _cleanups;
225
+ private _detached;
226
+ private _screenshotOpts;
227
+ private _screenshotSeq;
228
+ private _screenshotLog;
229
+ private constructor();
230
+ /** The underlying CDP session, for advanced/raw use. */
231
+ get cdp(): CDPSession;
232
+ /**
233
+ * All screenshots captured into this evidence session, in order.
234
+ *
235
+ * Each entry carries `seq`, `ts`, `label`, `trigger`, and an artifact
236
+ * reference (`artifactId` or `path`). The list is empty when no screenshot
237
+ * has been captured yet or when `screenshots.mode` is `"off"`.
238
+ */
239
+ get screenshots(): readonly ScreenshotEntry[];
240
+ /**
241
+ * Capture a screenshot into the evidence stream, subject to the configured
242
+ * {@link ScreenshotMode} and the `trigger` argument.
243
+ *
244
+ * | mode | "step" trigger | "failure" trigger | "manual" trigger |
245
+ * |---------------|----------------|-------------------|------------------|
246
+ * | "off" | skip | skip | skip |
247
+ * | "on-failure" | skip | capture | capture |
248
+ * | "every-step" | capture | capture | capture |
249
+ *
250
+ * Always best-effort: errors from the I/O delegate are silently swallowed
251
+ * so a broken page state never masks the real test error.
252
+ *
253
+ * Does nothing when no `screenshots` option was passed to {@link attach}.
254
+ */
255
+ captureShot(label: string, trigger: ScreenshotTrigger): Promise<void>;
256
+ /**
257
+ * Open one CDP session on `page` and wire up the requested capabilities:
258
+ * Network trace, Fetch mock (guardrail ②), and Emulation (guardrail ① for
259
+ * viewport). Capabilities are only enabled when their config is present, so a
260
+ * page with no mocks never enables `Fetch` and leaves the user's own request
261
+ * interception untouched.
262
+ */
263
+ static attach(page: Page, options: EvidenceSessionOptions): Promise<EvidenceSession>;
264
+ private _installMocks;
265
+ private _guardViewport;
266
+ /**
267
+ * Remove all listeners/overrides, restore guarded page methods, and detach
268
+ * the CDP session. Idempotent and best-effort — safe to call after the page
269
+ * has closed.
270
+ */
271
+ detach(): Promise<void>;
272
+ }
273
+ export {};
274
+ //# sourceMappingURL=evidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Shared evidence CDP session — the foundation for browser evidence capture.
3
+ *
4
+ * A single self-opened `createCDPSession` hosts **all** CDP-backed capabilities
5
+ * at once, instead of opening one session per capability:
6
+ *
7
+ * - **Network trace** (`Network` domain) — every in-page request as a Glubean
8
+ * trace event (see {@link ./network.ts}).
9
+ * - **Request mock** (`Fetch` domain) — fulfill matching requests with a canned
10
+ * response; non-matching requests are continued untouched.
11
+ * - **Emulation** (`Emulation` domain) — timezone / geolocation / viewport.
12
+ *
13
+ * The keystone spike disproved the "Fetch is near-exclusive" hypothesis: a
14
+ * self-opened session running `Fetch.enable`/`fulfillRequest` is stable **as
15
+ * long as the user has not enabled Puppeteer's own request interception**.
16
+ * Two coexistence hazards remain, each handled by a guardrail below:
17
+ *
18
+ * **Guardrail ① — viewport ownership.** Our `Emulation.setDeviceMetricsOverride`
19
+ * and Puppeteer's `page.setViewport()` both drive device metrics and clobber
20
+ * each other last-wins. When `emulate.viewport` is configured, Glubean is the
21
+ * sole owner: it applies the viewport last and blocks `page.setViewport()` with
22
+ * a clear error so the two never race.
23
+ *
24
+ * **Guardrail ② — Fetch double-open.** If the user turns on Puppeteer request
25
+ * interception (`page.setRequestInterception(true)`) while our `Fetch` mock is
26
+ * active, both stacks try to handle the same paused request and fulfillment
27
+ * conflicts. When mocks are enabled, Glubean owns `Fetch` and blocks
28
+ * `page.setRequestInterception(true)` with a clear error. When no mocks are
29
+ * configured we never enable `Fetch`, so the user's own interception is free.
30
+ *
31
+ * @module evidence
32
+ */
33
+ import { attachNetworkTracer, } from "./network.js";
34
+ // ── Pure helpers (exported for testing) ───────────────────────────────
35
+ /** @internal Does `rule` match the given request? */
36
+ export function matchMock(rule, req) {
37
+ if (rule.method && rule.method.toUpperCase() !== req.method.toUpperCase()) {
38
+ return false;
39
+ }
40
+ if (typeof rule.url === "string")
41
+ return req.url.includes(rule.url);
42
+ // Test against a stateless clone: a user-supplied global/sticky regex
43
+ // (`/g`, `/y`) carries `lastIndex` state, so `.test()` on the original would
44
+ // flip-flop matches for the same URL across repeated requests (and would also
45
+ // mutate the caller's regex). Strip `g`/`y` on a copy to keep matching pure.
46
+ const stateless = new RegExp(rule.url.source, rule.url.flags.replace(/[gy]/g, ""));
47
+ return stateless.test(req.url);
48
+ }
49
+ /** @internal Find the first matching mock rule, or `undefined`. */
50
+ export function findMock(mocks, req) {
51
+ return mocks.find((m) => matchMock(m, req));
52
+ }
53
+ /**
54
+ * @internal Build `Fetch.fulfillRequest` params from a rule.
55
+ *
56
+ * The body is always base64-encoded (as CDP requires). Content-type is inferred
57
+ * from the body kind unless `rule.contentType` is set. User headers win over the
58
+ * inferred content-type.
59
+ */
60
+ export function buildFulfillParams(rule, requestId) {
61
+ let bodyStr = "";
62
+ let inferredType;
63
+ if (rule.body !== undefined) {
64
+ if (typeof rule.body === "string") {
65
+ bodyStr = rule.body;
66
+ inferredType = "text/plain; charset=utf-8";
67
+ }
68
+ else {
69
+ bodyStr = JSON.stringify(rule.body);
70
+ inferredType = "application/json; charset=utf-8";
71
+ }
72
+ }
73
+ const headerMap = new Map();
74
+ const contentType = rule.contentType ?? inferredType;
75
+ if (contentType !== undefined)
76
+ headerMap.set("content-type", contentType);
77
+ // User headers win over the inferred content-type (case-insensitive keys).
78
+ for (const [name, value] of Object.entries(rule.headers ?? {})) {
79
+ headerMap.set(name.toLowerCase(), value);
80
+ }
81
+ return {
82
+ requestId,
83
+ responseCode: rule.status ?? 200,
84
+ responseHeaders: [...headerMap].map(([name, value]) => ({ name, value })),
85
+ body: Buffer.from(bodyStr, "utf8").toString("base64"),
86
+ };
87
+ }
88
+ /**
89
+ * @internal Build the ordered list of `Emulation.*` CDP calls.
90
+ *
91
+ * Timezone and geolocation come first; the viewport override is applied **last**
92
+ * (guardrail ①) so it is the final word on device metrics at setup time.
93
+ */
94
+ export function buildEmulationCalls(emulate) {
95
+ const calls = [];
96
+ if (emulate.timezone !== undefined) {
97
+ calls.push({
98
+ method: "Emulation.setTimezoneOverride",
99
+ params: { timezoneId: emulate.timezone },
100
+ });
101
+ }
102
+ if (emulate.geolocation) {
103
+ const { latitude, longitude, accuracy } = emulate.geolocation;
104
+ calls.push({
105
+ method: "Emulation.setGeolocationOverride",
106
+ params: { latitude, longitude, accuracy: accuracy ?? 0 },
107
+ });
108
+ }
109
+ if (emulate.viewport) {
110
+ const { width, height, deviceScaleFactor, mobile } = emulate.viewport;
111
+ calls.push({
112
+ method: "Emulation.setDeviceMetricsOverride",
113
+ params: {
114
+ width,
115
+ height,
116
+ deviceScaleFactor: deviceScaleFactor ?? 1,
117
+ mobile: mobile ?? false,
118
+ },
119
+ });
120
+ }
121
+ return calls;
122
+ }
123
+ /**
124
+ * @internal Replace `page[method]` with a guard, returning a restore function.
125
+ *
126
+ * `shouldBlock` decides, per call arguments, whether to throw the guard error.
127
+ * Blocked calls throw synchronously; allowed calls fall through to the original
128
+ * method (or resolve to `undefined` if there was none). Used to enforce
129
+ * guardrails ① (viewport) and ② (Fetch interception).
130
+ */
131
+ export function guardPageMethod(
132
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
+ page, method, message, shouldBlock) {
134
+ const hadOwn = Object.prototype.hasOwnProperty.call(page, method);
135
+ const previous = page[method];
136
+ const original = typeof previous === "function"
137
+ ? previous.bind(page)
138
+ : undefined;
139
+ page[method] = (...args) => {
140
+ if (shouldBlock(args))
141
+ throw new Error(message);
142
+ return original ? original(...args) : Promise.resolve(undefined);
143
+ };
144
+ return () => {
145
+ if (hadOwn)
146
+ page[method] = previous;
147
+ else
148
+ delete page[method];
149
+ };
150
+ }
151
+ // ── EvidenceSession ───────────────────────────────────────────────────
152
+ /**
153
+ * A single self-opened CDP session that hosts every CDP-backed evidence
154
+ * capability for one page. Create with {@link EvidenceSession.attach}; release
155
+ * with {@link EvidenceSession.detach}.
156
+ */
157
+ export class EvidenceSession {
158
+ _cdp;
159
+ _cleanups = [];
160
+ _detached = false;
161
+ // ── Screenshot state ──────────────────────────────────────────────
162
+ _screenshotOpts;
163
+ _screenshotSeq = 0;
164
+ _screenshotLog = [];
165
+ constructor(cdp) {
166
+ this._cdp = cdp;
167
+ }
168
+ /** The underlying CDP session, for advanced/raw use. */
169
+ get cdp() {
170
+ return this._cdp;
171
+ }
172
+ /**
173
+ * All screenshots captured into this evidence session, in order.
174
+ *
175
+ * Each entry carries `seq`, `ts`, `label`, `trigger`, and an artifact
176
+ * reference (`artifactId` or `path`). The list is empty when no screenshot
177
+ * has been captured yet or when `screenshots.mode` is `"off"`.
178
+ */
179
+ get screenshots() {
180
+ return this._screenshotLog;
181
+ }
182
+ /**
183
+ * Capture a screenshot into the evidence stream, subject to the configured
184
+ * {@link ScreenshotMode} and the `trigger` argument.
185
+ *
186
+ * | mode | "step" trigger | "failure" trigger | "manual" trigger |
187
+ * |---------------|----------------|-------------------|------------------|
188
+ * | "off" | skip | skip | skip |
189
+ * | "on-failure" | skip | capture | capture |
190
+ * | "every-step" | capture | capture | capture |
191
+ *
192
+ * Always best-effort: errors from the I/O delegate are silently swallowed
193
+ * so a broken page state never masks the real test error.
194
+ *
195
+ * Does nothing when no `screenshots` option was passed to {@link attach}.
196
+ */
197
+ async captureShot(label, trigger) {
198
+ const opts = this._screenshotOpts;
199
+ if (!opts)
200
+ return;
201
+ // "off" blocks automatic triggers but manual checkpoints always fire.
202
+ if (opts.mode === "off" && trigger !== "manual")
203
+ return;
204
+ if (opts.mode === "on-failure" && trigger === "step")
205
+ return;
206
+ this._screenshotSeq++;
207
+ const seq = this._screenshotSeq;
208
+ const ts = new Date().toISOString();
209
+ const sanitized = label.replace(/[^a-z0-9_-]/gi, "_").slice(0, 60);
210
+ const tsCompact = ts.replace(/[:.]/g, "").slice(0, 15);
211
+ const prefix = trigger === "failure" ? "FAIL-" : "";
212
+ const filename = `${prefix}${String(seq).padStart(3, "0")}-${sanitized}-${tsCompact}.png`;
213
+ try {
214
+ const ref = await opts.shoot(filename, label, trigger);
215
+ this._screenshotLog.push({ seq, ts, label, trigger, ...ref });
216
+ }
217
+ catch {
218
+ // best-effort: page may be in a broken state
219
+ }
220
+ }
221
+ /**
222
+ * Open one CDP session on `page` and wire up the requested capabilities:
223
+ * Network trace, Fetch mock (guardrail ②), and Emulation (guardrail ① for
224
+ * viewport). Capabilities are only enabled when their config is present, so a
225
+ * page with no mocks never enables `Fetch` and leaves the user's own request
226
+ * interception untouched.
227
+ */
228
+ static async attach(page, options) {
229
+ const cdp = await page.createCDPSession();
230
+ const session = new EvidenceSession(cdp);
231
+ // Wire screenshot options (no CDP domain — just stores the delegate).
232
+ // Store opts even when mode is "off" so that captureShot can still
233
+ // honour explicit manual checkpoints (captureShot itself gates auto
234
+ // triggers via `if (mode === "off" && trigger !== "manual") return`).
235
+ if (options.screenshots) {
236
+ session._screenshotOpts = options.screenshots;
237
+ }
238
+ try {
239
+ // 1. Network trace.
240
+ if (options.trace) {
241
+ const removeNetwork = await attachNetworkTracer(cdp, {
242
+ trace: options.trace,
243
+ include: options.network?.include,
244
+ excludePaths: options.network?.excludePaths,
245
+ filter: options.network?.filter,
246
+ });
247
+ session._cleanups.push(removeNetwork);
248
+ }
249
+ // 2. Fetch mock — guardrail ②: Glubean owns Fetch, block user interception.
250
+ const mocks = options.mocks;
251
+ if (mocks && mocks.length > 0) {
252
+ await session._installMocks(page, mocks);
253
+ }
254
+ // 3. Emulation (timezone / geolocation) + viewport last (guardrail ①).
255
+ if (options.emulate) {
256
+ for (const call of buildEmulationCalls(options.emulate)) {
257
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
258
+ await cdp.send(call.method, call.params);
259
+ }
260
+ if (options.emulate.viewport) {
261
+ session._guardViewport(page);
262
+ }
263
+ }
264
+ }
265
+ catch (err) {
266
+ // Roll back any partial wiring so we never leak a half-open session.
267
+ await session.detach();
268
+ throw err;
269
+ }
270
+ return session;
271
+ }
272
+ async _installMocks(page, mocks) {
273
+ // Guardrail ②: block the user from enabling Puppeteer request interception
274
+ // while our Fetch mock is active (double-fulfill conflict). Disabling
275
+ // (`false`) is allowed through to the original.
276
+ const restoreInterception = guardPageMethod(page, "setRequestInterception", "Glubean request mocking is active on this page: do not call " +
277
+ "page.setRequestInterception(true) — it conflicts with the mock's " +
278
+ "Fetch handler. Remove the `mock` option to manage interception yourself.", (args) => args[0] === true);
279
+ this._cleanups.push(restoreInterception);
280
+ // Intercept every request at the Request stage; match in JS. Mocked
281
+ // requests are fulfilled, everything else is continued untouched — so the
282
+ // Network tracer still observes real responses.
283
+ await this._cdp.send("Fetch.enable", {
284
+ patterns: [{ urlPattern: "*", requestStage: "Request" }],
285
+ });
286
+ const onPaused = (event) => {
287
+ const rule = findMock(mocks, {
288
+ url: event.request.url,
289
+ method: event.request.method,
290
+ });
291
+ const done = rule
292
+ ? this._cdp.send("Fetch.fulfillRequest",
293
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
294
+ buildFulfillParams(rule, event.requestId))
295
+ : this._cdp.send("Fetch.continueRequest", {
296
+ requestId: event.requestId,
297
+ });
298
+ // The request is gone if the page navigated away mid-flight — ignore.
299
+ done.catch(() => { });
300
+ };
301
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
302
+ this._cdp.on("Fetch.requestPaused", onPaused);
303
+ this._cleanups.push(() => {
304
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
305
+ this._cdp.off("Fetch.requestPaused", onPaused);
306
+ });
307
+ }
308
+ _guardViewport(page) {
309
+ // Guardrail ①: Glubean owns the viewport via Emulation on this session.
310
+ // Block page.setViewport() so it can't clobber the override last-wins.
311
+ const restore = guardPageMethod(page, "setViewport", "Glubean owns the viewport on this page (via the `emulate.viewport` " +
312
+ "option): do not call page.setViewport() — the two overrides race " +
313
+ "last-wins. Configure the viewport through browser({ emulate }) instead.", () => true);
314
+ this._cleanups.push(restore);
315
+ }
316
+ /**
317
+ * Remove all listeners/overrides, restore guarded page methods, and detach
318
+ * the CDP session. Idempotent and best-effort — safe to call after the page
319
+ * has closed.
320
+ */
321
+ async detach() {
322
+ if (this._detached)
323
+ return;
324
+ this._detached = true;
325
+ // Run cleanups in reverse (LIFO) so guards/overrides unwind in order.
326
+ for (const cleanup of this._cleanups.reverse()) {
327
+ try {
328
+ await cleanup();
329
+ }
330
+ catch {
331
+ // best-effort — page/session may already be gone
332
+ }
333
+ }
334
+ this._cleanups.length = 0;
335
+ try {
336
+ await this._cdp.detach();
337
+ }
338
+ catch {
339
+ // session may already be closed
340
+ }
341
+ }
342
+ }
343
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -38,6 +38,7 @@
38
38
  */
39
39
  export { browser } from "./plugin.js";
40
40
  export { GlubeanBrowser, GlubeanPage } from "./page.js";
41
- export type { ActionOptions, BrowserAction, BrowserEvent, BrowserOptions, BrowserTestContext, InstrumentedPage, PuppeteerLike, NetworkTraceOptions, ResponseChecks, ScreenshotMode, } from "./page.js";
41
+ export type { ActionOptions, BrowserAction, BrowserEvent, BrowserOptions, BrowserTestContext, InstrumentedPage, PuppeteerLike, NetworkTraceOptions, ResponseChecks, } from "./page.js";
42
+ export type { EmulationOptions, EvidenceScreenshotOptions, GeolocationOverride, MockRule, ScreenshotEntry, ScreenshotMode, ScreenshotTrigger, ViewportOverride, } from "./evidence.js";
42
43
  export type { WrappedLocator } from "./locator.js";
43
44
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}