@glubean/browser 0.8.1 → 0.9.0

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,470 @@
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 / user agent.
12
+ * - **Storage state** — restore cookies / localStorage before the page's
13
+ * first script runs, and capture them back out on demand (a thin "login
14
+ * once, reuse the session" primitive). Cookies go through this session's
15
+ * `Network.setCookies` (browser-context scoped, session-agnostic in CDP).
16
+ * localStorage does **not** — see guardrail ③.
17
+ *
18
+ * The keystone spike disproved the "Fetch is near-exclusive" hypothesis: a
19
+ * self-opened session running `Fetch.enable`/`fulfillRequest` is stable **as
20
+ * long as the user has not enabled Puppeteer's own request interception**.
21
+ * Three coexistence hazards exist, each handled below:
22
+ *
23
+ * **Guardrail ① — viewport ownership.** Our `Emulation.setDeviceMetricsOverride`
24
+ * and Puppeteer's `page.setViewport()` both drive device metrics and clobber
25
+ * each other last-wins. When `emulate.viewport` is configured, Glubean is the
26
+ * sole owner: it applies the viewport last and blocks `page.setViewport()` with
27
+ * a clear error so the two never race.
28
+ *
29
+ * **Guardrail ② — Fetch double-open.** If the user turns on Puppeteer request
30
+ * interception (`page.setRequestInterception(true)`) while our `Fetch` mock is
31
+ * active, both stacks try to handle the same paused request and fulfillment
32
+ * conflicts. When mocks are enabled, Glubean owns `Fetch` and blocks
33
+ * `page.setRequestInterception(true)` with a clear error. When no mocks are
34
+ * configured we never enable `Fetch`, so the user's own interception is free.
35
+ *
36
+ * **Guardrail ③ — new-document scripts need Puppeteer's OWN session.**
37
+ * Verified empirically: sending `Page.addScriptToEvaluateOnNewDocument` on
38
+ * our *auxiliary* `page.createCDPSession()` session registers without error
39
+ * (a real `identifier` comes back) but the script never actually fires on
40
+ * subsequent navigations — only the session Puppeteer itself uses for the
41
+ * page's frame-lifecycle bookkeeping gets its new-document scripts run.
42
+ * `storageState.localStorage` therefore seeds via Puppeteer's own
43
+ * `page.evaluateOnNewDocument()`, not a raw CDP call on this session.
44
+ *
45
+ * **Downloads** (`Browser` domain, BT1-M5) — `Browser.setDownloadBehavior`
46
+ * with `eventsEnabled: true`, called on this same auxiliary session, both
47
+ * configures the save directory AND (unlike guardrail ③'s Page-domain
48
+ * finding) reliably delivers `Browser.downloadWillBegin` /
49
+ * `Browser.downloadProgress` back on THIS session — verified empirically
50
+ * (spike script) against puppeteer-core ^24; `Browser.*` is genuinely
51
+ * session-agnostic where `Page.addScriptToEvaluateOnNewDocument` was not.
52
+ * The deprecated `Page.setDownloadBehavior` / `Page.downloadWillBegin` also
53
+ * work on the same spike but `Browser.*` is the protocol's forward path, so
54
+ * that's what's wired here. One caveat verified in the same spike: the file
55
+ * on disk is saved as `suggestedFilename`, not `guid` (despite some CDP docs
56
+ * implying the latter) — `DownloadEntry.path` is built from that name, which
57
+ * is only exact when Chrome didn't have to de-duplicate a collision.
58
+ * Always wired when a page is created (like dialog/popup) — a download IS
59
+ * evidence the moment it happens, not an opt-in capability.
60
+ *
61
+ * **Guardrail ④ — download events are browser-context-global.** Unlike the
62
+ * page-scoped `Network`/`Fetch` domains, `Browser.setDownloadBehavior` sets a
63
+ * single context-wide save path (last caller wins) and its `downloadWillBegin`/
64
+ * `downloadProgress` events fire on *every* session that turned events on, for
65
+ * *every* download in the context. So two instrumented pages in one Chrome
66
+ * would otherwise cross-observe and cross-repoint each other's downloads. Two
67
+ * mitigations: (a) the page layer uses ONE browser-wide download dir (not
68
+ * per-test) so the last-wins path is a no-op; (b) this session enables the
69
+ * `Page` domain, tracks its target's frame ids (`Page.getFrameTree` +
70
+ * `frameAttached`/`frameDetached`), and only records downloads whose
71
+ * originating `frameId` it owns — so a page never resolves another page's
72
+ * download. Both degrade safely: an unreadable frame tree falls back to
73
+ * accepting all events (single-page runs are unaffected).
74
+ *
75
+ * @module evidence
76
+ */
77
+ import type { CDPSession, Page } from "puppeteer-core";
78
+ import { type NetworkTracerOptions, type TraceFn } from "./network.js";
79
+ /**
80
+ * When screenshots are automatically captured into the evidence stream.
81
+ *
82
+ * - `"off"` — no automatic screenshots
83
+ * - `"on-failure"` — capture when a step or test fails (default)
84
+ * - `"every-step"` — capture after every action AND on failure
85
+ */
86
+ export type ScreenshotMode = "off" | "on-failure" | "every-step";
87
+ /**
88
+ * What triggered a screenshot capture.
89
+ *
90
+ * - `"step"` — post-action capture in every-step mode
91
+ * - `"failure"` — automatic capture on action or assertion failure
92
+ * - `"manual"` — explicit call to `page.captureScreenshot()`
93
+ */
94
+ export type ScreenshotTrigger = "step" | "failure" | "manual";
95
+ /** A screenshot captured into the evidence stream. */
96
+ export interface ScreenshotEntry {
97
+ /** Sequential number within this evidence session (1-based). */
98
+ seq: number;
99
+ /** Wall-clock ISO timestamp at capture time. */
100
+ ts: string;
101
+ /** Human-readable label (the action or assertion that triggered the capture). */
102
+ label: string;
103
+ /** What triggered this capture. */
104
+ trigger: ScreenshotTrigger;
105
+ /** Artifact ID when `ctx.saveArtifact` is available (SDK ≥ 0.13). */
106
+ artifactId?: string;
107
+ /** File path when falling back to direct file write. */
108
+ path?: string;
109
+ }
110
+ /**
111
+ * Screenshot capture options for the shared evidence session.
112
+ *
113
+ * The `shoot` delegate performs the actual I/O (screenshot + artifact save +
114
+ * `ctx.event()` emission); {@link EvidenceSession.captureShot} handles the
115
+ * mode / trigger policy, sequencing, and accumulation of entries.
116
+ */
117
+ export interface EvidenceScreenshotOptions {
118
+ /** Policy: which triggers result in a capture. */
119
+ mode: ScreenshotMode;
120
+ /**
121
+ * I/O delegate — takes the screenshot, saves the artifact, and emits
122
+ * the `browser:screenshot` evidence event. Returns an artifact reference
123
+ * for {@link ScreenshotEntry}. Called only when the mode/trigger policy allows.
124
+ *
125
+ * @param filename — suggested filename: `[FAIL-]NNN-label-ts.png`
126
+ * @param label — human label for the action/assertion
127
+ * @param trigger — what triggered this capture
128
+ */
129
+ shoot: (filename: string, label: string, trigger: ScreenshotTrigger) => Promise<{
130
+ artifactId?: string;
131
+ path?: string;
132
+ }>;
133
+ }
134
+ /** A single header as CDP's `Fetch.fulfillRequest` expects it. */
135
+ interface HeaderEntry {
136
+ name: string;
137
+ value: string;
138
+ }
139
+ /**
140
+ * A request-mock rule. Matching requests are fulfilled with a canned response;
141
+ * everything else is continued untouched.
142
+ */
143
+ export interface MockRule {
144
+ /**
145
+ * Match the request URL. A string matches by substring (`url.includes(...)`);
146
+ * a `RegExp` matches by `test(url)`.
147
+ */
148
+ url: string | RegExp;
149
+ /** Restrict to a single HTTP method (case-insensitive). Omit to match any. */
150
+ method?: string;
151
+ /** Response status code. @default 200 */
152
+ status?: number;
153
+ /** Extra response headers. */
154
+ headers?: Record<string, string>;
155
+ /**
156
+ * Response body. A string is sent verbatim; any other value is
157
+ * `JSON.stringify`-ed. The `content-type` is inferred (JSON vs plain text)
158
+ * unless `contentType` is set.
159
+ */
160
+ body?: unknown;
161
+ /** Explicit `content-type` header. Overrides the inferred value. */
162
+ contentType?: string;
163
+ }
164
+ /** Geolocation override. */
165
+ export interface GeolocationOverride {
166
+ latitude: number;
167
+ longitude: number;
168
+ /** Accuracy in meters. @default 0 (mirrors Puppeteer's `setGeolocation`). */
169
+ accuracy?: number;
170
+ }
171
+ /** Viewport / device-metrics override (owned solely by Glubean — see guardrail ①). */
172
+ export interface ViewportOverride {
173
+ width: number;
174
+ height: number;
175
+ /** @default 1 */
176
+ deviceScaleFactor?: number;
177
+ /** @default false */
178
+ mobile?: boolean;
179
+ }
180
+ /**
181
+ * Environment emulation applied on the shared evidence session.
182
+ *
183
+ * Timezone, geolocation, and user agent are pure overrides with no Puppeteer
184
+ * conflict. Viewport is special: see guardrail ① — do **not** also call
185
+ * `page.setViewport()`, it will race with this override.
186
+ */
187
+ export interface EmulationOptions {
188
+ /** IANA timezone id, e.g. `"America/New_York"`. */
189
+ timezone?: string;
190
+ /** Geolocation override. */
191
+ geolocation?: GeolocationOverride;
192
+ /** Viewport / device metrics. Glubean becomes the sole viewport owner. */
193
+ viewport?: ViewportOverride;
194
+ /** User-agent string override (`Emulation.setUserAgentOverride`). */
195
+ userAgent?: string;
196
+ }
197
+ /**
198
+ * A cookie as accepted by {@link EvidenceSession.attach}'s `storageState.cookies`
199
+ * and returned by {@link EvidenceSession.captureStorageState}. Mirrors the CDP
200
+ * `Network.CookieParam` / `Network.Cookie` shapes closely enough to round-trip:
201
+ * a captured cookie can be fed straight back in as an applied one.
202
+ */
203
+ export interface StorageCookie {
204
+ name: string;
205
+ value: string;
206
+ /** Either `domain` or `url` must be resolvable for CDP to place the cookie. */
207
+ domain?: string;
208
+ path?: string;
209
+ url?: string;
210
+ /** Unix time in seconds, or `-1` for a session cookie. */
211
+ expires?: number;
212
+ httpOnly?: boolean;
213
+ secure?: boolean;
214
+ sameSite?: "Strict" | "Lax" | "None";
215
+ }
216
+ /**
217
+ * Cookies + localStorage for one page — a thin "login once, reuse the
218
+ * session" primitive (à la Playwright's `storageState`). Cookies apply via
219
+ * CDP `Network.setCookies`; localStorage applies via Puppeteer's own
220
+ * `page.evaluateOnNewDocument()` (see guardrail ③) so it is present before
221
+ * the page's own scripts run on every navigation of this page.
222
+ */
223
+ export interface StorageState {
224
+ cookies?: StorageCookie[];
225
+ /** Key/value pairs seeded into `localStorage` on every new document. */
226
+ localStorage?: Record<string, string>;
227
+ }
228
+ /** Lifecycle state of a browser download (mirrors CDP `Browser.downloadProgress.state`). */
229
+ export type DownloadState = "inProgress" | "completed" | "canceled";
230
+ /**
231
+ * A browser download captured via CDP `Browser.downloadWillBegin` /
232
+ * `Browser.downloadProgress`.
233
+ */
234
+ export interface DownloadEntry {
235
+ /** CDP-assigned globally-unique download id. */
236
+ guid: string;
237
+ /** URL the download was initiated from (may be `data:`/`blob:`). */
238
+ url: string;
239
+ /** Filename suggested by the server/anchor at download start. */
240
+ suggestedFilename: string;
241
+ /**
242
+ * Best-effort on-disk path: `${dir}/${suggestedFilename}`. Exact only when
243
+ * Chrome didn't have to de-duplicate a filename collision in `dir` — see
244
+ * the module doc's Downloads note.
245
+ */
246
+ path: string;
247
+ }
248
+ /** Options wiring the shared session's download capture. */
249
+ export interface DownloadOptions {
250
+ /** Directory downloads are saved to. Must already exist — the caller creates it. */
251
+ dir: string;
252
+ /**
253
+ * Called on every state transition (`inProgress` fires once per progress
254
+ * tick — usually more than once per download; `completed`/`canceled` fire
255
+ * exactly once). Mainly for evidence emission; {@link EvidenceSession.waitForDownload}
256
+ * is the ergonomic way to correlate a triggering action with its result.
257
+ */
258
+ onDownload?: (entry: DownloadEntry, state: DownloadState) => void;
259
+ }
260
+ /** Options for {@link EvidenceSession.attach}. */
261
+ export interface EvidenceSessionOptions {
262
+ /**
263
+ * Network-trace callback (`ctx.trace`). When omitted, the `Network` domain
264
+ * tracer is not attached.
265
+ */
266
+ trace?: TraceFn;
267
+ /** Network-trace filter configuration. Ignored when `trace` is omitted. */
268
+ network?: Pick<NetworkTracerOptions, "include" | "excludePaths" | "filter">;
269
+ /** Request-mock rules. When non-empty, the `Fetch` domain is enabled (guardrail ②). */
270
+ mocks?: MockRule[];
271
+ /** Environment emulation (timezone / geolocation / viewport / user agent). */
272
+ emulate?: EmulationOptions;
273
+ /**
274
+ * Cookies / localStorage to restore before the page's first script runs
275
+ * (`storageState.cookies` via `Network.setCookies`, `storageState.localStorage`
276
+ * via Puppeteer's `page.evaluateOnNewDocument()` — see guardrail ③).
277
+ * Capture the current state with {@link EvidenceSession.captureStorageState}.
278
+ */
279
+ storageState?: StorageState;
280
+ /**
281
+ * Screenshot capture policy and I/O delegate.
282
+ *
283
+ * When provided, {@link EvidenceSession.captureShot} becomes active and will
284
+ * call `screenshots.shoot` based on the configured mode and trigger.
285
+ * Omit (or set `mode: "off"`) to disable all automatic screenshot capture.
286
+ */
287
+ screenshots?: EvidenceScreenshotOptions;
288
+ /**
289
+ * Download capture (`Browser.setDownloadBehavior` + `downloadWillBegin`/
290
+ * `downloadProgress`). When provided, every download on this page is
291
+ * allowed (not blocked) and reported via `onDownload` / {@link EvidenceSession.waitForDownload}.
292
+ */
293
+ downloads?: DownloadOptions;
294
+ }
295
+ /** A single CDP call: `{ method, params }`. Kept pure for testing. */
296
+ export interface CdpCall {
297
+ method: string;
298
+ params?: Record<string, unknown>;
299
+ }
300
+ /** @internal Does `rule` match the given request? */
301
+ export declare function matchMock(rule: MockRule, req: {
302
+ url: string;
303
+ method: string;
304
+ }): boolean;
305
+ /** @internal Find the first matching mock rule, or `undefined`. */
306
+ export declare function findMock(mocks: readonly MockRule[], req: {
307
+ url: string;
308
+ method: string;
309
+ }): MockRule | undefined;
310
+ /**
311
+ * @internal Build `Fetch.fulfillRequest` params from a rule.
312
+ *
313
+ * The body is always base64-encoded (as CDP requires). Content-type is inferred
314
+ * from the body kind unless `rule.contentType` is set. User headers win over the
315
+ * inferred content-type.
316
+ */
317
+ export declare function buildFulfillParams(rule: MockRule, requestId: string): {
318
+ requestId: string;
319
+ responseCode: number;
320
+ responseHeaders: HeaderEntry[];
321
+ body: string;
322
+ };
323
+ /**
324
+ * @internal Build the ordered list of `Emulation.*` CDP calls.
325
+ *
326
+ * Timezone, geolocation, and user agent come first (order-independent among
327
+ * themselves); the viewport override is applied **last** (guardrail ①) so it
328
+ * is the final word on device metrics at setup time.
329
+ */
330
+ export declare function buildEmulationCalls(emulate: EmulationOptions): CdpCall[];
331
+ /**
332
+ * @internal Build `Network.setCookies` params from `storageState.cookies`.
333
+ * Returns `undefined` when there is nothing to set (caller skips the call).
334
+ */
335
+ export declare function buildSetCookiesParams(cookies: StorageCookie[] | undefined): {
336
+ cookies: StorageCookie[];
337
+ } | undefined;
338
+ /**
339
+ * @internal Replace `page[method]` with a guard, returning a restore function.
340
+ *
341
+ * `shouldBlock` decides, per call arguments, whether to throw the guard error.
342
+ * Blocked calls throw synchronously; allowed calls fall through to the original
343
+ * method (or resolve to `undefined` if there was none). Used to enforce
344
+ * guardrails ① (viewport) and ② (Fetch interception).
345
+ */
346
+ export declare function guardPageMethod(page: any, method: string, message: string, shouldBlock: (args: unknown[]) => boolean): () => void;
347
+ /**
348
+ * A single self-opened CDP session that hosts every CDP-backed evidence
349
+ * capability for one page. Create with {@link EvidenceSession.attach}; release
350
+ * with {@link EvidenceSession.detach}.
351
+ */
352
+ export declare class EvidenceSession {
353
+ private readonly _cdp;
354
+ private readonly _cleanups;
355
+ private _detached;
356
+ private _screenshotOpts;
357
+ private _screenshotSeq;
358
+ private _screenshotLog;
359
+ private _downloadsEnabled;
360
+ private _downloadDir;
361
+ private _onDownload;
362
+ /**
363
+ * Frame ids owned by THIS page's target. `Browser.setDownloadBehavior`'s
364
+ * events are browser-context-global — every session that turned events on
365
+ * receives every download in the context. We only record downloads whose
366
+ * originating `frameId` belongs to this page, so two instrumented pages
367
+ * sharing one Chrome never cross-observe each other's downloads.
368
+ */
369
+ private _ownedFrames;
370
+ /**
371
+ * True only once the initial `Page.getFrameTree` seeded {@link _ownedFrames}.
372
+ * The frame filter engages ONLY when this is set — otherwise we accept all
373
+ * download events (fallback mode). Without this flag, a later
374
+ * `Page.frameAttached` would grow `_ownedFrames` from empty to non-empty and
375
+ * silently flip fallback mode into a PARTIAL filter that drops the page's own
376
+ * top-frame downloads (codex R2 P2).
377
+ */
378
+ private _frameTreeSeeded;
379
+ private _pendingDownloads;
380
+ private _downloadWaiters;
381
+ private constructor();
382
+ /** The underlying CDP session, for advanced/raw use. */
383
+ get cdp(): CDPSession;
384
+ /**
385
+ * All screenshots captured into this evidence session, in order.
386
+ *
387
+ * Each entry carries `seq`, `ts`, `label`, `trigger`, and an artifact
388
+ * reference (`artifactId` or `path`). The list is empty when no screenshot
389
+ * has been captured yet or when `screenshots.mode` is `"off"`.
390
+ */
391
+ get screenshots(): readonly ScreenshotEntry[];
392
+ /**
393
+ * Capture a screenshot into the evidence stream, subject to the configured
394
+ * {@link ScreenshotMode} and the `trigger` argument.
395
+ *
396
+ * | mode | "step" trigger | "failure" trigger | "manual" trigger |
397
+ * |---------------|----------------|-------------------|------------------|
398
+ * | "off" | skip | skip | skip |
399
+ * | "on-failure" | skip | capture | capture |
400
+ * | "every-step" | capture | capture | capture |
401
+ *
402
+ * Always best-effort: errors from the I/O delegate are silently swallowed
403
+ * so a broken page state never masks the real test error.
404
+ *
405
+ * Does nothing when no `screenshots` option was passed to {@link attach}.
406
+ */
407
+ captureShot(label: string, trigger: ScreenshotTrigger): Promise<void>;
408
+ /**
409
+ * Open one CDP session on `page` and wire up the requested capabilities:
410
+ * Network trace, Fetch mock (guardrail ②), Emulation (guardrail ① for
411
+ * viewport), and storage state (cookies + localStorage). Capabilities are
412
+ * only enabled when their config is present, so a page with no mocks never
413
+ * enables `Fetch` and leaves the user's own request interception untouched.
414
+ */
415
+ static attach(page: Page, options: EvidenceSessionOptions): Promise<EvidenceSession>;
416
+ private _installMocks;
417
+ private _applyStorageState;
418
+ /**
419
+ * @internal Wire `Browser.setDownloadBehavior` (`eventsEnabled: true`) plus
420
+ * the `downloadWillBegin` / `downloadProgress` listeners on this session.
421
+ * See the module doc's Downloads note for why `Browser.*` (not the
422
+ * deprecated `Page.*` pair) and why it works on an auxiliary session.
423
+ *
424
+ * `Browser.*` download events are browser-context-global, so we also enable
425
+ * the `Page` domain and track this target's frame ids, then only record
426
+ * downloads originating from a frame we own — two instrumented pages in one
427
+ * Chrome must not cross-observe each other's downloads.
428
+ */
429
+ private _enableDownloads;
430
+ /** @internal Best-effort onDownload callback — never let it wedge the waiter machine. */
431
+ private _notifyDownload;
432
+ /**
433
+ * Wait for the NEXT download (one that completes after this call) to finish,
434
+ * and resolve with its metadata. Register the wait *before* triggering the
435
+ * action that starts the download — `GlubeanPage.waitForDownload(action)` in
436
+ * `page.ts` does exactly this and is the ergonomic wrapper most callers
437
+ * should use instead of this lower-level method.
438
+ *
439
+ * Rejects if the next download is canceled, after `timeoutMs`, if `signal`
440
+ * aborts (e.g. the triggering action threw), or if the session has detached.
441
+ * Does **not** resolve from downloads that already completed before the call —
442
+ * each wait is scoped to a fresh, future download.
443
+ */
444
+ waitForDownload(timeoutMs: number, signal?: AbortSignal): Promise<DownloadEntry>;
445
+ /**
446
+ * Capture the current page's cookies + localStorage as a {@link StorageState}
447
+ * snapshot — the counterpart to {@link EvidenceSessionOptions.storageState}.
448
+ * Cookies are scoped to the page's current URL (`Network.getCookies`), not
449
+ * every cookie the browser holds, so unrelated tabs/origins never leak in.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * await page.goto("/login");
454
+ * // ... perform login ...
455
+ * const state = await page.getStorageState();
456
+ * // Reuse on a fresh page to skip the login flow:
457
+ * const chrome2 = browser({ launch: true, storageState: state });
458
+ * ```
459
+ */
460
+ captureStorageState(page: Page): Promise<StorageState>;
461
+ private _guardViewport;
462
+ /**
463
+ * Remove all listeners/overrides, restore guarded page methods, and detach
464
+ * the CDP session. Idempotent and best-effort — safe to call after the page
465
+ * has closed.
466
+ */
467
+ detach(): Promise<void>;
468
+ }
469
+ export {};
470
+ //# 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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"}