@orkestrel/scaffold 0.0.67 → 0.0.68
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/dist/bin/main.js +67 -44
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/templates/brief.md +9 -0
- package/dist/host/claude/agents/orkestrel.md +4 -4
- package/dist/host/claude/rules/names.md +15 -0
- package/dist/host/claude/rules/tests.md +33 -4
- package/dist/host/claude/rules/workspace.md +14 -2
- package/dist/host/dotfiles/prettierignore +3 -0
- package/dist/host/guides/README.md +65 -0
- package/dist/host/guides/abort.md +169 -0
- package/dist/host/guides/agent.md +1509 -0
- package/dist/host/guides/brief.md +1266 -0
- package/dist/host/guides/browser.md +2200 -0
- package/dist/host/guides/budget.md +196 -0
- package/dist/host/guides/codec.md +519 -0
- package/dist/host/guides/console.md +785 -0
- package/dist/host/guides/contract.md +1193 -0
- package/dist/host/guides/csv.md +541 -0
- package/dist/host/guides/database.md +2518 -0
- package/dist/host/guides/emitter.md +233 -0
- package/dist/host/guides/form.md +1791 -0
- package/dist/host/guides/html.md +717 -0
- package/dist/host/guides/indexeddb.md +505 -0
- package/dist/host/guides/interpret.md +1029 -0
- package/dist/host/guides/lsp.md +515 -0
- package/dist/host/guides/markdown.md +964 -0
- package/dist/host/guides/mcp.md +5554 -0
- package/dist/host/guides/middleware.md +927 -0
- package/dist/host/guides/msg.md +440 -0
- package/dist/host/guides/ndjson.md +120 -0
- package/dist/host/guides/ollama.md +380 -0
- package/dist/host/guides/pool.md +280 -0
- package/dist/host/guides/probe.md +1210 -0
- package/dist/host/guides/process.md +1620 -0
- package/dist/host/guides/program.md +1110 -0
- package/dist/host/guides/qualifier.md +854 -0
- package/dist/host/guides/queue.md +370 -0
- package/dist/host/guides/rater.md +330 -0
- package/dist/host/guides/reason.md +1122 -0
- package/dist/host/guides/relation.md +373 -0
- package/dist/host/guides/router.md +753 -0
- package/dist/host/guides/scaffold.md +192 -31
- package/dist/host/guides/sea.md +383 -0
- package/dist/host/guides/server.md +752 -0
- package/dist/host/guides/sqlite.md +330 -0
- package/dist/host/guides/sse.md +187 -0
- package/dist/host/guides/supervisor.md +4890 -0
- package/dist/host/guides/table.md +1556 -0
- package/dist/host/guides/template.md +280 -0
- package/dist/host/guides/terminal.md +1145 -0
- package/dist/host/guides/test.md +2969 -0
- package/dist/host/guides/timeout.md +252 -0
- package/dist/host/guides/tool.md +311 -0
- package/dist/host/guides/toolbox.md +1038 -0
- package/dist/host/guides/websocket.md +282 -0
- package/dist/host/guides/worker.md +615 -0
- package/dist/host/guides/workflow.md +1507 -0
- package/dist/host/guides/workspace.md +595 -0
- package/dist/host/manifest.json +1218 -10
- package/dist/host/tests/policy.test.ts +279 -2
- package/dist/host/tests/setupPolicy.ts +437 -6
- package/dist/src/core/index.cjs +38 -16
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +33 -9
- package/dist/src/core/index.d.ts +33 -9
- package/dist/src/core/index.js +37 -17
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +1750 -1567
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +106 -24
- package/dist/src/server/index.d.ts +106 -24
- package/dist/src/server/index.js +1751 -1570
- package/dist/src/server/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,2200 @@
|
|
|
1
|
+
# Browser
|
|
2
|
+
|
|
3
|
+
> A lightweight Chrome DevTools Protocol automation layer for Chromium-family
|
|
4
|
+
> browsers: an environment-agnostic core that drives pages, frames, locators, and
|
|
5
|
+
> DOM snapshots over an injected transport, and a Node runtime that finds,
|
|
6
|
+
> launches, and connects to the browser itself.
|
|
7
|
+
|
|
8
|
+
`CDPClient` frames JSON-RPC-shaped CDP messages over the transport, `BrowserContext` and
|
|
9
|
+
`BrowserPage` model a CDP browser context and its pages, `BrowserSnapshot` turns a captured DOM
|
|
10
|
+
snapshot into navigable serializable data, and `BrowserCodegen` records page interactions for later
|
|
11
|
+
script compilation — none of it touching `WebSocket`, `node:*`, or a filesystem, so the same code
|
|
12
|
+
runs under Node or in a page. One capability reaches past the protocol: `article()` distills a
|
|
13
|
+
captured document to its reader-facing prose through `@orkestrel/html`, selecting content rather
|
|
14
|
+
than dumping the whole body's text. The Node pieces are `WebSocketCDPTransport`, a `WebSocket`-backed
|
|
15
|
+
CDP transport; `Browser`, which spawns a real Chromium-family process when nothing is already
|
|
16
|
+
listening on the CDP endpoint; and a filesystem-backed browser writer. Import the
|
|
17
|
+
environment-agnostic core from `@orkestrel/browser` and the Node runtime from
|
|
18
|
+
`@orkestrel/browser/server`. Source: [`src/core`](../src/core) (through `@src/core`) and
|
|
19
|
+
[`src/server`](../src/server) (through `@src/server`).
|
|
20
|
+
|
|
21
|
+
## Surface
|
|
22
|
+
|
|
23
|
+
### Connect to a browser and drive a page
|
|
24
|
+
|
|
25
|
+
Connect to an already-running browser, or launch one, then open a page and drive it:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { createBrowser } from '@orkestrel/browser/server'
|
|
29
|
+
|
|
30
|
+
const browser = createBrowser({ headless: true })
|
|
31
|
+
await browser.connect() // CDP endpoint discovery → connect, else launch
|
|
32
|
+
const page = await browser.create({ url: 'https://example.com' })
|
|
33
|
+
await page.click('#accept')
|
|
34
|
+
const shot = await page.screenshot({ path: './out.png' })
|
|
35
|
+
await browser.destroy()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Drive the core client over an injected transport
|
|
39
|
+
|
|
40
|
+
Drive the CDP client from any environment over a transport that satisfies
|
|
41
|
+
`CDPTransportInterface`:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createCDPClient } from '@orkestrel/browser'
|
|
45
|
+
|
|
46
|
+
const client = createCDPClient({ transport }) // transport: CDPTransportInterface
|
|
47
|
+
await client.connect()
|
|
48
|
+
const targets = await client.send('Target.getTargets')
|
|
49
|
+
await client.close()
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Core
|
|
53
|
+
|
|
54
|
+
#### Factories
|
|
55
|
+
|
|
56
|
+
| API | Kind | Summary |
|
|
57
|
+
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
|
|
58
|
+
| `createCDPClient` | function | Creates a `CDPClientInterface` bound to the given `CDPTransportInterface`. |
|
|
59
|
+
| `createBrowserSnapshot` | function | Creates a navigable `BrowserSnapshotInterface` over decoded `BrowserSnapshotInput` data. |
|
|
60
|
+
|
|
61
|
+
#### Classes
|
|
62
|
+
|
|
63
|
+
| API | Kind | Summary |
|
|
64
|
+
| ----------------- | ----- | -------------------------------------------------------------------------------------- |
|
|
65
|
+
| `CDPClient` | class | Provides a lightweight Chrome DevTools Protocol client over a `CDPTransportInterface`. |
|
|
66
|
+
| `BrowserContext` | class | Owns pages and shared state inside one Chromium browser context. |
|
|
67
|
+
| `BrowserFrame` | class | Represents one attached document frame, evaluated through its own CDP execution world. |
|
|
68
|
+
| `BrowserPage` | class | Represents a top-level browser page, including its target lifecycle and child frames. |
|
|
69
|
+
| `BrowserCodegen` | class | Records page navigation and form interactions and compiles replayable scripts. |
|
|
70
|
+
| `BrowserSnapshot` | class | Represents a navigable, serializable browser DOM snapshot. |
|
|
71
|
+
|
|
72
|
+
#### Constants
|
|
73
|
+
|
|
74
|
+
A `Shape` cell holds the constant's declared type.
|
|
75
|
+
|
|
76
|
+
| Constant | Kind | Shape | Summary |
|
|
77
|
+
| -------------------------------------- | ----- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
78
|
+
| `BROWSER_DEFAULT_TIMEOUT_MS` | const | `number` | Sets the default timeout for browser connection, requests, and navigation, `30_000` milliseconds. |
|
|
79
|
+
| `BROWSER_WAIT_POLL_INTERVAL_MS` | const | `number` | Sets the poll interval while waiting for a selector to appear, `100` milliseconds. |
|
|
80
|
+
| `BROWSER_DEFAULT_VIEWPORT_WIDTH` | const | `number` | Sets the default viewport width, `1280` pixels. |
|
|
81
|
+
| `BROWSER_DEFAULT_VIEWPORT_HEIGHT` | const | `number` | Sets the default viewport height, `720` pixels. |
|
|
82
|
+
| `BROWSER_CODEGEN_BINDING_NAME` | const | `string` | Names the CDP runtime binding the codegen recorder script calls into, `'__orkestrelBrowserCodegen'`. |
|
|
83
|
+
| `BROWSER_CODEGEN_SOURCE` | const | `string` | Holds the in-page recorder script injected through `Page.addScriptToEvaluateOnNewDocument` and `Runtime.evaluate`. |
|
|
84
|
+
| `BASE64_CHARS` | const | `string` | Holds the index-ordered base64 alphabet used to build `BASE64_LOOKUP`. |
|
|
85
|
+
| `BASE64_LOOKUP` | const | `Readonly<Record<string, number>>` | Maps each base64 character to its 6-bit value, derived from `BASE64_CHARS`. |
|
|
86
|
+
| `BROWSER_RESULT_LIMIT` | const | `number` | Caps the serialized-character length for an `evaluate()`/`content()` result at `2_500_000`, enforced in-page before the result is returned to CDP. |
|
|
87
|
+
| `BROWSER_RESULT_LIMIT_SENTINEL_PREFIX` | const | `string` | Names the distinctive prefix for the in-page result-limit sentinel error, `'[[ORKESTREL_BROWSER_RESULT_LIMIT]]'`, immediately followed by the serialized length. |
|
|
88
|
+
| `BROWSER_RESULT_LIMIT_PATTERN` | const | `RegExp` | Matches the in-page result-limit sentinel error message, anchored immediately after the `Error:` (optionally `Uncaught Error:`) prefix Chromium prepends to a thrown error's description, `/^(?:Uncaught )?Error: \[\[ORKESTREL_BROWSER_RESULT_LIMIT\]\](\d+)/`. |
|
|
89
|
+
| `BROWSER_STOP_LOADING_TIMEOUT_MS` | const | `number` | Bounds the best-effort `Page.stopLoading` call issued after a failed `navigate()` at `1_000` milliseconds. |
|
|
90
|
+
| `BROWSER_FRAME_WORLD_NAME` | const | `string` | Names the isolated world used for iframe evaluation, `'__orkestrelBrowserFrame'`. |
|
|
91
|
+
| `BROWSER_SNAPSHOT_NODE_LIMIT` | const | `number` | Sets the default maximum node count accepted from a decoded CDP DOM snapshot, `100_000`. |
|
|
92
|
+
|
|
93
|
+
#### Errors
|
|
94
|
+
|
|
95
|
+
| Error | Kind | Signature | Summary |
|
|
96
|
+
| ------------------------- | ----- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
97
|
+
| `BrowserError` | class | `extends Error` | Represents the base error for all browser automation operations, carrying the code `BROWSER_ERROR` and a `context` record. |
|
|
98
|
+
| `BrowserSelectorError` | class | `extends BrowserError` | Reports that a selector-based lookup or wait timed out without the element appearing, under the code `BROWSER_SELECTOR_ERROR`. |
|
|
99
|
+
| `CDPError` | class | `extends BrowserError` | Reports that a CDP request received an error response from the remote endpoint, under the code `BROWSER_CDP_ERROR`, with the `method`, the CDP `code`, the `message`, and any `data` in its context. |
|
|
100
|
+
| `CDPConnectionError` | class | `extends BrowserError` | Reports that a CDP request could not be sent or completed because the client was not in a connectable state — not connected, closed while connecting, or the connection dropped mid-request — under the code `BROWSER_CDP_CONNECTION_ERROR`. |
|
|
101
|
+
| `CDPTimeoutError` | class | `extends BrowserError` | Reports that a pending CDP request was not answered within its timeout window, under the code `BROWSER_CDP_TIMEOUT_ERROR`. |
|
|
102
|
+
| `BrowserResultLimitError` | class | `extends BrowserError` | Reports that an `evaluate()`/`content()` result exceeded `BROWSER_RESULT_LIMIT` and was rejected in-page before it could overflow the CDP transport frame, under the code `BROWSER_RESULT_LIMIT_ERROR`. |
|
|
103
|
+
|
|
104
|
+
In a guard table a `Shape` cell holds the type the guard narrows to.
|
|
105
|
+
|
|
106
|
+
| Guard | Kind | Shape | Summary |
|
|
107
|
+
| --------------------------- | -------- | ------------------------- | -------------------------------------------------------- |
|
|
108
|
+
| `isBrowserError` | function | `BrowserError` | Narrows an unknown value to a `BrowserError`. |
|
|
109
|
+
| `isBrowserSelectorError` | function | `BrowserSelectorError` | Narrows an unknown value to a `BrowserSelectorError`. |
|
|
110
|
+
| `isCDPError` | function | `CDPError` | Narrows an unknown value to a `CDPError`. |
|
|
111
|
+
| `isCDPConnectionError` | function | `CDPConnectionError` | Narrows an unknown value to a `CDPConnectionError`. |
|
|
112
|
+
| `isCDPTimeoutError` | function | `CDPTimeoutError` | Narrows an unknown value to a `CDPTimeoutError`. |
|
|
113
|
+
| `isBrowserResultLimitError` | function | `BrowserResultLimitError` | Narrows an unknown value to a `BrowserResultLimitError`. |
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
try {
|
|
117
|
+
await page.wait('#missing')
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (isBrowserSelectorError(error)) log(error.code)
|
|
120
|
+
else if (isCDPError(error)) log(error.code, error.context)
|
|
121
|
+
else if (isCDPConnectionError(error)) log(error.code)
|
|
122
|
+
else if (isCDPTimeoutError(error)) log(error.code)
|
|
123
|
+
else if (isBrowserResultLimitError(error)) log(error.code, error.context)
|
|
124
|
+
else if (isBrowserError(error)) log(error.code)
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Helpers
|
|
129
|
+
|
|
130
|
+
| API | Kind | Summary |
|
|
131
|
+
| ---------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `decodeBase64` | function | Decodes a base64-encoded string into raw bytes. |
|
|
133
|
+
| `compileGuardedEvaluateExpression` | function | Compiles a `Runtime.evaluate` expression so the in-page code stringifies its own result and throws a recognizable sentinel error before an oversized result would overflow the CDP transport frame. |
|
|
134
|
+
| `normalizeCodegenActions` | function | Normalizes recorded codegen actions, collapsing consecutive `fill` actions on the same selector into the latest value. |
|
|
135
|
+
| `parseCodegenActionPayload` | function | Coerces a codegen binding payload string to a `BrowserCodegenAction`, or `undefined` off-shape. |
|
|
136
|
+
| `parseCodegenNavigateAction` | function | Coerces a `Page.frameNavigated` CDP event to a `navigate` codegen action, or `undefined` off-shape and for every frame but the top-level one. |
|
|
137
|
+
| `compileCodegenScript` | function | Compiles recorded codegen actions into a replayable JavaScript or TypeScript script. |
|
|
138
|
+
| `readEvaluationResult` | function | Decodes one CDP `Runtime.evaluate` result, throwing a `BrowserError` on a failed evaluation and a `BrowserResultLimitError` past the guarded result size. |
|
|
139
|
+
| `requireBrowserString` | function | Requires an evaluated browser value to be a string. |
|
|
140
|
+
| `readBrowserFrames` | function | Decodes a flattened CDP `Page.getFrameTree` result into depth-first frame metadata, skipping every off-shape frame. |
|
|
141
|
+
| `compileAttachedWaitExpression` | function | Compiles an in-page wait for an attached selector. |
|
|
142
|
+
| `compileDetachedWaitExpression` | function | Compiles an in-page wait for a detached selector. |
|
|
143
|
+
| `compileVisibleWaitExpression` | function | Compiles an in-page wait for a visible selector. |
|
|
144
|
+
| `compileHiddenWaitExpression` | function | Compiles an in-page wait for a hidden selector. |
|
|
145
|
+
| `compileClickExpression` | function | Compiles a strict, visibility-checked click expression. |
|
|
146
|
+
| `compileFillExpression` | function | Compiles a strict, editable fill expression. |
|
|
147
|
+
| `compileSelectExpression` | function | Compiles a strict select expression. |
|
|
148
|
+
| `parseNumberArray` | function | Coerces an unknown value to an all-number array, or `undefined` off-shape. |
|
|
149
|
+
| `parseSnapshotString` | function | Coerces one CDP snapshot string-table index to its string, or `undefined` off-shape. |
|
|
150
|
+
| `readRareStringData` | function | Decodes CDP snapshot sparse string data into a node-index map, skipping every off-shape entry. |
|
|
151
|
+
| `readRareBooleanData` | function | Decodes CDP snapshot sparse boolean data into a set of node indexes, skipping every off-shape entry. |
|
|
152
|
+
| `readRareIntegerData` | function | Decodes CDP snapshot sparse integer data into a node-index map, skipping every off-shape entry. |
|
|
153
|
+
| `parseBrowserRect` | function | Coerces a four-number CSS-pixel rectangle to a `BrowserRect`, or `undefined` off-shape. |
|
|
154
|
+
| `readBrowserAttributes` | function | Decodes flattened CDP node attributes into a frozen record, skipping every off-shape pair. |
|
|
155
|
+
| `readBrowserSnapshot` | function | Decodes a CDP `DOMSnapshot.captureSnapshot` result into a serializable `BrowserSnapshotInput`, throwing a `BrowserError` off-shape and a `BrowserResultLimitError` past the configured node limit. |
|
|
156
|
+
| `isBrowserNodeQuery` | function | Tests whether a browser-node matcher is a declarative query rather than a predicate. |
|
|
157
|
+
| `matchesBrowserNode` | function | Tests a captured node against a declarative query. |
|
|
158
|
+
| `isBrowserNodeVisible` | function | Tests whether a captured node has a non-empty rendered layout box. |
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import {
|
|
162
|
+
compileGuardedEvaluateExpression,
|
|
163
|
+
normalizeCodegenActions,
|
|
164
|
+
parseCodegenActionPayload,
|
|
165
|
+
parseCodegenNavigateAction,
|
|
166
|
+
compileCodegenScript,
|
|
167
|
+
readEvaluationResult,
|
|
168
|
+
requireBrowserString,
|
|
169
|
+
readBrowserFrames,
|
|
170
|
+
compileAttachedWaitExpression,
|
|
171
|
+
compileDetachedWaitExpression,
|
|
172
|
+
compileVisibleWaitExpression,
|
|
173
|
+
compileHiddenWaitExpression,
|
|
174
|
+
compileClickExpression,
|
|
175
|
+
compileFillExpression,
|
|
176
|
+
compileSelectExpression,
|
|
177
|
+
parseNumberArray,
|
|
178
|
+
parseSnapshotString,
|
|
179
|
+
readRareStringData,
|
|
180
|
+
readRareBooleanData,
|
|
181
|
+
readRareIntegerData,
|
|
182
|
+
parseBrowserRect,
|
|
183
|
+
readBrowserAttributes,
|
|
184
|
+
readBrowserSnapshot,
|
|
185
|
+
matchesBrowserNode,
|
|
186
|
+
isBrowserNodeVisible,
|
|
187
|
+
} from '@orkestrel/browser'
|
|
188
|
+
|
|
189
|
+
const guarded = compileGuardedEvaluateExpression('document.title', 3_000_000) // wrapped expression string
|
|
190
|
+
const actions = normalizeCodegenActions(rawActions)
|
|
191
|
+
const action = parseCodegenActionPayload(payload) // BrowserCodegenAction | undefined
|
|
192
|
+
const navigate = parseCodegenNavigateAction(frameNavigatedParams)
|
|
193
|
+
const script = compileCodegenScript(actions, { language: 'typescript' })
|
|
194
|
+
const value = readEvaluationResult(runtimeResult)
|
|
195
|
+
const title = requireBrowserString(value, 'Title')
|
|
196
|
+
const frames = readBrowserFrames(frameTreeResult)
|
|
197
|
+
const attached = compileAttachedWaitExpression('#result', true, 30_000)
|
|
198
|
+
const detached = compileDetachedWaitExpression('.spinner', true, 30_000)
|
|
199
|
+
const visible = compileVisibleWaitExpression('#result', true, 30_000)
|
|
200
|
+
const hidden = compileHiddenWaitExpression('.spinner', true, 30_000)
|
|
201
|
+
const click = compileClickExpression('#submit', true)
|
|
202
|
+
const fill = compileFillExpression('#query', 'browser', true)
|
|
203
|
+
const select = compileSelectExpression('#region', ['us'], true)
|
|
204
|
+
const numbers = parseNumberArray([1, 2, 3])
|
|
205
|
+
const text = parseSnapshotString(snapshotStrings, 1)
|
|
206
|
+
const rareStrings = readRareStringData(rawRareStrings, snapshotStrings)
|
|
207
|
+
const rareBooleans = readRareBooleanData(rawRareBooleans)
|
|
208
|
+
const rareIntegers = readRareIntegerData(rawRareIntegers)
|
|
209
|
+
const rect = parseBrowserRect([0, 0, 100, 40])
|
|
210
|
+
const attributes = readBrowserAttributes(rawAttributes, snapshotStrings)
|
|
211
|
+
const decoded = readBrowserSnapshot(rawSnapshot, ['display']) // BrowserSnapshotInput
|
|
212
|
+
const node = decoded.documents[0].nodes[0]
|
|
213
|
+
const id = node.attributes['id']
|
|
214
|
+
const article = matchesBrowserNode(node, { name: 'article', visible: true })
|
|
215
|
+
const rendered = isBrowserNodeVisible(node)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Navigating decoded data is the `BrowserSnapshot` entity's job, not a helper
|
|
219
|
+
family's — see [`BrowserSnapshotInterface`](#browsersnapshotinterface) later.
|
|
220
|
+
|
|
221
|
+
#### Types
|
|
222
|
+
|
|
223
|
+
A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional member and `plus` introducing its call-signature members, and a type alias's own type literal with a union's arms escaped as `\|`. An extended interface's name comes before `plus`, with the members it adds after.
|
|
224
|
+
|
|
225
|
+
| Type | Kind | Shape | Summary |
|
|
226
|
+
| ----------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
227
|
+
| `CDPTransportEventMap` | type | `{ message, close, error }` | Maps the events emitted by a `CDPTransportInterface` — the raw text pipe a `CDPClientInterface` sends and receives JSON-RPC frames over. |
|
|
228
|
+
| `CDPTransportInterface` | interface | `{ emitter } plus start, send, close` | Represents the text pipe a `CDPClient` sends and receives JSON-RPC frames over. |
|
|
229
|
+
| `CDPClientOptions` | interface | `{ transport, timeout?, on?, error? }` | Describes the options for creating a `CDPClient` instance. |
|
|
230
|
+
| `CDPHandler` | type | `(params: Readonly<Record<string, unknown>>) => void` | Receives a subscribed CDP event with its params record. |
|
|
231
|
+
| `CDPClientEventMap` | type | `{ connect, close, drop, error }` | Maps the events a `CDPClientInterface` emits. |
|
|
232
|
+
| `CDPTarget` | interface | `{ id, category, title, url }` | Represents one entry of the CDP `Target.getTargets` result. |
|
|
233
|
+
| `CDPClientInterface` | interface | `{ emitter, connected } plus connect, reconnect, send, subscribe, unsubscribe, close` | Provides a lightweight Chrome DevTools Protocol client over a `CDPTransportInterface`. |
|
|
234
|
+
| `CDPSendOptions` | interface | `{ session?, timeout? }` | Describes the options for one CDP method call. |
|
|
235
|
+
| `BrowserWriterInterface` | interface | `{} plus write` | Provides a pluggable sink for persisting captured browser bytes to a path. |
|
|
236
|
+
| `BrowserViewport` | interface | `{ width, height, scale?, mobile?, touch?, landscape? }` | Describes the viewport dimensions for a browser page. |
|
|
237
|
+
| `BrowserWaitUntil` | type | `'commit' \| 'load' \| 'domcontentloaded'` | Names the page load condition for navigation — the CDP load event awaited by `navigate()`. |
|
|
238
|
+
| `BrowserPageOptions` | interface | `{ on?, error?, url?, viewport?, timeout? }` | Describes the options for creating a `BrowserPage` instance. |
|
|
239
|
+
| `BrowserNavigationOptions` | interface | `{ condition?, timeout? }` | Describes the options for page navigation. |
|
|
240
|
+
| `BrowserActionOptions` | interface | `{ timeout?, strict?, force?, trial? }` | Describes the options for element interaction (click, fill, select, wait). |
|
|
241
|
+
| `BrowserWaitState` | type | `'attached' \| 'detached' \| 'visible' \| 'hidden'` | Names an element state a frame or page can wait for. |
|
|
242
|
+
| `BrowserWaitOptions` | interface | `BrowserActionOptions plus { state? }` | Describes the options for waiting on an element. |
|
|
243
|
+
| `BrowserScreenshotOptions` | interface | `{ path?, full?, format?, quality?, clip?, transparent?, animations?, caret?, scale?, mask?, color? }` | Describes the options for taking a page screenshot. |
|
|
244
|
+
| `BrowserContentResult` | interface | `{ url, title, html, text }` | Describes the result of page content extraction. |
|
|
245
|
+
| `BrowserScreenshotResult` | interface | `{ bytes, path }` | Describes the result of a page screenshot. |
|
|
246
|
+
| `BrowserCodegenAction` | type | `{ action: 'navigate', url } \| { action: 'click', selector } \| { action: 'fill', selector, value } \| { action: 'select', selector, values }` | Represents one recorded browser action captured during a codegen session. |
|
|
247
|
+
| `BrowserCodegenEventMap` | type | `{ start, stop, action, clear }` | Maps the events a `BrowserCodegenInterface` emits. |
|
|
248
|
+
| `BrowserCodegenOptions` | interface | `{ on?, error? }` | Describes the options for creating a `BrowserCodegen` recorder. |
|
|
249
|
+
| `BrowserCodegenLanguage` | type | `'javascript' \| 'typescript'` | Names the target language for a compiled codegen script. |
|
|
250
|
+
| `BrowserCodegenScriptOptions` | interface | `{ language? }` | Describes the options for compiling recorded actions into a script. |
|
|
251
|
+
| `BrowserCodegenInterface` | interface | `{ emitter, started } plus start, stop, actions, script, clear, destroy` | Records page interactions (navigation, click, fill, select) as a session runs, for later compilation into a replayable script. |
|
|
252
|
+
| `BrowserSessionFunction` | type | `(frame: string) => Promise<string>` | Resolves the current CDP session for a frame id. |
|
|
253
|
+
| `BrowserFrameInfo` | interface | `{ id, parent, name, url }` | Describes serializable frame metadata decoded from CDP `Page.getFrameTree`. |
|
|
254
|
+
| `BrowserFrameInterface` | interface | `{ id, parent, name, url, selectors, keyboard, mouse, touch } plus title, content, article, click, fill, select, evaluate, handle, wait, send, subscribe, unsubscribe, save, assert, update` | Provides the operations shared by a top-level page and an iframe document. |
|
|
255
|
+
| `BrowserSendOptions` | interface | `{ timeout? }` | Describes the options for one raw CDP method call issued in a frame's target session. |
|
|
256
|
+
| `BrowserRect` | type | `readonly [x: number, y: number, width: number, height: number]` | Represents a rectangle in CSS pixels: x, y, width, height. |
|
|
257
|
+
| `BrowserLayout` | interface | `{ bounds, styles, text, paint, offset, scroll, client }` | Describes layout data associated with one captured DOM node. |
|
|
258
|
+
| `BrowserNode` | interface | `{ document, frame, index, id, parent, category, name, value, attributes, text, input, checked, selected, clickable, shadow, content, pseudo, source, origin, layout }` | Represents one serializable DOM node decoded from a CDP DOM snapshot. |
|
|
259
|
+
| `BrowserDocument` | interface | `{ index, frame, url, title, nodes, scroll, width, height }` | Represents one document captured in a CDP DOM snapshot. |
|
|
260
|
+
| `BrowserSnapshotInput` | interface | `{ documents, styles }` | Describes the serializable input for a navigable browser snapshot — the form a `BrowserSnapshot` is built from and serializes back to. |
|
|
261
|
+
| `BrowserWalkOrder` | type | `'depth' \| 'breadth'` | Names the structural ordering for a browser snapshot walk. |
|
|
262
|
+
| `BrowserWalkOptions` | interface | `{ root?, order? }` | Describes the options for walking a browser snapshot. |
|
|
263
|
+
| `BrowserSiblingRelation` | type | `'preceding' \| 'following'` | Names a structural sibling relationship relative to a browser node. |
|
|
264
|
+
| `BrowserSnapshotInterface` | interface | `BrowserSnapshotInput plus walk, descendants, document, children, parent, siblings, ancestors, common, distance, find, filter, closest, path` | Represents a navigable, serializable snapshot of every document attached to a page, extending `BrowserSnapshotInput` with walking, structural relationships, search, and path derivation over plain `BrowserNode` values. |
|
|
265
|
+
| `BrowserSnapshotOptions` | interface | `{ styles?, paint?, rects?, limit? }` | Describes the options configuring capture through `BrowserPageInterface` `snapshot()`. The snapshot entity's creation input is `BrowserSnapshotInput`. |
|
|
266
|
+
| `BrowserNodePredicate` | type | `(node: BrowserNode) => boolean` | Names the predicate form accepted by `BrowserSnapshotInterface` find, filter, and closest methods. |
|
|
267
|
+
| `BrowserNodeQuery` | interface | `{ name?, text?, attributes?, frame?, visible?, clickable? }` | Describes a declarative browser-node matcher used by `matchesBrowserNode`. |
|
|
268
|
+
| `BrowserPageInterface` | interface | `BrowserFrameInterface plus { emitter, network, navigation, scripts, accessibility, diagnostics, clock, opener, target, closed } plus navigate, reload, back, forward, screenshot, pdf, frame, frames, snapshot, codegen, destroy, close` | Abstracts a single top-level browser page, extending `BrowserFrameInterface` with navigation, screenshots, frame discovery, DOM snapshots, codegen, and target teardown. |
|
|
269
|
+
| `BrowserContextInterface` | interface | `{ emitter, id, cookies, permissions, storage, emulation } plus page, pages, create, sync, destroy, close` | Represents an isolated browser session over a CDP browser context. |
|
|
270
|
+
|
|
271
|
+
### Server
|
|
272
|
+
|
|
273
|
+
Server-side connection lifecycle — discover an already-running browser through
|
|
274
|
+
CDP, connect to it, or launch a fresh Chromium-family process:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { createBrowser } from '@orkestrel/browser/server'
|
|
278
|
+
|
|
279
|
+
const browser = createBrowser({ cdp: { port: 9222 } })
|
|
280
|
+
const discovery = await browser.discover() // passive probe, no side effects
|
|
281
|
+
await browser.connect() // reuses discovery.endpoint if found, else launches
|
|
282
|
+
const ctx = browser.context() // the default context (created lazily on `create()`, or eagerly if connect() discovers existing pages)
|
|
283
|
+
await browser.destroy() // closes the process and releases resources
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### Factories
|
|
287
|
+
|
|
288
|
+
| API | Kind | Summary |
|
|
289
|
+
| --------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
|
|
290
|
+
| `createBrowser` | function | Creates a raw-CDP `BrowserInterface` façade with discovery, connection, and lifecycle management. |
|
|
291
|
+
| `createCDPTransport` | function | Creates a Node `WebSocket`-backed `CDPTransportInterface` for the given CDP debugger URL. |
|
|
292
|
+
| `createBrowserWriter` | function | Creates a filesystem-backed `BrowserWriterInterface` that persists bytes through `node:fs/promises`. |
|
|
293
|
+
|
|
294
|
+
#### Classes
|
|
295
|
+
|
|
296
|
+
| API | Kind | Summary |
|
|
297
|
+
| ----------------------- | ----- | ----------------------------------------------------------------------------- |
|
|
298
|
+
| `Browser` | class | Discovers, launches, connects to, and owns Chromium-family browser sessions. |
|
|
299
|
+
| `WebSocketCDPTransport` | class | Provides a raw CDP text transport backed by `@orkestrel/websocket`. |
|
|
300
|
+
| `FileBrowserWriter` | class | Persists captured browser bytes to the filesystem through `node:fs/promises`. |
|
|
301
|
+
|
|
302
|
+
#### Constants
|
|
303
|
+
|
|
304
|
+
A `Shape` cell holds the constant's declared type.
|
|
305
|
+
|
|
306
|
+
| Constant | Kind | Shape | Summary |
|
|
307
|
+
| --------------------------------- | ----- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
308
|
+
| `BROWSER_DEFAULT_CDP_PORT` | const | `number` | Sets the default CDP port probed for an existing browser and used for launches, `9222`. |
|
|
309
|
+
| `BROWSER_DEFAULT_HOST` | const | `string` | Sets the default host probed for an existing browser and used for launches, `'127.0.0.1'`, which avoids `localhost` resolving to `::1` when Chromium binds `127.0.0.1`. |
|
|
310
|
+
| `BROWSER_CDP_PROTOCOL` | const | `string` | Names the protocol prefix for CDP discovery requests, `'http'`. |
|
|
311
|
+
| `BROWSER_CDP_VERSION_PATH` | const | `string` | Names the path appended to the CDP host to fetch version metadata, `'/json/version'`, which is where endpoint discovery reads. |
|
|
312
|
+
| `BROWSER_CDP_LIST_PATH` | const | `string` | Names the path appended to the CDP host to list open targets — pages, workers, and every other target category Chromium reports — `'/json/list'`. |
|
|
313
|
+
| `BROWSER_LAUNCH_ARGS` | const | `readonly string[]` | Lists the flags always passed to a launched browser process, alongside the caller's own. |
|
|
314
|
+
| `BROWSER_HEADLESS_ARG` | const | `string` | Names the flag that enables headless mode on a launched browser process, `'--headless=new'`. |
|
|
315
|
+
| `BROWSER_PROFILE_PREFIX` | const | `string` | Names the prefix for isolated browser profiles created beneath the operating-system temp directory, `'orkestrel-browser-'`. |
|
|
316
|
+
| `BROWSER_KILL_GRACE_MS` | const | `number` | Bounds each launched-process exit window during TERM-to-KILL teardown at `3_000` milliseconds. |
|
|
317
|
+
| `BROWSER_PORT_PROBE_TIMEOUT_MS` | const | `number` | Bounds the `discover: false` port-occupancy probe before launching at `200` milliseconds, which is short because the probe only needs to detect an already-listening CDP endpoint rather than perform full discovery. |
|
|
318
|
+
| `BROWSER_TRANSPORT_LOSS_DEFER_MS` | const | `number` | Defers once for `50` milliseconds when a transport loss is observed on an owned process, giving a near-simultaneous process-exit event, which libuv may reap slightly later than the socket close, first say over the diagnosis. |
|
|
319
|
+
| `BROWSER_PROCESS_EXIT_CAUSE` | const | `string` | Names the machine-readable error-context cause for an owned browser process exiting, `'process-exit'`. |
|
|
320
|
+
| `BROWSER_TRANSPORT_LOSS_CAUSE` | const | `string` | Names the machine-readable error-context cause for a CDP transport disconnecting while its browser remains alive, `'transport-loss'`. |
|
|
321
|
+
| `BROWSER_ENV_PATH_KEYS` | const | `readonly string[]` | Lists the environment variables checked, in order, for an explicit browser executable path override: `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH`. |
|
|
322
|
+
| `BROWSER_EXECUTABLE_PATHS` | const | `Readonly<Record<string, readonly string[]>>` | Lists the well-known Chrome/Chromium/Edge executable paths with no platform-specific root, keyed by `process.platform`, leaving `win32` empty because its roots come from `BROWSER_WINDOWS_SUFFIXES`. |
|
|
323
|
+
| `BROWSER_WINDOWS_SUFFIXES` | const | `readonly string[]` | Lists the Windows install-root-relative suffixes for Chrome/Edge/Chromium, joined against each candidate root (`PROGRAMFILES`, `PROGRAMFILES(X86)`, `LOCALAPPDATA`). |
|
|
324
|
+
| `BROWSER_WINDOWS_ROOT_FALLBACKS` | const | `Readonly<Record<string, string>>` | Lists the fallback Windows install roots used when `PROGRAMFILES`, `PROGRAMFILES(X86)`, or `LOCALAPPDATA` is absent. |
|
|
325
|
+
| `BROWSER_EXECUTABLE_NAMES` | const | `readonly string[]` | Lists the command names probed on PATH when no well-known executable path exists. |
|
|
326
|
+
| `BROWSER_STORE_ENV_KEY` | const | `string` | Names the environment variable that carries an additional Playwright browser store base directory, `'PLAYWRIGHT_BROWSERS_PATH'`. |
|
|
327
|
+
| `BROWSER_STORE_DEFAULT_DIRS` | const | `readonly string[]` | Lists the well-known Playwright browser store base directories checked in addition to `PLAYWRIGHT_BROWSERS_PATH`, starting with `/opt/pw-browsers`. |
|
|
328
|
+
| `BROWSER_STORE_CACHE_DIRS` | const | `Readonly<Record<string, string>>` | Names the per-OS default Playwright browser cache directory, relative to the home directory (win32 uses `LOCALAPPDATA` directly). |
|
|
329
|
+
| `BROWSER_STORE_LINK_NAME` | const | `string` | Names the top-level Chromium symlink or binary Playwright maintains inside a browser store base, `'chromium'`. |
|
|
330
|
+
| `BROWSER_STORE_GLOBS` | const | `Readonly<Record<string, string>>` | Names the glob pattern (relative to a store base) matching a versioned Chromium binary, keyed by `process.platform`. |
|
|
331
|
+
| `BROWSER_ENGINE_HINTS` | const | `Readonly<Record<BrowserEngine, readonly string[]>>` | Lists the case-insensitive substrings identifying an executable path/name's browser engine, checked by `parseBrowserEngine` in the order `edge` → `chromium` → `chrome`. |
|
|
332
|
+
|
|
333
|
+
#### Errors
|
|
334
|
+
|
|
335
|
+
| Error | Kind | Signature | Summary |
|
|
336
|
+
| -------------------------- | ----- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
337
|
+
| `BrowserConnectionError` | class | `extends BrowserError` | Reports that a CDP connection, discovery, or launch attempt failed, under the code `BROWSER_CONNECTION_ERROR`. |
|
|
338
|
+
| `BrowserNotConnectedError` | class | `extends BrowserError` | Reports that an operation requiring an active connection was attempted while disconnected, under the code `BROWSER_NOT_CONNECTED_ERROR`. |
|
|
339
|
+
| `BrowserDestroyedError` | class | `extends BrowserError` | Reports that an operation was attempted after the browser wrapper was destroyed, under the code `BROWSER_DESTROYED_ERROR`. |
|
|
340
|
+
|
|
341
|
+
In a guard table a `Shape` cell holds the type the guard narrows to.
|
|
342
|
+
|
|
343
|
+
| Guard | Kind | Shape | Summary |
|
|
344
|
+
| ---------------------------- | -------- | -------------------------- | --------------------------------------------------------- |
|
|
345
|
+
| `isBrowserConnectionError` | function | `BrowserConnectionError` | Narrows an unknown value to a `BrowserConnectionError`. |
|
|
346
|
+
| `isBrowserNotConnectedError` | function | `BrowserNotConnectedError` | Narrows an unknown value to a `BrowserNotConnectedError`. |
|
|
347
|
+
| `isBrowserDestroyedError` | function | `BrowserDestroyedError` | Narrows an unknown value to a `BrowserDestroyedError`. |
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
try {
|
|
351
|
+
await browser.connect()
|
|
352
|
+
} catch (error) {
|
|
353
|
+
if (isBrowserConnectionError(error)) log(error.code)
|
|
354
|
+
else if (isBrowserNotConnectedError(error)) log(error.code)
|
|
355
|
+
else if (isBrowserDestroyedError(error)) log(error.code)
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### Helpers
|
|
360
|
+
|
|
361
|
+
| API | Kind | Summary |
|
|
362
|
+
| ------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
363
|
+
| `findSystemBrowsers` | function | Enumerates every Chrome/Chromium/Edge executable discoverable on this machine, deduplicated by normalized absolute path. |
|
|
364
|
+
| `findSystemBrowser` | function | Locates a Chrome/Chromium/Edge executable on this machine — the first entry of `findSystemBrowsers`. |
|
|
365
|
+
| `parseBrowserEngine` | function | Classifies an executable path/name into a `BrowserEngine` by case-insensitive hint, checked in the order edge → chromium → chrome. |
|
|
366
|
+
| `normalizeExecutablePath` | function | Normalizes an executable path for cross-source deduplication (case-insensitive on Windows). |
|
|
367
|
+
| `browserToEngine` | function | Classifies a `/json/version` `Browser` string into a `BrowserEngine` (`Edg/` → edge, `Chrome/` → chrome, else chromium). |
|
|
368
|
+
| `createBrowserProfile` | function | Resolves a persistent caller profile or creates an isolated temporary one. |
|
|
369
|
+
| `removeBrowserProfile` | function | Removes a library-owned isolated browser profile. |
|
|
370
|
+
| `findEnvOverrides` | function | Checks the env-override keys (`PLAYWRIGHT_EXECUTABLE_PATH`, `CHROME_PATH`) in order and returns every one that exists. |
|
|
371
|
+
| `buildInstallPaths` | function | Builds the default well-known install-path candidates for a platform, deriving Windows roots from env vars. |
|
|
372
|
+
| `buildWindowsRoots` | function | Derives Windows install roots from env vars, falling back to well-known literals when absent. |
|
|
373
|
+
| `findInstallPaths` | function | Returns every candidate path that exists on disk, in the given order. |
|
|
374
|
+
| `probePathNames` | function | Probes PATH (`which`/`where`) for every resolvable command name, in the given order. |
|
|
375
|
+
| `readFirstLine` | function | Returns the first non-empty line of a command's output, without its surrounding whitespace. |
|
|
376
|
+
| `buildStoreBases` | function | Builds the default Playwright browser store base directories to search for a managed Chromium. |
|
|
377
|
+
| `findStorePaths` | function | Searches one store base for the top-level `chromium` link and every `chromium-*` install, highest revision first. |
|
|
378
|
+
| `launchBrowserProcess` | function | Launches a browser process with raw-CDP debugging flags. |
|
|
379
|
+
| `waitForCDPReady` | function | Polls a browser's CDP version endpoint until it responds or the timeout elapses. |
|
|
380
|
+
| `fetchCDPTargets` | function | Fetches the current CDP target list from a browser's `/json/list` endpoint, as a `Result` carrying either the targets or a coded `BrowserConnectionError`. |
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
import {
|
|
384
|
+
createCDPTransport,
|
|
385
|
+
createBrowserWriter,
|
|
386
|
+
findSystemBrowsers,
|
|
387
|
+
findSystemBrowser,
|
|
388
|
+
parseBrowserEngine,
|
|
389
|
+
normalizeExecutablePath,
|
|
390
|
+
browserToEngine,
|
|
391
|
+
createBrowserProfile,
|
|
392
|
+
removeBrowserProfile,
|
|
393
|
+
findEnvOverrides,
|
|
394
|
+
buildInstallPaths,
|
|
395
|
+
buildWindowsRoots,
|
|
396
|
+
findInstallPaths,
|
|
397
|
+
probePathNames,
|
|
398
|
+
readFirstLine,
|
|
399
|
+
buildStoreBases,
|
|
400
|
+
findStorePaths,
|
|
401
|
+
launchBrowserProcess,
|
|
402
|
+
waitForCDPReady,
|
|
403
|
+
fetchCDPTargets,
|
|
404
|
+
} from '@orkestrel/browser/server'
|
|
405
|
+
|
|
406
|
+
const transport = createCDPTransport({ url: 'ws://localhost:9222/devtools/browser/abc' })
|
|
407
|
+
const writer = createBrowserWriter()
|
|
408
|
+
|
|
409
|
+
const browsers = findSystemBrowsers() // readonly SystemBrowser[]
|
|
410
|
+
const found = findSystemBrowser() // SystemBrowser | undefined — first entry of findSystemBrowsers()
|
|
411
|
+
// findSystemBrowsers({ env: {}, paths: [], names: [], stores: [], engine: 'edge' }) — override any candidate source, narrow by engine
|
|
412
|
+
|
|
413
|
+
parseBrowserEngine('/usr/bin/msedge') // 'edge'
|
|
414
|
+
normalizeExecutablePath('/usr/bin/Chrome', process.platform) // string — case-folded on win32 only
|
|
415
|
+
browserToEngine('HeadlessChrome/120.0') // 'chrome' — classifies a /json/version Browser string
|
|
416
|
+
const profile = await createBrowserProfile()
|
|
417
|
+
await removeBrowserProfile(profile)
|
|
418
|
+
|
|
419
|
+
// findSystemBrowsers's internal resolution steps, exposed for composition/testing:
|
|
420
|
+
const env = process.env
|
|
421
|
+
findEnvOverrides(env) // readonly string[] — every matching override that exists
|
|
422
|
+
const roots = buildWindowsRoots(env) // readonly string[] — PROGRAMFILES / PROGRAMFILES(X86) / LOCALAPPDATA
|
|
423
|
+
buildInstallPaths('win32', env) // readonly string[] — well-known Chrome/Edge/Chromium paths
|
|
424
|
+
findInstallPaths(buildInstallPaths(process.platform, env)) // readonly string[]
|
|
425
|
+
probePathNames(['google-chrome', 'msedge'], process.platform) // readonly string[]
|
|
426
|
+
readFirstLine('C:\\bin\\chrome.exe\r\nC:\\other\\chrome.exe\r\n') // 'C:\\bin\\chrome.exe' — CRLF-safe
|
|
427
|
+
const stores = buildStoreBases(env, process.platform) // readonly string[]
|
|
428
|
+
for (const store of stores) findStorePaths(store, process.platform) // readonly string[]
|
|
429
|
+
if (found !== undefined) {
|
|
430
|
+
const child = launchBrowserProcess(found.executable, 9222, true)
|
|
431
|
+
const debuggerUrl = await waitForCDPReady(9222, 5000)
|
|
432
|
+
const targets = await fetchCDPTargets(9222, 5000) // Result<readonly CDPTarget[], BrowserError>
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### Types
|
|
437
|
+
|
|
438
|
+
A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional member and `plus` introducing its call-signature members, and a type alias's own type literal with a union's arms escaped as `\|`.
|
|
439
|
+
|
|
440
|
+
| Type | Kind | Shape | Summary |
|
|
441
|
+
| ------------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
442
|
+
| `BrowserEngine` | type | `'chromium' \| 'chrome' \| 'edge'` | Names a supported browser engine (raw CDP targets Chromium-family browsers only). |
|
|
443
|
+
| `BrowserConnection` | type | `'cdp' \| 'launch' \| 'persistent'` | Names how the browser connection was established. |
|
|
444
|
+
| `BrowserStatus` | type | `'idle' \| 'connecting' \| 'connected' \| 'disconnected' \| 'error'` | Names the lifecycle status of a browser wrapper. |
|
|
445
|
+
| `BrowserDiscoveryResult` | interface | `{ endpoint, browser }` | Describes the result of passive browser discovery. |
|
|
446
|
+
| `SystemBrowserOptions` | interface | `{ env?, paths?, names?, stores?, engine? }` | Describes the options overriding `findSystemBrowsers`'/`findSystemBrowser`'s candidate sources. |
|
|
447
|
+
| `SystemBrowser` | type | `{ executable, engine }` | Represents one discovered browser executable on this machine. |
|
|
448
|
+
| `BrowserProfileResult` | interface | `{ path, temporary }` | Describes the resolved browser profile directory used for a Chromium-family launch. |
|
|
449
|
+
| `BrowserCDPOptions` | interface | `{ port?, host?, endpoint?, discover? }` | Configures the CDP (Chrome DevTools Protocol) connection. |
|
|
450
|
+
| `BrowserEventMap` | type | `{ idle, discover, connect, disconnect, launch, page, context, error, destroy }` | Maps the events a `BrowserInterface` emits. |
|
|
451
|
+
| `BrowserOptions` | interface | `{ on?, error?, headless?, executable?, profile?, cdp?, timeout?, viewport?, signal?, args?, engine?, browsers? }` | Describes the options for creating a `Browser` instance. |
|
|
452
|
+
| `BrowserInterface` | interface | `{ emitter, engine, status, connection, owned, pid } plus discover, connect, adopt, disconnect, context, contexts, isolate, create, destroy, close` | Wraps a browser with discovery, connection management, and lifecycle control. |
|
|
453
|
+
| `WebSocketCDPTransportOptions` | interface | `{ on?, error?, url, timeout? }` | Describes the options for creating a `WebSocketCDPTransport` instance. |
|
|
454
|
+
|
|
455
|
+
### Extended Chromium automation surface
|
|
456
|
+
|
|
457
|
+
The focused CDP feature layer is grouped into small classes. Managers expose
|
|
458
|
+
single-word operations through `BrowserContextInterface` and
|
|
459
|
+
`BrowserPageInterface`; the helpers remain pure so protocol decoding,
|
|
460
|
+
validation, scraping, and compilation can be tested without a browser.
|
|
461
|
+
|
|
462
|
+
#### Extended constants
|
|
463
|
+
|
|
464
|
+
A `Shape` cell holds the constant's declared type.
|
|
465
|
+
|
|
466
|
+
| API | Kind | Shape | Summary |
|
|
467
|
+
| ------------------------------ | ----- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
468
|
+
| `BROWSER_HAR_CREATOR` | const | `{ name, version }` | Names the tool identity embedded in HAR 1.2 documents. |
|
|
469
|
+
| `BROWSER_KEY_MODIFIERS` | const | `Readonly<Record<string, number>>` | Maps a canonical modifier name to its CDP Input modifier bit value. |
|
|
470
|
+
| `BROWSER_MOUSE_BUTTON_MASKS` | const | `Readonly<Record<BrowserMouseButton, number>>` | Maps each public mouse button to its CDP Input pressed-button bit value. |
|
|
471
|
+
| `BROWSER_SCREENSHOT_ATTRIBUTE` | const | `string` | Names the attribute that tags temporary screenshot styles and masks. |
|
|
472
|
+
| `BROWSER_STABLE_FRAME_COUNT` | const | `number` | Sets the number of animation frames whose element bounds must agree before trusted input. |
|
|
473
|
+
| `BROWSER_TEST_ID_ATTRIBUTE` | const | `string` | Names the attribute the semantic test-id selector uses. |
|
|
474
|
+
| `BROWSER_VISIBILITY_SOURCE` | const | `string` | Holds the in-page visibility predicate source, over a `style` computed style and a `rect` bounding box already in scope at the interpolation site. |
|
|
475
|
+
|
|
476
|
+
#### Extended classes
|
|
477
|
+
|
|
478
|
+
| API | Kind | Summary |
|
|
479
|
+
| -------------------------- | ----- | --------------------------------------------------------------------------------------- |
|
|
480
|
+
| `BrowserAccessibility` | class | Captures Chromium Accessibility-domain snapshots for one page. |
|
|
481
|
+
| `BrowserClock` | class | Controls the Chromium virtual-time budget for deterministic page timers. |
|
|
482
|
+
| `BrowserCookieManager` | class | Performs cookie operations isolated to one browser context. |
|
|
483
|
+
| `BrowserCoverage` | class | Collects JavaScript precise coverage and CSS rule usage for one page target. |
|
|
484
|
+
| `BrowserDiagnostics` | class | Groups the tracing, coverage, performance, and profiler classes beneath one page. |
|
|
485
|
+
| `BrowserEmulationManager` | class | Applies rendering, identity, location, and network emulation for context pages. |
|
|
486
|
+
| `BrowserHARManager` | class | Records and replays HTTP archives over one page network manager. |
|
|
487
|
+
| `BrowserKeyboard` | class | Sends trusted keyboard input through Chromium's CDP Input domain. |
|
|
488
|
+
| `BrowserLocator` | class | Represents a reusable strict semantic locator over one frame. |
|
|
489
|
+
| `BrowserMouse` | class | Sends trusted mouse input through Chromium's CDP Input domain. |
|
|
490
|
+
| `BrowserNavigationManager` | class | Runs URL and page-predicate waits resilient to ordinary navigation events. |
|
|
491
|
+
| `BrowserNetworkManager` | class | Drives the page-scoped Network and Fetch domain lifecycle. |
|
|
492
|
+
| `BrowserPerformance` | class | Reads Performance-domain metrics for one frame. |
|
|
493
|
+
| `BrowserPermissionManager` | class | Applies permission overrides isolated to one browser context. |
|
|
494
|
+
| `BrowserProfiler` | class | Records sampled JavaScript CPU profiles over one frame's Profiler domain. |
|
|
495
|
+
| `BrowserScriptManager` | class | Installs new-document scripts and promise-based host functions for one page. |
|
|
496
|
+
| `BrowserSelectorManager` | class | Creates semantic locators for one frame. |
|
|
497
|
+
| `BrowserStorageManager` | class | Imports, exports, and clears cookie and web-storage state for one browser context. |
|
|
498
|
+
| `BrowserTouch` | class | Sends trusted touch input through Chromium's CDP Input domain. |
|
|
499
|
+
| `BrowserTracing` | class | Captures Chromium traces streamed through the IO domain. |
|
|
500
|
+
| `BrowserTransition` | class | Runs one asynchronous transition at a time, shared by every caller that joins it. |
|
|
501
|
+
| `BrowserWebSocket` | class | Represents an observable WebSocket connection reconstructed from Network-domain events. |
|
|
502
|
+
|
|
503
|
+
#### Extended helpers
|
|
504
|
+
|
|
505
|
+
| API | Kind | Summary |
|
|
506
|
+
| ---------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
507
|
+
| `browserHARHeadersToRecord` | function | Converts HAR name/value headers into a Fetch-domain header record. |
|
|
508
|
+
| `browserHeadersToProtocol` | function | Converts a header record to Fetch-domain name/value entries. |
|
|
509
|
+
| `browserPDFToParams` | function | Validates and compiles Page.printToPDF parameters. |
|
|
510
|
+
| `browserScreenshotToParams` | function | Validates and compiles basic Page.captureScreenshot parameters. |
|
|
511
|
+
| `bytesToText` | function | Decodes UTF-8 bytes as text. |
|
|
512
|
+
| `compileActionabilityFunction` | function | Compiles the element-side actionability pass used before trusted input. |
|
|
513
|
+
| `compileAttachedLocatorWaitExpression` | function | Compiles an attached-state locator wait. |
|
|
514
|
+
| `compileBrowserBindingCleanup` | function | Compiles current-document cleanup for one page-side host binding facade. |
|
|
515
|
+
| `compileBrowserBindingResult` | function | Compiles delivery of a host binding result to one execution context. |
|
|
516
|
+
| `compileBrowserBindingSource` | function | Compiles the page-side promise facade for one Runtime binding. |
|
|
517
|
+
| `compileDetachedLocatorWaitExpression` | function | Compiles a detached-state locator wait. |
|
|
518
|
+
| `compileFunctionWaitExpression` | function | Compiles an auto-retrying in-page predicate wait. |
|
|
519
|
+
| `compileHiddenLocatorWaitExpression` | function | Compiles a hidden-state locator wait. |
|
|
520
|
+
| `compileLocatorExpression` | function | Compiles a deep locator query returning its first match. |
|
|
521
|
+
| `compileLocatorListExpression` | function | Compiles a deep, shadow-aware locator query returning every match. |
|
|
522
|
+
| `compileScreenshotCleanupExpression` | function | Compiles cleanup for temporary screenshot styles and masks. |
|
|
523
|
+
| `compileScreenshotPreparationExpression` | function | Compiles temporary animation, caret, and mask setup for a screenshot. |
|
|
524
|
+
| `compileStorageClearExpression` | function | Compiles an expression that clears local and session storage. |
|
|
525
|
+
| `compileStorageReadExpression` | function | Compiles an expression that serializes local and session storage. |
|
|
526
|
+
| `compileStorageRestoreExpression` | function | Compiles an expression that restores one origin's web storage. |
|
|
527
|
+
| `compileVisibleLocatorWaitExpression` | function | Compiles a visible-state locator wait. |
|
|
528
|
+
| `computeBrowserButtons` | function | Computes the CDP Input pressed-button bitmask. |
|
|
529
|
+
| `computeBrowserModifiers` | function | Computes the CDP Input modifier bitmask. |
|
|
530
|
+
| `concatBytes` | function | Concatenates byte chunks without Node-specific buffers. |
|
|
531
|
+
| `cookieToProtocol` | function | Converts a typed cookie input into Chromium protocol fields. |
|
|
532
|
+
| `createBrowserHAREntry` | function | Builds a standards-shaped HAR 1.2 entry from one observed exchange. |
|
|
533
|
+
| `encodeBase64` | function | Encodes raw bytes as base64 without relying on Node or DOM globals. |
|
|
534
|
+
| `extractBrowserChord` | function | Extracts a keyboard chord such as `Control+Shift+P` into its parts, throwing a `BrowserError` on an empty chord or an unsupported modifier. |
|
|
535
|
+
| `keyToBrowserInput` | function | Normalizes one key to CDP keyboard event data. |
|
|
536
|
+
| `matchesBrowserCookieURL` | function | Matches a decoded cookie against one request URL. |
|
|
537
|
+
| `matchesBrowserRoute` | function | Matches a request against route criteria. |
|
|
538
|
+
| `matchesBrowserURL` | function | Matches a URL using Chromium-style `*` and `**` glob segments. |
|
|
539
|
+
| `mediaToFeatures` | function | Converts typed media preferences to Chromium emulated media features. |
|
|
540
|
+
| `parseBrowserAXString` | function | Coerces a string-valued Accessibility-domain AXValue to a string, or `undefined` off-shape. |
|
|
541
|
+
| `parseBrowserBindingCall` | function | Coerces one Runtime binding invocation to a `BrowserBindingCall`, or `undefined` off-shape. |
|
|
542
|
+
| `parseBrowserConsoleMessage` | function | Coerces one `Runtime.consoleAPICalled` event to a `BrowserConsoleMessage`, or `undefined` off-shape. |
|
|
543
|
+
| `parseBrowserCookiePartition` | function | Coerces an optional Chromium cookie partition key to a `BrowserCookiePartition`, or `undefined` off-shape. |
|
|
544
|
+
| `parseBrowserDownloadProgress` | function | Coerces one `Browser.downloadProgress` event to a `BrowserDownloadProgress`, or `undefined` off-shape. |
|
|
545
|
+
| `parseBrowserDownloadStart` | function | Coerces one `Browser.downloadWillBegin` event to a `BrowserDownloadStart`, or `undefined` off-shape. |
|
|
546
|
+
| `parseBrowserPageError` | function | Coerces one `Runtime.exceptionThrown` event to a `BrowserPageError`, or `undefined` off-shape. |
|
|
547
|
+
| `parseBrowserRequest` | function | Coerces one `Network.requestWillBeSent` or `Fetch.requestPaused` event to a `BrowserRequest`, or `undefined` off-shape. |
|
|
548
|
+
| `parseBrowserRequestFailure` | function | Coerces one `Network.loadingFailed` event to a `BrowserRequestFailure`, or `undefined` off-shape. |
|
|
549
|
+
| `parseBrowserResponse` | function | Coerces one `Network.responseReceived` event to a `BrowserResponse`, or `undefined` off-shape. |
|
|
550
|
+
| `parseBrowserResponseRecord` | function | Coerces one Chromium response object plus its event identity to a `BrowserResponse`, or `undefined` off-shape. |
|
|
551
|
+
| `parseBrowserSecurity` | function | Coerces Chromium TLS security details to a `BrowserSecurity`, or `undefined` off-shape. |
|
|
552
|
+
| `parseBrowserTiming` | function | Coerces Chromium response timing to a `BrowserTiming`, or `undefined` off-shape. |
|
|
553
|
+
| `parseBrowserTimingRange` | function | Coerces one named start/end pair of Chromium network timing to a `BrowserTimingRange`, or `undefined` off-shape. |
|
|
554
|
+
| `parseBrowserWebSocketFrame` | function | Coerces one WebSocket frame event to a `BrowserWebSocketFrame`, or `undefined` off-shape. |
|
|
555
|
+
| `readBrowserAXValue` | function | Decodes an Accessibility-domain AXValue, or `undefined` when the record carries none. |
|
|
556
|
+
| `readBrowserAccessibility` | function | Decodes Accessibility-domain nodes into a flat serializable tree, throwing a `BrowserError` off-shape. |
|
|
557
|
+
| `readBrowserCookie` | function | Decodes one Chromium cookie, throwing a `BrowserError` off-shape. |
|
|
558
|
+
| `readBrowserCookies` | function | Decodes the cookies `Storage.getCookies` returns, throwing a `BrowserError` off-shape. |
|
|
559
|
+
| `readBrowserCoverageRanges` | function | Decodes and normalizes coverage ranges, throwing a `BrowserError` off-shape. |
|
|
560
|
+
| `readBrowserHeaders` | function | Decodes a Chromium Headers object into string values, skipping every entry that is neither a string nor a finite number. |
|
|
561
|
+
| `readBrowserMetrics` | function | Decodes Performance-domain metrics, throwing a `BrowserError` off-shape. |
|
|
562
|
+
| `readBrowserProfile` | function | Decodes one CPU profile, throwing a `BrowserError` off-shape. |
|
|
563
|
+
| `readBrowserProfileFrame` | function | Decodes a CPU profile call frame, throwing a `BrowserError` off-shape. |
|
|
564
|
+
| `readBrowserQuad` | function | Decodes the first `DOM.getContentQuads` quad and its center, throwing a `BrowserError` off-shape. |
|
|
565
|
+
| `readBrowserRemoteValue` | function | Decodes a Runtime remote object's printable value, falling back to its unserializable form and then its description, or `undefined` when it carries none. |
|
|
566
|
+
| `readBrowserScriptCoverage` | function | Decodes JavaScript precise coverage, throwing a `BrowserError` off-shape. |
|
|
567
|
+
| `readBrowserScriptIdentifier` | function | Decodes the `Page.addScriptToEvaluateOnNewDocument` result, throwing a `BrowserError` off-shape. |
|
|
568
|
+
| `readBrowserStack` | function | Decodes a Chromium runtime stack trace, skipping every off-shape call frame. |
|
|
569
|
+
| `readBrowserStorageEntries` | function | Decodes a list of web-storage entries, throwing a `BrowserError` off-shape. |
|
|
570
|
+
| `readBrowserStorageOrigin` | function | Decodes one in-page web-storage snapshot, throwing a `BrowserError` off-shape. |
|
|
571
|
+
| `readBrowserStreamChunk` | function | Decodes one `IO.read` response, throwing a `BrowserError` off-shape. |
|
|
572
|
+
| `readBrowserStyleCoverage` | function | Decodes CSS rule usage, throwing a `BrowserError` off-shape. |
|
|
573
|
+
| `settleBrowserTeardown` | function | Awaits every teardown step in order and returns the first failure. |
|
|
574
|
+
| `textToBytes` | function | Encodes UTF-8 text as bytes. |
|
|
575
|
+
| `validateBrowserAccessibilityOptions` | function | Validates Accessibility-domain snapshot bounds. |
|
|
576
|
+
| `validateBrowserContextOptions` | function | Validates isolated-context options before creating remote state. |
|
|
577
|
+
| `validateBrowserEmulationOptions` | function | Validates context emulation boundaries before partial application. |
|
|
578
|
+
| `validateBrowserHAR` | function | Validates the HAR 1.2 fields required for deterministic replay. |
|
|
579
|
+
| `validateBrowserInputOptions` | function | Validates the bounded delay, count, steps, and position of one trusted-input operation. |
|
|
580
|
+
| `validateBrowserPoint` | function | Validates viewport input coordinates. |
|
|
581
|
+
| `validateBrowserRange` | function | Validates a finite numeric range. |
|
|
582
|
+
| `validateBrowserTimeout` | function | Validates a public browser timeout before protocol work begins. |
|
|
583
|
+
| `validateBrowserViewport` | function | Validates Chromium viewport metrics. |
|
|
584
|
+
|
|
585
|
+
The pure helpers can be composed around captured CDP payloads without creating
|
|
586
|
+
a browser entity. This compact fixture sketch intentionally shows every
|
|
587
|
+
helper family; production callers normally use the managers, which invoke
|
|
588
|
+
these decoders and compilers internally.
|
|
589
|
+
|
|
590
|
+
```ts
|
|
591
|
+
import {
|
|
592
|
+
browserHARHeadersToRecord,
|
|
593
|
+
browserHeadersToProtocol,
|
|
594
|
+
browserPDFToParams,
|
|
595
|
+
browserScreenshotToParams,
|
|
596
|
+
bytesToText,
|
|
597
|
+
compileActionabilityFunction,
|
|
598
|
+
compileAttachedLocatorWaitExpression,
|
|
599
|
+
compileBrowserBindingCleanup,
|
|
600
|
+
compileBrowserBindingResult,
|
|
601
|
+
compileBrowserBindingSource,
|
|
602
|
+
compileDetachedLocatorWaitExpression,
|
|
603
|
+
compileFunctionWaitExpression,
|
|
604
|
+
compileHiddenLocatorWaitExpression,
|
|
605
|
+
compileLocatorExpression,
|
|
606
|
+
compileLocatorListExpression,
|
|
607
|
+
compileScreenshotCleanupExpression,
|
|
608
|
+
compileScreenshotPreparationExpression,
|
|
609
|
+
compileStorageClearExpression,
|
|
610
|
+
compileStorageReadExpression,
|
|
611
|
+
compileStorageRestoreExpression,
|
|
612
|
+
compileVisibleLocatorWaitExpression,
|
|
613
|
+
computeBrowserButtons,
|
|
614
|
+
computeBrowserModifiers,
|
|
615
|
+
concatBytes,
|
|
616
|
+
cookieToProtocol,
|
|
617
|
+
createBrowserHAREntry,
|
|
618
|
+
encodeBase64,
|
|
619
|
+
extractBrowserChord,
|
|
620
|
+
keyToBrowserInput,
|
|
621
|
+
matchesBrowserCookieURL,
|
|
622
|
+
matchesBrowserRoute,
|
|
623
|
+
matchesBrowserURL,
|
|
624
|
+
mediaToFeatures,
|
|
625
|
+
parseBrowserAXString,
|
|
626
|
+
parseBrowserBindingCall,
|
|
627
|
+
parseBrowserConsoleMessage,
|
|
628
|
+
parseBrowserCookiePartition,
|
|
629
|
+
parseBrowserDownloadProgress,
|
|
630
|
+
parseBrowserDownloadStart,
|
|
631
|
+
parseBrowserPageError,
|
|
632
|
+
parseBrowserRequest,
|
|
633
|
+
parseBrowserRequestFailure,
|
|
634
|
+
parseBrowserResponse,
|
|
635
|
+
parseBrowserResponseRecord,
|
|
636
|
+
parseBrowserSecurity,
|
|
637
|
+
parseBrowserTiming,
|
|
638
|
+
parseBrowserTimingRange,
|
|
639
|
+
parseBrowserWebSocketFrame,
|
|
640
|
+
readBrowserAXValue,
|
|
641
|
+
readBrowserAccessibility,
|
|
642
|
+
readBrowserCookie,
|
|
643
|
+
readBrowserCookies,
|
|
644
|
+
readBrowserCoverageRanges,
|
|
645
|
+
readBrowserHeaders,
|
|
646
|
+
readBrowserMetrics,
|
|
647
|
+
readBrowserProfile,
|
|
648
|
+
readBrowserProfileFrame,
|
|
649
|
+
readBrowserQuad,
|
|
650
|
+
readBrowserRemoteValue,
|
|
651
|
+
readBrowserScriptCoverage,
|
|
652
|
+
readBrowserScriptIdentifier,
|
|
653
|
+
readBrowserStack,
|
|
654
|
+
readBrowserStorageEntries,
|
|
655
|
+
readBrowserStorageOrigin,
|
|
656
|
+
readBrowserStreamChunk,
|
|
657
|
+
readBrowserStyleCoverage,
|
|
658
|
+
settleBrowserTeardown,
|
|
659
|
+
textToBytes,
|
|
660
|
+
validateBrowserAccessibilityOptions,
|
|
661
|
+
validateBrowserContextOptions,
|
|
662
|
+
validateBrowserEmulationOptions,
|
|
663
|
+
validateBrowserHAR,
|
|
664
|
+
validateBrowserInputOptions,
|
|
665
|
+
validateBrowserPoint,
|
|
666
|
+
validateBrowserRange,
|
|
667
|
+
validateBrowserTimeout,
|
|
668
|
+
validateBrowserViewport,
|
|
669
|
+
} from '@orkestrel/browser'
|
|
670
|
+
|
|
671
|
+
const query = { selector: 'css', value: 'main' }
|
|
672
|
+
const bytes = textToBytes('hello')
|
|
673
|
+
bytesToText(bytes)
|
|
674
|
+
encodeBase64(bytes)
|
|
675
|
+
concatBytes([bytes])
|
|
676
|
+
browserHeadersToProtocol({ accept: 'application/json' })
|
|
677
|
+
browserHARHeadersToRecord([{ name: 'content-type', value: 'text/plain' }])
|
|
678
|
+
browserPDFToParams({ landscape: true })
|
|
679
|
+
browserScreenshotToParams({ format: 'png' })
|
|
680
|
+
compileActionabilityFunction({ visible: true, stable: true })
|
|
681
|
+
compileLocatorListExpression(query)
|
|
682
|
+
compileLocatorExpression(query)
|
|
683
|
+
compileAttachedLocatorWaitExpression(query, true, 1000)
|
|
684
|
+
compileDetachedLocatorWaitExpression(query, true, 1000)
|
|
685
|
+
compileVisibleLocatorWaitExpression(query, true, 1000)
|
|
686
|
+
compileHiddenLocatorWaitExpression(query, true, 1000)
|
|
687
|
+
compileFunctionWaitExpression('() => document.readyState === "complete"', 1000)
|
|
688
|
+
compileBrowserBindingSource('lookup')
|
|
689
|
+
compileBrowserBindingResult('lookup', 'call-1', true, { found: true })
|
|
690
|
+
compileBrowserBindingCleanup('lookup')
|
|
691
|
+
compileScreenshotPreparationExpression({ animations: false })
|
|
692
|
+
compileScreenshotCleanupExpression('1')
|
|
693
|
+
compileStorageReadExpression()
|
|
694
|
+
compileStorageRestoreExpression({
|
|
695
|
+
origin: 'https://example.com',
|
|
696
|
+
local: [{ name: 'theme', value: 'dark' }],
|
|
697
|
+
session: [],
|
|
698
|
+
})
|
|
699
|
+
compileStorageClearExpression()
|
|
700
|
+
computeBrowserButtons(['left'])
|
|
701
|
+
computeBrowserModifiers(['Control'])
|
|
702
|
+
cookieToProtocol({ name: 'session', value: 'value', url: 'https://example.com/' })
|
|
703
|
+
keyToBrowserInput('Enter')
|
|
704
|
+
extractBrowserChord('Control+Enter')
|
|
705
|
+
matchesBrowserURL('https://example.com/api', '**/api')
|
|
706
|
+
mediaToFeatures({ scheme: 'dark', motion: 'reduce' })
|
|
707
|
+
|
|
708
|
+
const request = parseBrowserRequest({
|
|
709
|
+
requestId: 'request-1',
|
|
710
|
+
request: { url: 'https://example.com/api', method: 'GET', headers: {} },
|
|
711
|
+
})
|
|
712
|
+
if (request !== undefined) {
|
|
713
|
+
matchesBrowserRoute(request, { url: '**/api' })
|
|
714
|
+
createBrowserHAREntry(
|
|
715
|
+
{ request, started: Date.now(), response: undefined },
|
|
716
|
+
10,
|
|
717
|
+
undefined,
|
|
718
|
+
'Request failed',
|
|
719
|
+
)
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const cookie = readBrowserCookie(
|
|
723
|
+
{
|
|
724
|
+
name: 'session',
|
|
725
|
+
value: 'value',
|
|
726
|
+
domain: 'example.com',
|
|
727
|
+
path: '/',
|
|
728
|
+
expires: -1,
|
|
729
|
+
size: 12,
|
|
730
|
+
httpOnly: true,
|
|
731
|
+
secure: true,
|
|
732
|
+
session: true,
|
|
733
|
+
priority: 'Medium',
|
|
734
|
+
},
|
|
735
|
+
0,
|
|
736
|
+
)
|
|
737
|
+
matchesBrowserCookieURL(cookie, 'https://example.com/')
|
|
738
|
+
|
|
739
|
+
const payload: unknown = {}
|
|
740
|
+
parseBrowserAXString(payload)
|
|
741
|
+
readBrowserAXValue(payload)
|
|
742
|
+
readBrowserAccessibility(payload)
|
|
743
|
+
parseBrowserBindingCall(payload)
|
|
744
|
+
parseBrowserConsoleMessage(payload)
|
|
745
|
+
parseBrowserCookiePartition(payload)
|
|
746
|
+
readBrowserCookies(payload)
|
|
747
|
+
readBrowserCoverageRanges([], 0)
|
|
748
|
+
parseBrowserDownloadProgress(payload)
|
|
749
|
+
parseBrowserDownloadStart(payload)
|
|
750
|
+
readBrowserHeaders(payload)
|
|
751
|
+
readBrowserMetrics(payload)
|
|
752
|
+
parseBrowserPageError(payload)
|
|
753
|
+
readBrowserProfile(payload)
|
|
754
|
+
readBrowserProfileFrame(payload, 0)
|
|
755
|
+
readBrowserQuad(payload)
|
|
756
|
+
readBrowserRemoteValue(payload)
|
|
757
|
+
parseBrowserRequestFailure(payload)
|
|
758
|
+
parseBrowserResponse(payload)
|
|
759
|
+
parseBrowserResponseRecord(payload, 'request-1', 'loader-1', undefined, 0)
|
|
760
|
+
readBrowserScriptCoverage(payload)
|
|
761
|
+
readBrowserScriptIdentifier(payload)
|
|
762
|
+
parseBrowserSecurity(payload)
|
|
763
|
+
readBrowserStack(payload)
|
|
764
|
+
readBrowserStorageEntries([], 'https://example.com', 'local')
|
|
765
|
+
readBrowserStorageOrigin(payload, 'https://example.com')
|
|
766
|
+
readBrowserStreamChunk(payload)
|
|
767
|
+
readBrowserStyleCoverage(payload)
|
|
768
|
+
await settleBrowserTeardown(
|
|
769
|
+
async () => undefined,
|
|
770
|
+
async () => undefined,
|
|
771
|
+
) // unknown — the value the first failing step threw, or undefined
|
|
772
|
+
parseBrowserTiming(payload)
|
|
773
|
+
parseBrowserTimingRange(payload, 'dnsStart', 'dnsEnd')
|
|
774
|
+
parseBrowserWebSocketFrame(payload)
|
|
775
|
+
validateBrowserAccessibilityOptions({ depth: 3 })
|
|
776
|
+
validateBrowserInputOptions({ delay: 10, count: 2 })
|
|
777
|
+
validateBrowserContextOptions({ origins: ['https://example.com'] })
|
|
778
|
+
validateBrowserEmulationOptions({ locale: 'en-US' })
|
|
779
|
+
validateBrowserHAR({
|
|
780
|
+
log: { version: '1.2', creator: { name: 'fixture', version: '1' }, entries: [] },
|
|
781
|
+
})
|
|
782
|
+
validateBrowserPoint({ x: 10, y: 20 })
|
|
783
|
+
validateBrowserRange(50, 'quality', 0, 100)
|
|
784
|
+
validateBrowserTimeout(1000)
|
|
785
|
+
validateBrowserViewport({ width: 1280, height: 720 })
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
#### Extended types
|
|
789
|
+
|
|
790
|
+
A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional member and `plus` introducing its call-signature members, and a type alias's own type literal with a union's arms escaped as `\|`. An extended interface's name comes before `plus`, with the members it adds after.
|
|
791
|
+
|
|
792
|
+
| API | Kind | Shape | Summary |
|
|
793
|
+
| ----------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
794
|
+
| `BrowserAXNode` | interface | `{ id, parent, children, backend, frame, ignored, role, name, description, value, properties }` | Represents one decoded Chromium accessibility node. |
|
|
795
|
+
| `BrowserAccessibilityInterface` | interface | `{} plus snapshot` | Inspects the accessibility tree. |
|
|
796
|
+
| `BrowserAccessibilityOptions` | interface | `{ root?, depth? }` | Describes the options for an accessibility snapshot. |
|
|
797
|
+
| `BrowserAccessibilitySnapshot` | interface | `{ roots, nodes }` | Describes a serializable accessibility-tree snapshot. |
|
|
798
|
+
| `BrowserActionabilityOptions` | interface | `{ visible?, stable?, events?, enabled?, editable?, position? }` | Describes the actionability checks performed before locator input. |
|
|
799
|
+
| `BrowserBindingCall` | interface | `{ id, name, args, context }` | Describes a decoded page-to-host binding call. |
|
|
800
|
+
| `BrowserBindingHandler` | type | `(...args: unknown[]) => unknown \| Promise<unknown>` | Runs a host function exposed into page JavaScript. |
|
|
801
|
+
| `BrowserChord` | interface | `{ modifiers, key }` | Describes a parsed keyboard chord. |
|
|
802
|
+
| `BrowserClickOptions` | interface | `BrowserInputOptions plus { button?, count? }` | Describes the options for a trusted mouse click. |
|
|
803
|
+
| `BrowserClockInterface` | interface | `{ installed } plus install, pause, resume, advance, uninstall` | Controls Chromium virtual time for deterministic page timers. |
|
|
804
|
+
| `BrowserConsoleMessage` | interface | `{ level, text, values, timestamp, stack }` | Represents one console API call. |
|
|
805
|
+
| `BrowserContextEventMap` | type | `{ page, close }` | Maps the browser-context lifecycle events. |
|
|
806
|
+
| `BrowserContextOptions` | interface | `{ on?, error?, proxy?, origins?, downloads?, emulation? }` | Describes the options for creating and configuring an isolated browser context. |
|
|
807
|
+
| `BrowserCookie` | interface | `{ name, value, domain, path, expires, http, secure, site, partition }` | Represents one cookie returned from a browser context. |
|
|
808
|
+
| `BrowserCookieFilter` | interface | `{ name?, domain?, path? }` | Describes optional narrowing criteria for clearing context cookies. |
|
|
809
|
+
| `BrowserCookieInput` | interface | `{ name, value, url?, domain?, path?, expires?, http?, secure?, site?, priority?, partition? }` | Describes the input used to create or replace a browser cookie. |
|
|
810
|
+
| `BrowserCookieManagerInterface` | interface | `{} plus cookies, set, clear` | Provides cookie operations scoped to one browser context. |
|
|
811
|
+
| `BrowserCookiePartition` | interface | `{ site, ancestor? }` | Describes a cookie partition key used by CHIPS-partitioned cookies. |
|
|
812
|
+
| `BrowserCoverageInterface` | interface | `{ active } plus start, stop, destroy` | Drives the coverage capture lifecycle. |
|
|
813
|
+
| `BrowserCoverageOptions` | interface | `{ javascript?, css?, detailed? }` | Describes the options for a coverage capture. |
|
|
814
|
+
| `BrowserCoverageRange` | interface | `{ start, end, count }` | Describes a source range reported by JavaScript or CSS coverage. |
|
|
815
|
+
| `BrowserCoverageResult` | interface | `{ scripts, styles }` | Describes combined JavaScript and CSS usage. |
|
|
816
|
+
| `BrowserCredentials` | interface | `{ username, password }` | Describes the HTTP basic-auth credentials applied to context pages. |
|
|
817
|
+
| `BrowserDiagnosticsInterface` | interface | `{ tracing, coverage, performance, profiler } plus destroy` | Groups the diagnostics by capability. |
|
|
818
|
+
| `BrowserDialogCategory` | type | `'alert' \| 'confirm' \| 'prompt' \| 'beforeunload'` | Names a JavaScript dialog category reported by Chromium. |
|
|
819
|
+
| `BrowserDialogInterface` | interface | `{ category, message, default } plus accept, dismiss` | Represents one active JavaScript dialog. |
|
|
820
|
+
| `BrowserDownloadEventMap` | type | `{ progress, complete, cancel }` | Maps the download progress events. |
|
|
821
|
+
| `BrowserDownloadInterface` | interface | `{ emitter, id, url, name, status, received, total, path } plus cancel, update` | Represents one context download tracked through Chromium's Browser domain. |
|
|
822
|
+
| `BrowserDownloadOptions` | interface | `{ path, named? }` | Describes the download policy for a browser context. |
|
|
823
|
+
| `BrowserDownloadProgress` | interface | `{ status, received, total, path? }` | Describes a protocol-neutral download progress update. |
|
|
824
|
+
| `BrowserDownloadStart` | interface | `{ id, url, name, frame }` | Describes a decoded `Browser.downloadWillBegin` event. |
|
|
825
|
+
| `BrowserDownloadStatus` | type | `'pending' \| 'complete' \| 'cancelled'` | Names a download lifecycle phase. |
|
|
826
|
+
| `BrowserDragOptions` | interface | `BrowserInputOptions plus { button?, steps? }` | Describes the options for a trusted mouse drag. |
|
|
827
|
+
| `BrowserEmulationManagerInterface` | interface | `{} plus apply, clear, attach` | Configures context-scoped emulation. |
|
|
828
|
+
| `BrowserEmulationOptions` | interface | `{ viewport?, user?, locale?, timezone?, geolocation?, media?, offline?, headers?, credentials? }` | Describes network and rendering overrides inherited by context pages. |
|
|
829
|
+
| `BrowserFileChooserInterface` | interface | `{ multiple } plus upload, cancel` | Represents one intercepted file chooser. |
|
|
830
|
+
| `BrowserFunctionCoverage` | interface | `{ name, ranges, block }` | Describes function coverage inside one script. |
|
|
831
|
+
| `BrowserGeolocation` | interface | `{ latitude, longitude, accuracy? }` | Describes a geographic location override. |
|
|
832
|
+
| `BrowserHAR` | interface | `{ log }` | Describes the standards-shaped HAR 1.2 document produced by the network manager. |
|
|
833
|
+
| `BrowserHARContent` | interface | `{ size, mimeType, text?, encoding? }` | Describes response body metadata in an HTTP archive. |
|
|
834
|
+
| `BrowserHARCookie` | interface | `BrowserHARValue plus { path?, domain?, expires?, httpOnly?, secure? }` | Represents one cookie in an HTTP archive. |
|
|
835
|
+
| `BrowserHARCreator` | interface | `{ name, version }` | Describes the tool identity embedded in an HTTP archive. |
|
|
836
|
+
| `BrowserHAREntry` | interface | `{ startedDateTime, time, request, response, cache, timings }` | Represents one completed HTTP exchange in a HAR recording. |
|
|
837
|
+
| `BrowserHARLog` | interface | `{ version, creator, entries }` | Describes the HAR 1.2 log object. |
|
|
838
|
+
| `BrowserHARManagerInterface` | interface | `{ recording } plus start, stop, replay, clear` | Provides HAR recording and replay operations. |
|
|
839
|
+
| `BrowserHAROptions` | interface | `{ path?, content? }` | Describes the options for a HAR recording. |
|
|
840
|
+
| `BrowserHARPending` | interface | `{ request, started, response }` | Holds recording state until a request finishes; a new value replaces it on each update. |
|
|
841
|
+
| `BrowserHARPost` | interface | `{ mimeType, text }` | Describes request body metadata in an HTTP archive. |
|
|
842
|
+
| `BrowserHARReplayOptions` | interface | `{ fallback? }` | Describes HAR replay behavior. |
|
|
843
|
+
| `BrowserHARRequest` | interface | `{ method, url, httpVersion, cookies, headers, queryString, postData?, headersSize, bodySize }` | Describes a HAR 1.2 request entry. |
|
|
844
|
+
| `BrowserHARResponse` | interface | `{ status, statusText, httpVersion, cookies, headers, content, redirectURL, headersSize, bodySize }` | Describes a HAR 1.2 response entry. |
|
|
845
|
+
| `BrowserHARTimings` | interface | `{ blocked, dns, connect, send, wait, receive, ssl }` | Holds HAR 1.2 phase timings in milliseconds. |
|
|
846
|
+
| `BrowserHARValue` | interface | `{ name, value }` | Represents one name/value pair in an HTTP archive. |
|
|
847
|
+
| `BrowserHandleInterface` | interface | `{ id } plus value, call, property, properties, dispose` | Represents a remote JavaScript object retained in one frame execution context. |
|
|
848
|
+
| `BrowserInputOptions` | interface | `{ delay? }` | Describes the options shared by every trusted input operation. |
|
|
849
|
+
| `BrowserKey` | interface | `{ key, code, text, number }` | Describes normalized CDP keyboard key data. |
|
|
850
|
+
| `BrowserKeyboardInterface` | interface | `{} plus down, up, press, type, insert` | Provides keyboard input operations bound to one frame target session. |
|
|
851
|
+
| `BrowserLocatorClickOptions` | interface | `BrowserPointerOptions plus BrowserClickOptions` | Describes the options for a locator click, combining element resolution with mouse input. |
|
|
852
|
+
| `BrowserLocatorDragOptions` | interface | `BrowserPointerOptions plus BrowserDragOptions` | Describes the options for a locator drag, combining element resolution with mouse input. |
|
|
853
|
+
| `BrowserLocatorFilter` | interface | `{ text?, exact?, visible? }` | Describes a declarative locator filter applied after selector resolution. |
|
|
854
|
+
| `BrowserLocatorInterface` | interface | `{ frame, query } plus locator, filter, first, last, item, count, all, click, fill, select, check, uncheck, hover, focus, press, type, clear, wait, text, texts, html, value, attribute, visible, enabled, editable, screenshot, upload, drag` | Represents a reusable strict locator over one frame. |
|
|
855
|
+
| `BrowserLocatorTypeOptions` | interface | `BrowserActionOptions plus BrowserInputOptions` | Describes the options for locator keyboard entry, combining element resolution with key input. |
|
|
856
|
+
| `BrowserMargin` | interface | `{ top?, right?, bottom?, left? }` | Describes the paper margin lengths accepted by Chromium print-to-PDF. |
|
|
857
|
+
| `BrowserMedia` | interface | `{ output?, scheme?, contrast?, motion?, colors? }` | Describes browser color and media feature overrides. |
|
|
858
|
+
| `BrowserMetric` | interface | `{ name, value }` | Represents one Performance-domain metric. |
|
|
859
|
+
| `BrowserMouseButton` | type | `'left' \| 'middle' \| 'right' \| 'back' \| 'forward'` | Names a mouse button understood by Chromium's Input domain. |
|
|
860
|
+
| `BrowserMouseInterface` | interface | `{} plus move, down, up, click, drag, wheel` | Provides mouse input operations bound to one frame target session. |
|
|
861
|
+
| `BrowserNavigationManagerInterface` | interface | `{} plus wait, until` | Provides URL and in-page predicate waits associated with one page. |
|
|
862
|
+
| `BrowserNavigationResult` | interface | `{ url, response, same }` | Describes the outcome of a top-level navigation command. |
|
|
863
|
+
| `BrowserNavigationWait` | interface | `{ pattern, timer, resolve, reject }` | Represents one pending URL-pattern wait. |
|
|
864
|
+
| `BrowserNavigationWaitOptions` | interface | `{ timeout? }` | Describes the options for URL and predicate waits. |
|
|
865
|
+
| `BrowserNavigationWatch` | interface | `{ responses }` | Holds the state retained while correlating navigation with Network events. |
|
|
866
|
+
| `BrowserNetworkEventMap` | type | `{ request, response, failure, finish, socket }` | Maps the network events a page's network manager emits. |
|
|
867
|
+
| `BrowserNetworkManagerInterface` | interface | `{ emitter, har } plus start, body, text, json, route, unroute, headers, offline, credentials, destroy` | Provides page-scoped network observation and interception. |
|
|
868
|
+
| `BrowserOperationOptions` | type | `BrowserPointerOptions & BrowserClickOptions & BrowserDragOptions` | Collects every option a trusted-input operation can carry. |
|
|
869
|
+
| `BrowserPDFOptions` | interface | `{ path?, landscape?, background?, scale?, width?, height?, margin?, ranges?, header?, footer?, tagged?, outline? }` | Describes the options for printing a Chromium page to PDF. |
|
|
870
|
+
| `BrowserPDFResult` | interface | `{ bytes, path }` | Describes the result of printing a page to PDF. |
|
|
871
|
+
| `BrowserPageError` | interface | `{ message, stack, timestamp }` | Represents one uncaught page exception. |
|
|
872
|
+
| `BrowserPageEventMap` | type | `{ navigate, attach, detach, popup, dialog, chooser, download, console, error, crash, worker, request, response, failure, socket, close }` | Maps the typed page, frame, target, and user-visible browser events. |
|
|
873
|
+
| `BrowserPagesFunction` | type | `() => readonly BrowserPageInterface[]` | Returns the context's live pages at call time. |
|
|
874
|
+
| `BrowserPerformanceInterface` | interface | `{} plus metrics` | Reads Performance-domain metrics. |
|
|
875
|
+
| `BrowserPermissionManagerInterface` | interface | `{} plus grant, deny, clear` | Provides permission override operations scoped to one browser context. |
|
|
876
|
+
| `BrowserPoint` | interface | `{ x, y }` | Describes a point in viewport CSS pixels. |
|
|
877
|
+
| `BrowserPointerOptions` | interface | `BrowserActionOptions plus { position? }` | Describes the options for a locator operation that aims at a point inside the element. |
|
|
878
|
+
| `BrowserProfile` | interface | `{ start, end, nodes, samples, deltas }` | Describes a sampled CPU profile. |
|
|
879
|
+
| `BrowserProfileFrame` | interface | `{ function, script, url, line, column }` | Describes a JavaScript call frame from a CPU profile. |
|
|
880
|
+
| `BrowserProfileNode` | interface | `{ id, frame, hit, children }` | Represents one node in a sampled CPU profile. |
|
|
881
|
+
| `BrowserProfilerInterface` | interface | `{ active } plus start, stop, destroy` | Drives the sampled CPU profile lifecycle. |
|
|
882
|
+
| `BrowserProxy` | interface | `{ server, bypass? }` | Describes proxy settings used when creating an isolated browser context. |
|
|
883
|
+
| `BrowserQuad` | interface | `{ points, center }` | Describes a decoded content quad and its actionable center. |
|
|
884
|
+
| `BrowserQuery` | interface | `{ selector, value, name?, exact?, parent?, filter?, index? }` | Describes a serializable selector query, including optional ancestry and filtering. |
|
|
885
|
+
| `BrowserRequest` | interface | `{ id, loader, frame, url, method, headers, post, resource, timestamp, walltime, redirect }` | Represents one observed browser request. |
|
|
886
|
+
| `BrowserRequestFailure` | interface | `{ id, error, cancelled, blocked }` | Represents one failed browser request. |
|
|
887
|
+
| `BrowserResponse` | interface | `{ id, loader, frame, url, status, phrase, headers, mime, protocol, address, port, cached, worker, timestamp, timing, security }` | Represents one observed browser response. |
|
|
888
|
+
| `BrowserRoleOptions` | interface | `{ name?, exact? }` | Describes the options for role-based locator creation. |
|
|
889
|
+
| `BrowserRouteContinueOptions` | interface | `{ url?, method?, headers?, post? }` | Describes the overrides supplied when continuing an intercepted request. |
|
|
890
|
+
| `BrowserRouteDefinition` | interface | `{ query, handler }` | Represents one installed network route. |
|
|
891
|
+
| `BrowserRouteFulfillOptions` | interface | `{ status?, phrase?, headers?, body? }` | Describes the synthetic response supplied when fulfilling an intercepted request. |
|
|
892
|
+
| `BrowserRouteHandler` | type | `(route: BrowserRouteInterface) => void \| Promise<void>` | Runs for a matching intercepted request. |
|
|
893
|
+
| `BrowserRouteInterface` | interface | `{ id, request, handled } plus abort, continue, fulfill` | Represents one paused Fetch-domain request. |
|
|
894
|
+
| `BrowserRouteQuery` | interface | `{ url?, method?, resource? }` | Describes route matching criteria. Omitted fields match all values. |
|
|
895
|
+
| `BrowserSameSite` | type | `'Strict' \| 'Lax' \| 'None'` | Names a cookie same-site policy understood by Chromium. |
|
|
896
|
+
| `BrowserScreenshotScale` | type | `'css' \| 'device'` | Names a screenshot coordinate scale. |
|
|
897
|
+
| `BrowserScriptCoverage` | interface | `{ id, url, functions }` | Describes JavaScript script coverage. |
|
|
898
|
+
| `BrowserScriptEntry` | interface | `{ source, binding }` | Represents one installed new-document script and its optional host binding owner. |
|
|
899
|
+
| `BrowserScriptManagerInterface` | interface | `{} plus add, remove, expose, revoke, destroy` | Manages initialization scripts and host bindings for one page. |
|
|
900
|
+
| `BrowserSecurity` | interface | `{ protocol, issuer, from, to }` | Describes the TLS details supplied with a browser response. |
|
|
901
|
+
| `BrowserSelector` | type | `'css' \| 'role' \| 'text' \| 'label' \| 'placeholder' \| 'testId'` | Names a selector axis supported by `BrowserSelectorManagerInterface`. |
|
|
902
|
+
| `BrowserSelectorManagerInterface` | interface | `{} plus css, role, text, label, placeholder, testId` | Groups the locator factories by selector semantics. |
|
|
903
|
+
| `BrowserStackFrame` | interface | `{ url, function, line, column }` | Represents one browser-side stack frame. |
|
|
904
|
+
| `BrowserStorageEntry` | interface | `{ name, value }` | Represents one key/value pair from web storage. |
|
|
905
|
+
| `BrowserStorageManagerInterface` | interface | `{} plus state, restore, clear` | Provides storage-state import, export, and clearing operations. |
|
|
906
|
+
| `BrowserStorageOptions` | interface | `{ origins? }` | Describes the options for collecting storage state from selected origins. |
|
|
907
|
+
| `BrowserStorageOrigin` | interface | `{ origin, local, session }` | Describes an origin-scoped local and session storage snapshot. |
|
|
908
|
+
| `BrowserStorageState` | interface | `{ cookies, origins }` | Describes a portable browser authentication and storage snapshot. |
|
|
909
|
+
| `BrowserStreamChunk` | interface | `{ bytes, eof }` | Represents one decoded IO stream read. |
|
|
910
|
+
| `BrowserStyleCoverage` | interface | `{ id, ranges }` | Describes CSS stylesheet coverage. |
|
|
911
|
+
| `BrowserTeardownFunction` | type | `() => Promise<unknown>` | Runs one teardown step to settlement while the first failure is retained. |
|
|
912
|
+
| `BrowserTextOptions` | interface | `{ exact? }` | Describes the options for text-like locator creation. |
|
|
913
|
+
| `BrowserTiming` | interface | `{ request, proxy, dns, connect, ssl, send, receive }` | Holds network timing values in milliseconds relative to request time. |
|
|
914
|
+
| `BrowserTimingRange` | interface | `{ start, end }` | Describes the start/end pair for one network timing phase. |
|
|
915
|
+
| `BrowserTouchInterface` | interface | `{} plus tap` | Provides touch input operations bound to one frame target session. |
|
|
916
|
+
| `BrowserTracingInterface` | interface | `{ active } plus start, stop, destroy` | Drives the trace capture lifecycle. |
|
|
917
|
+
| `BrowserTracingOptions` | interface | `{ path?, categories?, screenshots?, sampling? }` | Describes the options for a Chromium trace capture. |
|
|
918
|
+
| `BrowserTracingResult` | interface | `{ bytes, path }` | Describes the result of a trace capture. |
|
|
919
|
+
| `BrowserTransitionFunction` | type | `() => Promise<T>` | Runs the work one `BrowserTransitionInterface` transition performs. |
|
|
920
|
+
| `BrowserTransitionInterface` | interface | `{ pending } plus execute` | Represents one asynchronous transition shared by every caller that arrives while it runs. |
|
|
921
|
+
| `BrowserUploadOptions` | interface | `BrowserActionOptions plus { files }` | Describes the options for setting files on a file input. |
|
|
922
|
+
| `BrowserUserAgent` | interface | `{ value, language?, platform? }` | Describes user-agent metadata accepted by Chromium emulation. |
|
|
923
|
+
| `BrowserWebSocketEventMap` | type | `{ receive, transmit, error, close }` | Maps the WebSocket lifecycle events. |
|
|
924
|
+
| `BrowserWebSocketFrame` | interface | `{ opcode, data, masked, timestamp }` | Describes a WebSocket frame payload. |
|
|
925
|
+
| `BrowserWebSocketInterface` | interface | `{ emitter, id, url } plus receive, transmit, fail, close` | Represents one observed WebSocket connection. |
|
|
926
|
+
| `BrowserWorkerCategory` | type | `'worker' \| 'service_worker' \| 'shared_worker'` | Names a worker target category. |
|
|
927
|
+
| `BrowserWorkerInterface` | interface | `{ id, url, category } plus evaluate, send, detach, close` | Represents a script worker attached to a page target. |
|
|
928
|
+
|
|
929
|
+
## Methods
|
|
930
|
+
|
|
931
|
+
The public methods of the layer's behavioral interfaces — every call-signature
|
|
932
|
+
member listed (their `readonly` data members stay Surface rows). The Core and
|
|
933
|
+
Server tables come first, then one table per behavioral interface the Extended
|
|
934
|
+
Chromium automation surface introduces, in source declaration order. Each
|
|
935
|
+
implementing class exposes exactly its interface's methods: `CDPClient` ↔
|
|
936
|
+
`CDPClientInterface`, `BrowserContext` ↔ `BrowserContextInterface`,
|
|
937
|
+
`BrowserFrame` ↔ `BrowserFrameInterface`, `BrowserPage` ↔
|
|
938
|
+
`BrowserPageInterface`, `BrowserSnapshot` ↔ `BrowserSnapshotInterface`,
|
|
939
|
+
`BrowserCodegen` ↔ `BrowserCodegenInterface`, `BrowserTransition` ↔
|
|
940
|
+
`BrowserTransitionInterface`, `Browser` ↔
|
|
941
|
+
`BrowserInterface`, `BrowserWebSocket` ↔ `BrowserWebSocketInterface`,
|
|
942
|
+
`BrowserDownload` ↔ `BrowserDownloadInterface`, `WebSocketCDPTransport` ↔
|
|
943
|
+
`CDPTransportInterface`, `FileBrowserWriter` ↔ `BrowserWriterInterface`,
|
|
944
|
+
`BrowserNavigationManager` ↔ `BrowserNavigationManagerInterface`,
|
|
945
|
+
`BrowserHandle` ↔ `BrowserHandleInterface`, `BrowserScriptManager` ↔
|
|
946
|
+
`BrowserScriptManagerInterface`, `BrowserAccessibility` ↔
|
|
947
|
+
`BrowserAccessibilityInterface`, `BrowserTracing` ↔ `BrowserTracingInterface`,
|
|
948
|
+
`BrowserCoverage` ↔ `BrowserCoverageInterface`, `BrowserPerformance` ↔
|
|
949
|
+
`BrowserPerformanceInterface`, `BrowserProfiler` ↔ `BrowserProfilerInterface`,
|
|
950
|
+
`BrowserDiagnostics` ↔ `BrowserDiagnosticsInterface`, `BrowserClock` ↔
|
|
951
|
+
`BrowserClockInterface`, `BrowserLocator` ↔ `BrowserLocatorInterface`,
|
|
952
|
+
`BrowserSelectorManager` ↔ `BrowserSelectorManagerInterface`,
|
|
953
|
+
`BrowserKeyboard` ↔ `BrowserKeyboardInterface`, `BrowserMouse` ↔
|
|
954
|
+
`BrowserMouseInterface`, `BrowserTouch` ↔ `BrowserTouchInterface`,
|
|
955
|
+
`BrowserDialog` ↔ `BrowserDialogInterface`, `BrowserFileChooser` ↔
|
|
956
|
+
`BrowserFileChooserInterface`, `BrowserWorker` ↔ `BrowserWorkerInterface`,
|
|
957
|
+
`BrowserRoute` ↔ `BrowserRouteInterface`, `BrowserHARManager` ↔
|
|
958
|
+
`BrowserHARManagerInterface`, `BrowserNetworkManager` ↔
|
|
959
|
+
`BrowserNetworkManagerInterface`, `BrowserCookieManager` ↔
|
|
960
|
+
`BrowserCookieManagerInterface`, `BrowserPermissionManager` ↔
|
|
961
|
+
`BrowserPermissionManagerInterface`, `BrowserStorageManager` ↔
|
|
962
|
+
`BrowserStorageManagerInterface`, `BrowserEmulationManager` ↔
|
|
963
|
+
`BrowserEmulationManagerInterface`.
|
|
964
|
+
|
|
965
|
+
#### `CDPTransportInterface`
|
|
966
|
+
|
|
967
|
+
The text pipe a `CDPClient` sends and receives JSON-RPC frames over.
|
|
968
|
+
|
|
969
|
+
| Method | Returns | Summary |
|
|
970
|
+
| ------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
971
|
+
| `start` | `Promise<void>` | Opens the underlying connection. |
|
|
972
|
+
| `send` | `Promise<void>` | Writes one raw text frame to the connection. Throws a coded `BrowserConnectionError` carrying the transport `url` when called before the connection opens or after it closes. |
|
|
973
|
+
| `close` | `Promise<void>` | Closes the underlying connection and releases its resources. |
|
|
974
|
+
|
|
975
|
+
```ts
|
|
976
|
+
transport.emitter.on('message', (data) => log(data))
|
|
977
|
+
await transport.start()
|
|
978
|
+
await transport.send('{"id":1,"method":"Target.getTargets"}')
|
|
979
|
+
await transport.close()
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
#### `CDPClientInterface`
|
|
983
|
+
|
|
984
|
+
Frames JSON-RPC-shaped CDP method calls and events over an injected
|
|
985
|
+
`CDPTransportInterface`. `connect` starts the transport and begins
|
|
986
|
+
dispatching; `send` issues a CDP method call, taking its session and per-call
|
|
987
|
+
timeout in a trailing `CDPSendOptions`; `emitter` reports the client's own
|
|
988
|
+
`connect` / `close` / `drop` / `error` transitions;
|
|
989
|
+
`subscribe` / `unsubscribe` register or remove a handler for a CDP event
|
|
990
|
+
(optionally session-scoped). Subscriptions are client-level registrations,
|
|
991
|
+
not connection-level state — they survive `close()` and a subsequent
|
|
992
|
+
`reconnect()` / `connect()`, and resume firing once reconnected. Calling
|
|
993
|
+
`close()` while a `connect()` is still in flight rejects that in-flight
|
|
994
|
+
connect attempt.
|
|
995
|
+
|
|
996
|
+
| Method | Returns | Summary |
|
|
997
|
+
| ------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
998
|
+
| `connect` | `Promise<void>` | Starts the transport and begins dispatching. Idempotent. |
|
|
999
|
+
| `reconnect` | `Promise<void>` | Closes the transport and re-establishes it. |
|
|
1000
|
+
| `send` | `Promise<unknown>` | Issues a CDP method call with optional params and a trailing `CDPSendOptions` carrying the `session` to scope it to and a per-call `timeout` overriding the client-wide default; rejects on timeout. |
|
|
1001
|
+
| `subscribe` | `void` | Registers a handler for a CDP event, optionally session-scoped. |
|
|
1002
|
+
| `unsubscribe` | `void` | Removes a handler for a CDP event, optionally session-scoped. |
|
|
1003
|
+
| `close` | `Promise<void>` | Tears down the transport and rejects every pending request. |
|
|
1004
|
+
|
|
1005
|
+
```ts
|
|
1006
|
+
import { createCDPClient } from '@orkestrel/browser'
|
|
1007
|
+
|
|
1008
|
+
const client = createCDPClient({ transport })
|
|
1009
|
+
await client.connect()
|
|
1010
|
+
const targets = await client.send('Target.getTargets')
|
|
1011
|
+
const onCreated = (params) => log(params)
|
|
1012
|
+
client.subscribe('Target.targetCreated', onCreated)
|
|
1013
|
+
client.unsubscribe('Target.targetCreated', onCreated)
|
|
1014
|
+
await client.reconnect()
|
|
1015
|
+
await client.close()
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
#### `BrowserContextInterface`
|
|
1019
|
+
|
|
1020
|
+
An isolated browser session over a CDP browser context; follows the manager
|
|
1021
|
+
accessor pattern (`page(index?)` / `pages()`).
|
|
1022
|
+
|
|
1023
|
+
| Method | Returns | Summary |
|
|
1024
|
+
| --------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1025
|
+
| `page` | `BrowserPageInterface \| undefined` | Returns one page by index, or the first page. |
|
|
1026
|
+
| `pages` | `readonly BrowserPageInterface[]` | Returns every page in creation order. |
|
|
1027
|
+
| `create` | `Promise<BrowserPageInterface>` | Opens a page in this context. |
|
|
1028
|
+
| `sync` | `Promise<void>` | Synchronizes pages from the given CDP targets, which the server discovers and core never fetches. Performs a destructive diff rather than an additive merge: a page whose target id is missing from `targets` is closed and dropped, and a target that is not yet tracked is attached and added. |
|
|
1029
|
+
| `destroy` | `Promise<void>` | Releases local pages and detaches their sessions without disposing the remote browser context. |
|
|
1030
|
+
| `close` | `Promise<void>` | Closes remote pages, disposes the remote browser context, and releases local resources. |
|
|
1031
|
+
|
|
1032
|
+
```ts
|
|
1033
|
+
const ctx = browser.context()
|
|
1034
|
+
const page = await ctx?.create({ url: 'https://example.com' })
|
|
1035
|
+
const all = ctx?.pages() // readonly BrowserPageInterface[]
|
|
1036
|
+
await ctx?.sync(targets) // reconcile pages from discovered CDP targets
|
|
1037
|
+
await ctx?.destroy() // local detach
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
#### `BrowserFrameInterface`
|
|
1041
|
+
|
|
1042
|
+
Operations shared by a top-level page and an iframe document. Child-frame
|
|
1043
|
+
evaluation uses a named isolated world and automatically follows an attached
|
|
1044
|
+
out-of-process iframe session when Chromium splits the frame into another
|
|
1045
|
+
target.
|
|
1046
|
+
|
|
1047
|
+
| Method | Returns | Summary |
|
|
1048
|
+
| ------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1049
|
+
| `title` | `Promise<string>` | Resolves the frame document title. |
|
|
1050
|
+
| `content` | `Promise<BrowserContentResult>` | Extracts the URL, title, HTML, and visible text under the result-size guards. |
|
|
1051
|
+
| `article` | `Promise<string>` | Distills the frame HTML to reader-facing plain text, with boilerplate and hidden regions pruned. |
|
|
1052
|
+
| `click` | `Promise<void>` | Clicks a CSS-selector match, strict by default and requiring it visible and enabled. |
|
|
1053
|
+
| `fill` | `Promise<void>` | Fills an editable input or contenteditable element, strict by default, dispatching input and change events. |
|
|
1054
|
+
| `select` | `Promise<void>` | Selects options on an enabled `select` element, strict by default. |
|
|
1055
|
+
| `evaluate` | `Promise<unknown>` | Evaluates an expression in the frame execution world under the result-size guard. |
|
|
1056
|
+
| `handle` | `Promise<BrowserHandleInterface>` | Evaluates an expression by reference and returns a disposable remote object handle. |
|
|
1057
|
+
| `wait` | `Promise<void>` | Waits for a selector to reach the attached, detached, visible, or hidden state. |
|
|
1058
|
+
| `send` | `Promise<unknown>` | Issues a raw CDP method in the frame's current target session, with a trailing `BrowserSendOptions` carrying a per-call `timeout` overriding the client-wide default. |
|
|
1059
|
+
| `subscribe` | `Promise<void>` | Subscribes to a CDP event in the frame's current target session. |
|
|
1060
|
+
| `unsubscribe` | `Promise<void>` | Removes a frame-session CDP event subscription. |
|
|
1061
|
+
| `save` | `Promise<void>` | Persists bytes through a page writer; a child frame rejects because it owns no writer. |
|
|
1062
|
+
| `assert` | `void` | Throws a coded `BrowserError` when the frame can no longer accept protocol work: a frame throws once the CDP client disconnects, and a page also throws once it closes. Every other member here calls it first. |
|
|
1063
|
+
| `update` | `void` | Records an externally observed URL as the frame's current `url`, which a page calls from its own `Page.frameNavigated` handler. |
|
|
1064
|
+
|
|
1065
|
+
```ts
|
|
1066
|
+
const child = await page.frame('checkout')
|
|
1067
|
+
const title = await child?.title()
|
|
1068
|
+
await child?.wait('form', { state: 'visible' })
|
|
1069
|
+
await child?.fill('[name=email]', 'ada@example.com')
|
|
1070
|
+
await child?.click('button[type=submit]')
|
|
1071
|
+
await child?.select('select', ['business'])
|
|
1072
|
+
const content = await child?.content()
|
|
1073
|
+
const article = await child?.article() // its own HTML capture, distilled to plain text
|
|
1074
|
+
const result = await child?.evaluate('document.readyState')
|
|
1075
|
+
const handle = await child?.handle('document.body')
|
|
1076
|
+
await handle?.dispose()
|
|
1077
|
+
const onLoad = () => log('loaded')
|
|
1078
|
+
await child?.subscribe('Page.loadEventFired', onLoad)
|
|
1079
|
+
await child?.unsubscribe('Page.loadEventFired', onLoad)
|
|
1080
|
+
const root = await child?.send('DOM.getDocument')
|
|
1081
|
+
const tree = await child?.send('DOM.getDocument', { depth: 1 }, { timeout: 5_000 })
|
|
1082
|
+
await page.save('./artifact.bin', new Uint8Array([1, 2, 3]))
|
|
1083
|
+
child?.assert() // throws once the client disconnects, or the page closes
|
|
1084
|
+
child?.update('https://example.com/checkout') // record a URL observed elsewhere
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
#### `BrowserPageInterface`
|
|
1088
|
+
|
|
1089
|
+
A top-level page. Its page/target-specific operations come first, then every
|
|
1090
|
+
member it inherits from `BrowserFrameInterface`, whose own behavior the
|
|
1091
|
+
preceding table states.
|
|
1092
|
+
|
|
1093
|
+
| Method | Returns | Summary |
|
|
1094
|
+
| ------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1095
|
+
| `navigate` | `Promise<BrowserNavigationResult>` | Goes to a URL, waits for the requested load condition, and returns the final URL with its response correlation. |
|
|
1096
|
+
| `reload` | `Promise<BrowserNavigationResult>` | Reloads the page and returns the final URL with its response correlation. |
|
|
1097
|
+
| `back` | `Promise<BrowserNavigationResult>` | Navigates to the previous history entry, or returns the unchanged URL when none exists. |
|
|
1098
|
+
| `forward` | `Promise<BrowserNavigationResult>` | Navigates to the next history entry, or returns the unchanged URL when none exists. |
|
|
1099
|
+
| `screenshot` | `Promise<BrowserScreenshotResult>` | Captures PNG or JPEG bytes, optionally full-page and persisted through an injected writer. |
|
|
1100
|
+
| `pdf` | `Promise<BrowserPDFResult>` | Prints the page to PDF bytes, optionally persisted through the injected writer. |
|
|
1101
|
+
| `frame` | `Promise<BrowserFrameInterface \| undefined>` | Looks up a first-class frame by name or URL. |
|
|
1102
|
+
| `frames` | `Promise<readonly BrowserFrameInterface[]>` | Decodes the flattened frame tree, main frame first. |
|
|
1103
|
+
| `snapshot` | `Promise<BrowserSnapshotInterface>` | Captures and decodes every attached document, shadow root, template content, layout box, and requested computed style. |
|
|
1104
|
+
| `codegen` | `Promise<BrowserCodegenInterface>` | Starts the action recorder, or returns the running one. |
|
|
1105
|
+
| `destroy` | `Promise<void>` | Releases local resources and detaches without closing the remote target. |
|
|
1106
|
+
| `close` | `Promise<void>` | Closes the remote target and releases its resources. |
|
|
1107
|
+
| `title` | `Promise<string>` | Resolves the frame document title. |
|
|
1108
|
+
| `content` | `Promise<BrowserContentResult>` | Extracts the URL, title, HTML, and visible text under the result-size guards. |
|
|
1109
|
+
| `article` | `Promise<string>` | Distills the frame HTML to reader-facing plain text, with boilerplate and hidden regions pruned. |
|
|
1110
|
+
| `click` | `Promise<void>` | Clicks a CSS-selector match, strict by default and requiring it visible and enabled. |
|
|
1111
|
+
| `fill` | `Promise<void>` | Fills an editable input or contenteditable element, strict by default, dispatching input and change events. |
|
|
1112
|
+
| `select` | `Promise<void>` | Selects options on an enabled `select` element, strict by default. |
|
|
1113
|
+
| `evaluate` | `Promise<unknown>` | Evaluates an expression in the frame execution world under the result-size guard. |
|
|
1114
|
+
| `handle` | `Promise<BrowserHandleInterface>` | Evaluates an expression by reference and returns a disposable remote object handle. |
|
|
1115
|
+
| `wait` | `Promise<void>` | Waits for a selector to reach the attached, detached, visible, or hidden state. |
|
|
1116
|
+
| `send` | `Promise<unknown>` | Issues a raw CDP method in the frame's current target session, with a trailing `BrowserSendOptions` carrying a per-call `timeout` overriding the client-wide default. |
|
|
1117
|
+
| `subscribe` | `Promise<void>` | Subscribes to a CDP event in the frame's current target session. |
|
|
1118
|
+
| `unsubscribe` | `Promise<void>` | Removes a frame-session CDP event subscription. |
|
|
1119
|
+
| `save` | `Promise<void>` | Persists bytes through a page writer; a child frame rejects because it owns no writer. |
|
|
1120
|
+
| `assert` | `void` | Throws a coded `BrowserError` when the frame can no longer accept protocol work: a frame throws once the CDP client disconnects, and a page also throws once it closes. Every other member here calls it first. |
|
|
1121
|
+
| `update` | `void` | Records an externally observed URL as the frame's current `url`, which a page calls from its own `Page.frameNavigated` handler. |
|
|
1122
|
+
|
|
1123
|
+
```ts
|
|
1124
|
+
await page.navigate('https://example.com')
|
|
1125
|
+
await page.reload()
|
|
1126
|
+
await page.back()
|
|
1127
|
+
await page.forward()
|
|
1128
|
+
const heading = await page.title()
|
|
1129
|
+
await page.click('#submit')
|
|
1130
|
+
await page.fill('#name', 'Ada')
|
|
1131
|
+
await page.select('#lang', ['en'])
|
|
1132
|
+
const content = await page.content()
|
|
1133
|
+
const result = await page.evaluate('document.title')
|
|
1134
|
+
const shot = await page.screenshot({ full: true, format: 'png' })
|
|
1135
|
+
const pdf = await page.pdf({ landscape: true })
|
|
1136
|
+
const child = await page.frame('checkout') // BrowserFrameInterface | undefined
|
|
1137
|
+
const children = await page.frames() // readonly BrowserFrameInterface[]
|
|
1138
|
+
const snapshot = await page.snapshot({ styles: ['display'], rects: true })
|
|
1139
|
+
await page.close()
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
#### `BrowserSnapshotInterface`
|
|
1143
|
+
|
|
1144
|
+
One page capture as navigable data. Its `readonly` members — `documents`
|
|
1145
|
+
and `styles`, inherited from the Surface `BrowserSnapshotInput` row — are the
|
|
1146
|
+
entire serialized form; every method that follows derives structure from them on
|
|
1147
|
+
demand, storing nothing that could drift. Nodes stay
|
|
1148
|
+
plain `BrowserNode` data — passed in as arguments and handed back unwrapped —
|
|
1149
|
+
so a snapshot survives `JSON.stringify` and comes back through
|
|
1150
|
+
`createBrowserSnapshot`. Walks are lazy generators, so `find` stops at the
|
|
1151
|
+
first match and `filter` stops at its limit.
|
|
1152
|
+
|
|
1153
|
+
| Method | Returns | Summary |
|
|
1154
|
+
| ------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1155
|
+
| `walk` | `Generator<BrowserNode, void, unknown>` | Traverses the whole capture, or one subtree when `root` is given and yielded first, in `'depth'` order by default or in `'breadth'` order. Visits each node exactly once. |
|
|
1156
|
+
| `descendants` | `Generator<BrowserNode, void, unknown>` | Traverses one node's subtree in depth-first order, excluding the node itself. |
|
|
1157
|
+
| `document` | `BrowserDocument \| undefined` | Resolves the captured document a node belongs to. |
|
|
1158
|
+
| `children` | `readonly BrowserNode[]` | Returns the direct children of a node, entering a linked iframe's content document. |
|
|
1159
|
+
| `parent` | `BrowserNode \| undefined` | Returns the structural parent of a node, crossing a document boundary to the owning iframe. |
|
|
1160
|
+
| `siblings` | `readonly BrowserNode[]` | Returns the structural siblings of a node; `'preceding'` or `'following'` narrows to one side, and omitting the relation returns every sibling but the node itself. |
|
|
1161
|
+
| `ancestors` | `readonly BrowserNode[]` | Returns the ancestors of a node, nearest first, across document and iframe boundaries. |
|
|
1162
|
+
| `common` | `BrowserNode \| undefined` | Returns the nearest common ancestor of two nodes, counting each node as its own candidate. |
|
|
1163
|
+
| `distance` | `number \| undefined` | Returns the structural edge count between two nodes, or `undefined` when they share no ancestor. |
|
|
1164
|
+
| `find` | `BrowserNode \| undefined` | Returns the first node matching a `BrowserNodeQuery` or a `BrowserNodePredicate`. |
|
|
1165
|
+
| `filter` | `readonly BrowserNode[]` | Returns every matching node, bounded by an optional `limit`; a negative or fractional limit throws a coded `BrowserError`. |
|
|
1166
|
+
| `closest` | `BrowserNode \| undefined` | Returns the nearest match from a node through its ancestors, testing the node first. |
|
|
1167
|
+
| `path` | `string` | Returns a deterministic frame-qualified structural path for one node. |
|
|
1168
|
+
|
|
1169
|
+
```ts
|
|
1170
|
+
import type { BrowserSnapshotInput } from '@orkestrel/browser'
|
|
1171
|
+
import { createBrowserSnapshot, matchesBrowserNode } from '@orkestrel/browser'
|
|
1172
|
+
|
|
1173
|
+
const captured = await page.snapshot({ styles: ['display'], rects: true })
|
|
1174
|
+
const stored: BrowserSnapshotInput = JSON.parse(JSON.stringify(captured)) // { documents, styles }
|
|
1175
|
+
const snapshot = createBrowserSnapshot(stored) // navigable again, same data
|
|
1176
|
+
|
|
1177
|
+
const main = snapshot.find({ name: 'main', visible: true }) // declarative query
|
|
1178
|
+
const heading = snapshot.find((node) => node.name === 'H1') // predicate
|
|
1179
|
+
const clickable = snapshot.filter({ clickable: true }, 20) // first 20 matches
|
|
1180
|
+
|
|
1181
|
+
if (main !== undefined && heading !== undefined) {
|
|
1182
|
+
snapshot.document(main)?.url // the document holding a node
|
|
1183
|
+
snapshot.children(main) // direct children, entering iframe content
|
|
1184
|
+
snapshot.parent(heading) // structural parent, iframe owner included
|
|
1185
|
+
snapshot.siblings(heading, 'preceding') // one structural side
|
|
1186
|
+
snapshot.ancestors(heading) // nearest-first, across frames
|
|
1187
|
+
snapshot.common(main, heading) // nearest shared ancestor
|
|
1188
|
+
snapshot.distance(main, heading) // structural edge count
|
|
1189
|
+
snapshot.closest(heading, { name: 'section' }) // self, then ancestors
|
|
1190
|
+
snapshot.path(heading) // frame("frame-main") > #document:0 > html:1 > ...
|
|
1191
|
+
|
|
1192
|
+
const perLevel = [...snapshot.walk({ root: main, order: 'breadth' })]
|
|
1193
|
+
const links = [...snapshot.descendants(main)].filter((node) =>
|
|
1194
|
+
matchesBrowserNode(node, { name: 'a', visible: true }),
|
|
1195
|
+
) // subtree search: descendants + matchesBrowserNode
|
|
1196
|
+
}
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
#### `BrowserCodegenInterface`
|
|
1200
|
+
|
|
1201
|
+
Records page interactions as a session runs, for later compilation into a
|
|
1202
|
+
replayable script.
|
|
1203
|
+
|
|
1204
|
+
| Method | Returns | Summary |
|
|
1205
|
+
| --------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1206
|
+
| `start` | `Promise<void>` | Begins recording on the page's session. A call after teardown is a silent no-op, because a torn-down recorder cannot be restarted and a fresh one is obtained through the page. |
|
|
1207
|
+
| `stop` | `Promise<readonly BrowserCodegenAction[]>` | Stops recording and returns the captured actions. |
|
|
1208
|
+
| `actions` | `readonly BrowserCodegenAction[]` | Returns the current normalized action list. |
|
|
1209
|
+
| `script` | `string` | Compiles the captured actions into a script. |
|
|
1210
|
+
| `clear` | `void` | Resets the captured action list. |
|
|
1211
|
+
| `destroy` | `Promise<void>` | Tears down the recorder and detaches its CDP listeners. |
|
|
1212
|
+
|
|
1213
|
+
```ts
|
|
1214
|
+
const codegen = await page.codegen()
|
|
1215
|
+
await page.click('#next')
|
|
1216
|
+
const actions = await codegen.stop()
|
|
1217
|
+
const script = codegen.script({ language: 'typescript' })
|
|
1218
|
+
codegen.clear() // reset the captured action list
|
|
1219
|
+
await codegen.destroy()
|
|
1220
|
+
```
|
|
1221
|
+
|
|
1222
|
+
#### `BrowserTransitionInterface`
|
|
1223
|
+
|
|
1224
|
+
One asynchronous transition at a time, shared by every caller that joins it
|
|
1225
|
+
while it runs. An entity keeps its own entry guards — what makes a transition
|
|
1226
|
+
unnecessary is the entity's own state — and holds one `BrowserTransition` per
|
|
1227
|
+
transition, so the in-flight identity check is written once instead of once per
|
|
1228
|
+
lifecycle.
|
|
1229
|
+
|
|
1230
|
+
| Method | Returns | Summary |
|
|
1231
|
+
| --------- | ------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
1232
|
+
| `execute` | `Promise<T>` | Starts the work when nothing is in flight, and otherwise joins the running transition and returns its result. |
|
|
1233
|
+
|
|
1234
|
+
```ts
|
|
1235
|
+
import { BrowserTransition } from '@orkestrel/browser'
|
|
1236
|
+
|
|
1237
|
+
const starting = new BrowserTransition()
|
|
1238
|
+
await starting.execute(() => transport.start())
|
|
1239
|
+
const joined = starting.pending // the in-flight promise, or undefined
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1242
|
+
#### `BrowserInterface`
|
|
1243
|
+
|
|
1244
|
+
Browser wrapper with discovery, connection management, and lifecycle control.
|
|
1245
|
+
Connection strategy (executed by `connect()`): explicit `cdp.endpoint` →
|
|
1246
|
+
passive discovery on `cdp.port` → launch a new process.
|
|
1247
|
+
|
|
1248
|
+
| Method | Returns | Summary |
|
|
1249
|
+
| ------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1250
|
+
| `discover` | `Promise<BrowserDiscoveryResult>` | Probes CDP passively, changing no connection state and neither launching nor attaching, and emits a `discover` event with the result. |
|
|
1251
|
+
| `connect` | `Promise<void>` | Establishes a connection through the endpoint, then discovery, then a launch. Idempotent. |
|
|
1252
|
+
| `adopt` | `void` | Assumes responsibility for terminating the connected browser. |
|
|
1253
|
+
| `disconnect` | `Promise<void>` | Detaches the client-side transport while the remote browser keeps running. A merely attached CDP session forgets the endpoint and its ownership becomes `undefined`. A launched or explicitly adopted session retains ownership and its endpoint, so the same instance can reconnect and stays responsible for eventual termination. Transport loss while an owned browser remains alive is resumable the same way. |
|
|
1254
|
+
| `context` | `BrowserContextInterface \| undefined` | Returns one context by index, or the first. |
|
|
1255
|
+
| `contexts` | `readonly BrowserContextInterface[]` | Returns every context. |
|
|
1256
|
+
| `isolate` | `Promise<BrowserContextInterface>` | Creates and registers an isolated CDP context with validated proxy, download, origin, and emulation options. |
|
|
1257
|
+
| `create` | `Promise<BrowserPageInterface>` | Opens a page in the default context. |
|
|
1258
|
+
| `destroy` | `Promise<void>` | Releases local resources. A launched browser has the process serving its CDP endpoint terminated and its exit awaited — on POSIX that terminate reaches the launch's whole process group and awaits its drain, and on Windows it terminates one process by identifier, the spawned process or the one a launcher handed the endpoint to — which leaves the profile unlocked before cleanup. An adopted attachment is sent CDP `Browser.close`. A merely attached browser is detached locally and nothing more, because other clients may share its targets. Idempotent. |
|
|
1259
|
+
| `close` | `Promise<void>` | Shuts the remote browser down: sends CDP `Browser.close` best-effort whether attached or owned, and for an owned browser also awaits the exit of the process serving the CDP endpoint plus its POSIX process-group drain, escalating to a kill only where needed. Then closes every tracked context and page, sending remote `Target.closeTarget` and `disposeBrowserContext` whatever the ownership, before releasing the CDP client. This is the way to shut down a browser the instance does not own and still wants terminated. |
|
|
1260
|
+
|
|
1261
|
+
```ts
|
|
1262
|
+
import { createBrowser } from '@orkestrel/browser/server'
|
|
1263
|
+
|
|
1264
|
+
const browser = createBrowser({ profile: './profile', cdp: { port: 9222 } })
|
|
1265
|
+
browser.emitter.on('connect', (mode) => log(mode))
|
|
1266
|
+
await browser.connect()
|
|
1267
|
+
const owned = browser.owned // true for this launched session
|
|
1268
|
+
const page = await browser.create({ url: 'https://example.com' })
|
|
1269
|
+
const isolated = await browser.isolate({ emulation: { locale: 'en-US' } })
|
|
1270
|
+
const all = browser.contexts() // readonly BrowserContextInterface[]
|
|
1271
|
+
const pid = browser.pid // number | undefined — the process serving the CDP endpoint, when this instance owns one
|
|
1272
|
+
await browser.disconnect() // retains ownership and endpoint for this persistent launch
|
|
1273
|
+
await browser.connect() // reconnect the same owner
|
|
1274
|
+
await isolated.close()
|
|
1275
|
+
await browser.destroy() // terminates and awaits the owned process
|
|
1276
|
+
```
|
|
1277
|
+
|
|
1278
|
+
#### `BrowserWebSocketInterface`
|
|
1279
|
+
|
|
1280
|
+
One WebSocket connection a page's network manager reconstructs from
|
|
1281
|
+
Network-domain events. The manager owns the connection and drives every method
|
|
1282
|
+
here; a consumer reads `id` and `url` and subscribes through `emitter`.
|
|
1283
|
+
|
|
1284
|
+
| Method | Returns | Summary |
|
|
1285
|
+
| ---------- | ------- | ---------------------------------------------------------------------------------------------- |
|
|
1286
|
+
| `receive` | `void` | Reports one received frame. The page's network manager drives it. |
|
|
1287
|
+
| `transmit` | `void` | Reports one sent frame. The page's network manager drives it. |
|
|
1288
|
+
| `fail` | `void` | Reports a connection fault. The page's network manager drives it. |
|
|
1289
|
+
| `close` | `void` | Reports the connection closing and destroys the emitter. The page's network manager drives it. |
|
|
1290
|
+
|
|
1291
|
+
```ts
|
|
1292
|
+
page.network.emitter.on('socket', (socket) => {
|
|
1293
|
+
log(socket.id, socket.url)
|
|
1294
|
+
socket.emitter.on('receive', (frame) => log(frame.data))
|
|
1295
|
+
socket.emitter.on('transmit', (frame) => log(frame.data))
|
|
1296
|
+
socket.emitter.on('error', (message) => log(message))
|
|
1297
|
+
socket.emitter.on('close', (timestamp) => log(timestamp))
|
|
1298
|
+
})
|
|
1299
|
+
// The page's network manager drives the connection from Network-domain events:
|
|
1300
|
+
socket.receive({ opcode: 1, data: 'pong', masked: false, timestamp: 4 })
|
|
1301
|
+
socket.transmit({ opcode: 1, data: 'ping', masked: false, timestamp: 3 })
|
|
1302
|
+
socket.fail('handshake rejected')
|
|
1303
|
+
socket.close(6)
|
|
1304
|
+
```
|
|
1305
|
+
|
|
1306
|
+
#### `BrowserDownloadInterface`
|
|
1307
|
+
|
|
1308
|
+
One context download tracked through Chromium's Browser domain. The owning page
|
|
1309
|
+
drives `update` from `Browser.downloadProgress`; a consumer calls `cancel` and
|
|
1310
|
+
reads the observed state.
|
|
1311
|
+
|
|
1312
|
+
| Method | Returns | Summary |
|
|
1313
|
+
| -------- | --------------- | -------------------------------------------------------------------------------------------------------- |
|
|
1314
|
+
| `cancel` | `Promise<void>` | Sends CDP `Browser.cancelDownload` for this download, and is ignored unless the status is still pending. |
|
|
1315
|
+
| `update` | `void` | Records one step of the download's progress. The owning page drives it. |
|
|
1316
|
+
|
|
1317
|
+
```ts
|
|
1318
|
+
page.emitter.on('download', (download) => {
|
|
1319
|
+
log(download.id, download.url, download.name)
|
|
1320
|
+
download.emitter.on('progress', (received, total) => log(received, total))
|
|
1321
|
+
download.emitter.on('complete', (path) => log(path))
|
|
1322
|
+
download.emitter.on('cancel', () => log('cancelled'))
|
|
1323
|
+
})
|
|
1324
|
+
// The owning page drives progress from Browser.downloadProgress:
|
|
1325
|
+
download.update({ status: 'pending', received: 512, total: 2_048 })
|
|
1326
|
+
download.update({ status: 'complete', received: 2_048, total: 2_048, path: './report.pdf' })
|
|
1327
|
+
await download.cancel() // ignored once the download settled
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
#### `BrowserWriterInterface`
|
|
1331
|
+
|
|
1332
|
+
The pluggable sink a page persists captured bytes through. Core never touches a
|
|
1333
|
+
filesystem; server supplies `FileBrowserWriter`.
|
|
1334
|
+
|
|
1335
|
+
| Method | Returns | Summary |
|
|
1336
|
+
| ------- | --------------- | ------------------------------------------------------------------------------- |
|
|
1337
|
+
| `write` | `Promise<void>` | Persists the captured bytes to the given path, creating its parent directories. |
|
|
1338
|
+
|
|
1339
|
+
```ts
|
|
1340
|
+
import { FileBrowserWriter } from '@orkestrel/browser/server'
|
|
1341
|
+
|
|
1342
|
+
const writer = new FileBrowserWriter()
|
|
1343
|
+
await writer.write('shots/hero.png', new Uint8Array([137, 80, 78, 71]))
|
|
1344
|
+
```
|
|
1345
|
+
|
|
1346
|
+
#### `BrowserNavigationManagerInterface`
|
|
1347
|
+
|
|
1348
|
+
Waits for a navigation the page performs on its own, rather than one the caller
|
|
1349
|
+
started.
|
|
1350
|
+
|
|
1351
|
+
| Method | Returns | Summary |
|
|
1352
|
+
| ------- | ------------------ | -------------------------------------------------------------------------------------------------------- |
|
|
1353
|
+
| `wait` | `Promise<string>` | Resolves with the URL of the next navigation matching the `*` and `**` glob pattern. Rejects on timeout. |
|
|
1354
|
+
| `until` | `Promise<unknown>` | Polls an expression in the page until it returns a truthy value, and resolves with that value. |
|
|
1355
|
+
|
|
1356
|
+
```ts
|
|
1357
|
+
const navigated = page.navigation.wait('**/checkout')
|
|
1358
|
+
await page.click('#buy')
|
|
1359
|
+
log(await navigated)
|
|
1360
|
+
await page.navigation.until('document.readyState === "complete"')
|
|
1361
|
+
```
|
|
1362
|
+
|
|
1363
|
+
#### `BrowserHandleInterface`
|
|
1364
|
+
|
|
1365
|
+
A retained remote JavaScript object. Release it with `dispose` when done.
|
|
1366
|
+
|
|
1367
|
+
| Method | Returns | Summary |
|
|
1368
|
+
| ------------ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
1369
|
+
| `value` | `Promise<unknown>` | Reads the object back by value. |
|
|
1370
|
+
| `call` | `Promise<unknown>` | Runs a function declaration with the handle as `this`, by value. |
|
|
1371
|
+
| `property` | `Promise<BrowserHandleInterface \| undefined>` | Retains one own property as its own handle, or returns `undefined` when the property is absent. |
|
|
1372
|
+
| `properties` | `Promise<Readonly<Record<string, unknown>>>` | Reads every own property by value. |
|
|
1373
|
+
| `dispose` | `Promise<void>` | Releases the retained remote object. Idempotent. |
|
|
1374
|
+
|
|
1375
|
+
```ts
|
|
1376
|
+
const handle = await page.handle('document.body')
|
|
1377
|
+
log(await handle.value())
|
|
1378
|
+
log(await handle.call('function() { return this.tagName }'))
|
|
1379
|
+
const dataset = await handle.property('dataset')
|
|
1380
|
+
log(await handle.properties())
|
|
1381
|
+
await dataset?.dispose()
|
|
1382
|
+
await handle.dispose()
|
|
1383
|
+
```
|
|
1384
|
+
|
|
1385
|
+
#### `BrowserScriptManagerInterface`
|
|
1386
|
+
|
|
1387
|
+
Installs new-document scripts and exposes host functions into page JavaScript.
|
|
1388
|
+
|
|
1389
|
+
| Method | Returns | Summary |
|
|
1390
|
+
| --------- | ----------------- | ------------------------------------------------------------------------------ |
|
|
1391
|
+
| `add` | `Promise<string>` | Installs a script evaluated on every new document, and returns its identifier. |
|
|
1392
|
+
| `remove` | `Promise<void>` | Removes one installed script by identifier. |
|
|
1393
|
+
| `expose` | `Promise<void>` | Binds a host function to a page-global name, callable from page JavaScript. |
|
|
1394
|
+
| `revoke` | `Promise<void>` | Removes one exposed binding and its installed bridge script. |
|
|
1395
|
+
| `destroy` | `Promise<void>` | Removes every installed script and binding this manager owns. |
|
|
1396
|
+
|
|
1397
|
+
```ts
|
|
1398
|
+
const id = await page.scripts.add('window.__seeded = true')
|
|
1399
|
+
await page.scripts.expose('add', (a, b) => Number(a) + Number(b))
|
|
1400
|
+
log(await page.evaluate('add(1, 2)'))
|
|
1401
|
+
await page.scripts.revoke('add')
|
|
1402
|
+
await page.scripts.remove(id)
|
|
1403
|
+
await page.scripts.destroy()
|
|
1404
|
+
```
|
|
1405
|
+
|
|
1406
|
+
#### `BrowserAccessibilityInterface`
|
|
1407
|
+
|
|
1408
|
+
Reads the page's accessibility tree as a serializable snapshot.
|
|
1409
|
+
|
|
1410
|
+
| Method | Returns | Summary |
|
|
1411
|
+
| ---------- | --------------------------------------- | ------------------------------------------------------------------------------ |
|
|
1412
|
+
| `snapshot` | `Promise<BrowserAccessibilitySnapshot>` | Reads the full accessibility tree, optionally pruned to the interesting nodes. |
|
|
1413
|
+
|
|
1414
|
+
```ts
|
|
1415
|
+
const tree = await page.accessibility.snapshot({ interesting: true })
|
|
1416
|
+
log(tree.nodes.map((node) => node.name))
|
|
1417
|
+
```
|
|
1418
|
+
|
|
1419
|
+
#### `BrowserTracingInterface`
|
|
1420
|
+
|
|
1421
|
+
Captures a Chromium trace streamed back through the IO domain.
|
|
1422
|
+
|
|
1423
|
+
| Method | Returns | Summary |
|
|
1424
|
+
| --------- | ------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
1425
|
+
| `start` | `Promise<void>` | Begins tracing with the given categories. Throws a `BrowserError` when a trace is already active. |
|
|
1426
|
+
| `stop` | `Promise<BrowserTracingResult>` | Ends tracing, drains the IO stream, and writes it through the page writer when a path was set. |
|
|
1427
|
+
| `destroy` | `Promise<void>` | Stops an active trace, discarding any failure, and does nothing when no trace is running. |
|
|
1428
|
+
|
|
1429
|
+
```ts
|
|
1430
|
+
await page.diagnostics.tracing.start({ screenshots: true })
|
|
1431
|
+
const trace = await page.diagnostics.tracing.stop() // { bytes, path }
|
|
1432
|
+
await page.diagnostics.tracing.destroy()
|
|
1433
|
+
```
|
|
1434
|
+
|
|
1435
|
+
#### `BrowserCoverageInterface`
|
|
1436
|
+
|
|
1437
|
+
Collects JavaScript precise coverage and CSS rule usage together.
|
|
1438
|
+
|
|
1439
|
+
| Method | Returns | Summary |
|
|
1440
|
+
| --------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
1441
|
+
| `start` | `Promise<void>` | Arms the requested domains. Throws a `BrowserError` when collection is already active or when neither domain is requested. |
|
|
1442
|
+
| `stop` | `Promise<BrowserCoverageResult>` | Reads the collected usage and disarms every domain it armed. |
|
|
1443
|
+
| `destroy` | `Promise<void>` | Stops an active collector, discarding any failure, and does nothing when no collection is running. |
|
|
1444
|
+
|
|
1445
|
+
```ts
|
|
1446
|
+
await page.diagnostics.coverage.start({ javascript: true, css: true })
|
|
1447
|
+
const usage = await page.diagnostics.coverage.stop() // { scripts, styles }
|
|
1448
|
+
await page.diagnostics.coverage.destroy()
|
|
1449
|
+
```
|
|
1450
|
+
|
|
1451
|
+
#### `BrowserPerformanceInterface`
|
|
1452
|
+
|
|
1453
|
+
Reads Performance-domain metrics for one frame.
|
|
1454
|
+
|
|
1455
|
+
| Method | Returns | Summary |
|
|
1456
|
+
| --------- | ----------------------------------- | ---------------------------------------------------------------------- |
|
|
1457
|
+
| `metrics` | `Promise<readonly BrowserMetric[]>` | Enables the domain, reads every metric, and disables the domain again. |
|
|
1458
|
+
|
|
1459
|
+
```ts
|
|
1460
|
+
const metrics = await page.diagnostics.performance.metrics()
|
|
1461
|
+
log(metrics.map((metric) => [metric.name, metric.value]))
|
|
1462
|
+
```
|
|
1463
|
+
|
|
1464
|
+
#### `BrowserProfilerInterface`
|
|
1465
|
+
|
|
1466
|
+
Records a sampled JavaScript CPU profile.
|
|
1467
|
+
|
|
1468
|
+
| Method | Returns | Summary |
|
|
1469
|
+
| --------- | ------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
1470
|
+
| `start` | `Promise<void>` | Begins sampling, optionally at an explicit positive integer interval in microseconds. |
|
|
1471
|
+
| `stop` | `Promise<BrowserProfile>` | Ends sampling and decodes the profile's nodes, samples, and time deltas. |
|
|
1472
|
+
| `destroy` | `Promise<void>` | Stops an active profiler, discarding any failure, and does nothing when no profile is running. |
|
|
1473
|
+
|
|
1474
|
+
```ts
|
|
1475
|
+
await page.diagnostics.profiler.start(100)
|
|
1476
|
+
const profile = await page.diagnostics.profiler.stop() // { start, end, nodes, samples, deltas }
|
|
1477
|
+
await page.diagnostics.profiler.destroy()
|
|
1478
|
+
```
|
|
1479
|
+
|
|
1480
|
+
#### `BrowserDiagnosticsInterface`
|
|
1481
|
+
|
|
1482
|
+
Groups the per-page diagnostics capabilities and owns their teardown. `tracing`,
|
|
1483
|
+
`coverage`, `performance`, and `profiler` are Surface data members.
|
|
1484
|
+
|
|
1485
|
+
| Method | Returns | Summary |
|
|
1486
|
+
| --------- | --------------- | --------------------------------------------------------------- |
|
|
1487
|
+
| `destroy` | `Promise<void>` | Tears down every diagnostics capability this page's group owns. |
|
|
1488
|
+
|
|
1489
|
+
```ts
|
|
1490
|
+
await page.diagnostics.destroy()
|
|
1491
|
+
```
|
|
1492
|
+
|
|
1493
|
+
#### `BrowserClockInterface`
|
|
1494
|
+
|
|
1495
|
+
Controls Chromium virtual time so page timers become deterministic.
|
|
1496
|
+
|
|
1497
|
+
| Method | Returns | Summary |
|
|
1498
|
+
| ----------- | --------------- | -------------------------------------------------------------------------------------- |
|
|
1499
|
+
| `install` | `Promise<void>` | Takes over the page clock, optionally seeding it with an epoch time. |
|
|
1500
|
+
| `pause` | `Promise<void>` | Suspends virtual time so no page timer advances. |
|
|
1501
|
+
| `resume` | `Promise<void>` | Continues virtual time after a pause. |
|
|
1502
|
+
| `advance` | `Promise<void>` | Moves virtual time forward by the given milliseconds, firing the timers that fall due. |
|
|
1503
|
+
| `uninstall` | `Promise<void>` | Returns the page to the real clock, and does nothing when no clock was installed. |
|
|
1504
|
+
|
|
1505
|
+
```ts
|
|
1506
|
+
await page.clock.install(Date.parse('2026-01-01T00:00:00Z'))
|
|
1507
|
+
await page.clock.pause()
|
|
1508
|
+
await page.clock.advance(5_000)
|
|
1509
|
+
await page.clock.resume()
|
|
1510
|
+
await page.clock.uninstall()
|
|
1511
|
+
```
|
|
1512
|
+
|
|
1513
|
+
#### `BrowserLocatorInterface`
|
|
1514
|
+
|
|
1515
|
+
A lazily resolved element query. Every accessor returns a new locator rather than
|
|
1516
|
+
mutating this one, and every action re-resolves the query before acting.
|
|
1517
|
+
|
|
1518
|
+
| Method | Returns | Summary |
|
|
1519
|
+
| ------------ | --------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
1520
|
+
| `locator` | `BrowserLocatorInterface` | Narrows to a descendant matching the CSS selector. |
|
|
1521
|
+
| `filter` | `BrowserLocatorInterface` | Narrows to the matches satisfying the filter. |
|
|
1522
|
+
| `first` | `BrowserLocatorInterface` | Narrows to the first match. |
|
|
1523
|
+
| `last` | `BrowserLocatorInterface` | Narrows to the last match. |
|
|
1524
|
+
| `item` | `BrowserLocatorInterface` | Narrows to the match at the given index. |
|
|
1525
|
+
| `count` | `Promise<number>` | Counts the current matches. |
|
|
1526
|
+
| `all` | `Promise<readonly BrowserLocatorInterface[]>` | Resolves one indexed locator per current match. |
|
|
1527
|
+
| `click` | `Promise<void>` | Clicks the match with trusted input after its actionability checks pass. |
|
|
1528
|
+
| `fill` | `Promise<void>` | Replaces the match's value with the given text. |
|
|
1529
|
+
| `select` | `Promise<void>` | Selects the given option values on the match. |
|
|
1530
|
+
| `check` | `Promise<void>` | Clicks the match unless it already reports checked. |
|
|
1531
|
+
| `uncheck` | `Promise<void>` | Clicks the match unless it already reports unchecked. |
|
|
1532
|
+
| `hover` | `Promise<void>` | Moves trusted pointer input over the match. |
|
|
1533
|
+
| `focus` | `Promise<void>` | Gives the match keyboard focus. |
|
|
1534
|
+
| `press` | `Promise<void>` | Focuses the match and presses one key or chord. |
|
|
1535
|
+
| `type` | `Promise<void>` | Focuses the match and types the value one key at a time. |
|
|
1536
|
+
| `clear` | `Promise<void>` | Empties the match's value. |
|
|
1537
|
+
| `wait` | `Promise<void>` | Waits until the match reaches the requested state. Rejects on timeout. |
|
|
1538
|
+
| `text` | `Promise<string>` | Reads the first match's rendered text. |
|
|
1539
|
+
| `texts` | `Promise<readonly string[]>` | Reads the rendered text of every match. |
|
|
1540
|
+
| `html` | `Promise<string>` | Reads the first match's inner HTML. |
|
|
1541
|
+
| `value` | `Promise<string>` | Reads the first match's form value. |
|
|
1542
|
+
| `attribute` | `Promise<string \| undefined>` | Reads one attribute of the first match, or returns `undefined` when the match carries none. |
|
|
1543
|
+
| `visible` | `Promise<boolean>` | Reports whether the first match renders a non-empty box. |
|
|
1544
|
+
| `enabled` | `Promise<boolean>` | Reports whether the first match accepts input. |
|
|
1545
|
+
| `editable` | `Promise<boolean>` | Reports whether the first match accepts typed text. |
|
|
1546
|
+
| `screenshot` | `Promise<BrowserScreenshotResult>` | Captures the first match's box, persisting it through the page writer when a path is given. |
|
|
1547
|
+
| `upload` | `Promise<void>` | Sets the file selection on the matched file input. |
|
|
1548
|
+
| `drag` | `Promise<void>` | Drags the match onto the target locator with trusted pointer input. |
|
|
1549
|
+
|
|
1550
|
+
```ts
|
|
1551
|
+
const rows = page.selectors.role('row')
|
|
1552
|
+
log(await rows.count())
|
|
1553
|
+
const first = rows.first()
|
|
1554
|
+
const last = rows.last()
|
|
1555
|
+
const second = rows.item(1)
|
|
1556
|
+
const named = rows.filter({ text: 'Ada' }).locator('td')
|
|
1557
|
+
for (const row of await rows.all()) log(await row.text())
|
|
1558
|
+
log(await named.texts(), await named.html(), await named.value())
|
|
1559
|
+
log(await named.attribute('data-id'))
|
|
1560
|
+
log(await named.visible(), await named.enabled(), await named.editable())
|
|
1561
|
+
await named.wait({ state: 'visible' })
|
|
1562
|
+
await named.click()
|
|
1563
|
+
await named.hover()
|
|
1564
|
+
await named.focus()
|
|
1565
|
+
await named.fill('Ada')
|
|
1566
|
+
await named.clear()
|
|
1567
|
+
await named.type('Grace')
|
|
1568
|
+
await named.press('Enter')
|
|
1569
|
+
await named.select(['us'])
|
|
1570
|
+
await named.check()
|
|
1571
|
+
await named.uncheck()
|
|
1572
|
+
await named.upload({ files: ['./avatar.png'] })
|
|
1573
|
+
await named.screenshot({ path: './row.png' })
|
|
1574
|
+
await first.drag(last)
|
|
1575
|
+
```
|
|
1576
|
+
|
|
1577
|
+
#### `BrowserSelectorManagerInterface`
|
|
1578
|
+
|
|
1579
|
+
Creates one locator per selector semantics. Every accessor is pure — it builds a
|
|
1580
|
+
query and performs no protocol call.
|
|
1581
|
+
|
|
1582
|
+
| Method | Returns | Summary |
|
|
1583
|
+
| ------------- | ------------------------- | ------------------------------------------------------------------ |
|
|
1584
|
+
| `css` | `BrowserLocatorInterface` | Locates by CSS selector. |
|
|
1585
|
+
| `role` | `BrowserLocatorInterface` | Locates by ARIA role, optionally by accessible name and exactness. |
|
|
1586
|
+
| `text` | `BrowserLocatorInterface` | Locates by rendered text, optionally exact. |
|
|
1587
|
+
| `label` | `BrowserLocatorInterface` | Locates a labelled control by its label text, optionally exact. |
|
|
1588
|
+
| `placeholder` | `BrowserLocatorInterface` | Locates an input by its placeholder text, optionally exact. |
|
|
1589
|
+
| `testId` | `BrowserLocatorInterface` | Locates by the test-id attribute. |
|
|
1590
|
+
|
|
1591
|
+
```ts
|
|
1592
|
+
await page.selectors.css('#hero').click()
|
|
1593
|
+
await page.selectors.role('button', { name: 'Save', exact: true }).click()
|
|
1594
|
+
await page.selectors.text('Continue').click()
|
|
1595
|
+
await page.selectors.label('Email', { exact: true }).fill('ada@example.com')
|
|
1596
|
+
await page.selectors.placeholder('Search').fill('browser')
|
|
1597
|
+
await page.selectors.testId('checkout').click()
|
|
1598
|
+
```
|
|
1599
|
+
|
|
1600
|
+
#### `BrowserKeyboardInterface`
|
|
1601
|
+
|
|
1602
|
+
Sends trusted keyboard input on the frame's own session. Held modifiers persist
|
|
1603
|
+
between calls until released.
|
|
1604
|
+
|
|
1605
|
+
| Method | Returns | Summary |
|
|
1606
|
+
| -------- | --------------- | --------------------------------------------------------------------------------------------------------- |
|
|
1607
|
+
| `down` | `Promise<void>` | Presses one key and holds it, retaining it in the modifier mask when it is a modifier. |
|
|
1608
|
+
| `up` | `Promise<void>` | Releases one key, dropping it from the modifier mask even when the release frame fails. |
|
|
1609
|
+
| `press` | `Promise<void>` | Presses a chord: holds its modifiers, presses and releases its terminal key, then releases the modifiers. |
|
|
1610
|
+
| `type` | `Promise<void>` | Types a string as one press and release per character. |
|
|
1611
|
+
| `insert` | `Promise<void>` | Inserts composed text in one frame, firing no per-key events. |
|
|
1612
|
+
|
|
1613
|
+
```ts
|
|
1614
|
+
await page.keyboard.down('Shift')
|
|
1615
|
+
await page.keyboard.up('Shift')
|
|
1616
|
+
await page.keyboard.press('Control+Enter')
|
|
1617
|
+
await page.keyboard.type('orkestrel', { delay: 10 })
|
|
1618
|
+
await page.keyboard.insert('pasted text')
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
#### `BrowserMouseInterface`
|
|
1622
|
+
|
|
1623
|
+
Sends trusted mouse input on the frame's own session, tracking the pointer
|
|
1624
|
+
position and the pressed-button mask between calls.
|
|
1625
|
+
|
|
1626
|
+
| Method | Returns | Summary |
|
|
1627
|
+
| ------- | --------------- | -------------------------------------------------------------------------------------------- |
|
|
1628
|
+
| `move` | `Promise<void>` | Moves the pointer to a point, carrying the pressed buttons. |
|
|
1629
|
+
| `down` | `Promise<void>` | Presses a button at the current point, adding it to the pressed mask. |
|
|
1630
|
+
| `up` | `Promise<void>` | Releases a button at the current point, dropping it from the mask even when the frame fails. |
|
|
1631
|
+
| `click` | `Promise<void>` | Moves to the given point, presses, optionally delays, and releases. |
|
|
1632
|
+
| `drag` | `Promise<void>` | Presses at the start, moves in the requested steps to the end, and releases. |
|
|
1633
|
+
| `wheel` | `Promise<void>` | Sends a wheel delta at the current point. |
|
|
1634
|
+
|
|
1635
|
+
```ts
|
|
1636
|
+
await page.mouse.move({ x: 50, y: 20 })
|
|
1637
|
+
await page.mouse.down('left')
|
|
1638
|
+
await page.mouse.up('left')
|
|
1639
|
+
await page.mouse.click({ x: 50, y: 20 }, { button: 'left', count: 2 })
|
|
1640
|
+
await page.mouse.drag({ x: 10, y: 10 }, { x: 90, y: 90 }, { steps: 20 })
|
|
1641
|
+
await page.mouse.wheel({ x: 0, y: -120 })
|
|
1642
|
+
```
|
|
1643
|
+
|
|
1644
|
+
#### `BrowserTouchInterface`
|
|
1645
|
+
|
|
1646
|
+
Sends trusted touch input on the frame's own session.
|
|
1647
|
+
|
|
1648
|
+
| Method | Returns | Summary |
|
|
1649
|
+
| ------ | --------------- | --------------------------------------------------------------------------------------- |
|
|
1650
|
+
| `tap` | `Promise<void>` | Dispatches a touch start at the point and a touch end, cancelling the touch on failure. |
|
|
1651
|
+
|
|
1652
|
+
```ts
|
|
1653
|
+
await page.touch.tap({ x: 120, y: 240 })
|
|
1654
|
+
```
|
|
1655
|
+
|
|
1656
|
+
#### `BrowserDialogInterface`
|
|
1657
|
+
|
|
1658
|
+
One JavaScript dialog awaiting a decision. `category`, `message`, and `default`
|
|
1659
|
+
are Surface data members.
|
|
1660
|
+
|
|
1661
|
+
| Method | Returns | Summary |
|
|
1662
|
+
| --------- | --------------- | ---------------------------------------------------------------------------------------- |
|
|
1663
|
+
| `accept` | `Promise<void>` | Accepts the dialog, optionally supplying prompt text. Throws once the dialog is handled. |
|
|
1664
|
+
| `dismiss` | `Promise<void>` | Dismisses the dialog. Throws once the dialog is handled. |
|
|
1665
|
+
|
|
1666
|
+
```ts
|
|
1667
|
+
page.emitter.on('dialog', async (dialog) => {
|
|
1668
|
+
if (dialog.category === 'prompt') await dialog.accept('Ada')
|
|
1669
|
+
else await dialog.dismiss()
|
|
1670
|
+
})
|
|
1671
|
+
```
|
|
1672
|
+
|
|
1673
|
+
#### `BrowserFileChooserInterface`
|
|
1674
|
+
|
|
1675
|
+
One intercepted file input selection. `multiple` is a Surface data member.
|
|
1676
|
+
|
|
1677
|
+
| Method | Returns | Summary |
|
|
1678
|
+
| -------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
1679
|
+
| `upload` | `Promise<void>` | Sets the chosen files. Throws when a single-file chooser is given several, and once the chooser is already handled. |
|
|
1680
|
+
| `cancel` | `Promise<void>` | Clears the selection. Throws once the chooser is already handled. |
|
|
1681
|
+
|
|
1682
|
+
```ts
|
|
1683
|
+
page.emitter.on('chooser', async (chooser) => {
|
|
1684
|
+
if (chooser.multiple) await chooser.upload(['one.txt', 'two.txt'])
|
|
1685
|
+
else await chooser.cancel()
|
|
1686
|
+
})
|
|
1687
|
+
```
|
|
1688
|
+
|
|
1689
|
+
#### `BrowserWorkerInterface`
|
|
1690
|
+
|
|
1691
|
+
A dedicated, shared, or service worker attached through its own flattened
|
|
1692
|
+
session. `id`, `url`, and `category` are Surface data members.
|
|
1693
|
+
|
|
1694
|
+
| Method | Returns | Summary |
|
|
1695
|
+
| ---------- | ------------------ | ---------------------------------------------------------------------------------- |
|
|
1696
|
+
| `evaluate` | `Promise<unknown>` | Evaluates a guarded expression in the worker and returns its value. |
|
|
1697
|
+
| `send` | `Promise<unknown>` | Issues one CDP method call on the worker's session. |
|
|
1698
|
+
| `detach` | `void` | Stops driving the worker locally without closing its target. |
|
|
1699
|
+
| `close` | `Promise<void>` | Closes the worker target, tolerating a worker that already terminated. Idempotent. |
|
|
1700
|
+
|
|
1701
|
+
```ts
|
|
1702
|
+
page.emitter.on('worker', async (worker) => {
|
|
1703
|
+
log(await worker.evaluate('self.location.href'))
|
|
1704
|
+
await worker.send('Runtime.enable')
|
|
1705
|
+
worker.detach()
|
|
1706
|
+
await worker.close()
|
|
1707
|
+
})
|
|
1708
|
+
```
|
|
1709
|
+
|
|
1710
|
+
#### `BrowserRouteInterface`
|
|
1711
|
+
|
|
1712
|
+
One paused request, decided exactly once. `id`, `request`, and `handled` are
|
|
1713
|
+
Surface data members.
|
|
1714
|
+
|
|
1715
|
+
| Method | Returns | Summary |
|
|
1716
|
+
| ---------- | --------------- | --------------------------------------------------------------------------------------- |
|
|
1717
|
+
| `abort` | `Promise<void>` | Fails the request with a Chromium error reason, `'Failed'` by default. |
|
|
1718
|
+
| `continue` | `Promise<void>` | Lets the request proceed, optionally overriding its URL, method, headers, or post body. |
|
|
1719
|
+
| `fulfill` | `Promise<void>` | Answers the request locally. Throws when the status is not an integer from 100 to 999. |
|
|
1720
|
+
|
|
1721
|
+
```ts
|
|
1722
|
+
await page.network.route({ url: '**/api' }, async (route) => {
|
|
1723
|
+
if (route.handled) return
|
|
1724
|
+
await route.fulfill({ status: 200, headers: { 'content-type': 'text/plain' }, body: 'ok' })
|
|
1725
|
+
})
|
|
1726
|
+
await page.network.route({ url: '**/slow' }, (route) => route.abort('TimedOut'))
|
|
1727
|
+
await page.network.route({ url: '**/pass' }, (route) => route.continue({ method: 'POST' }))
|
|
1728
|
+
```
|
|
1729
|
+
|
|
1730
|
+
#### `BrowserHARManagerInterface`
|
|
1731
|
+
|
|
1732
|
+
Records observed exchanges as a HAR 1.2 archive and replays one back.
|
|
1733
|
+
`recording` is a Surface data member.
|
|
1734
|
+
|
|
1735
|
+
| Method | Returns | Summary |
|
|
1736
|
+
| -------- | --------------------- | ------------------------------------------------------------------------------ |
|
|
1737
|
+
| `start` | `Promise<void>` | Begins recording exchanges, optionally capturing response content. |
|
|
1738
|
+
| `stop` | `Promise<BrowserHAR>` | Ends recording and returns the archive, writing it when a path was given. |
|
|
1739
|
+
| `replay` | `Promise<void>` | Serves matching requests from an archive instead of from the network. |
|
|
1740
|
+
| `clear` | `Promise<void>` | Drops the recorded entries and any active replay without ending the recording. |
|
|
1741
|
+
|
|
1742
|
+
```ts
|
|
1743
|
+
await page.network.har.start({ content: true })
|
|
1744
|
+
const har = await page.network.har.stop()
|
|
1745
|
+
await page.network.har.replay(har, { strict: true })
|
|
1746
|
+
await page.network.har.clear()
|
|
1747
|
+
```
|
|
1748
|
+
|
|
1749
|
+
#### `BrowserNetworkManagerInterface`
|
|
1750
|
+
|
|
1751
|
+
Page-scoped network observation and interception. `emitter` and `har` are
|
|
1752
|
+
Surface data members. Every method starts the Network domain first, so the page
|
|
1753
|
+
begins reporting `request` / `response` / `failure` from the first call.
|
|
1754
|
+
|
|
1755
|
+
| Method | Returns | Summary |
|
|
1756
|
+
| ------------- | --------------------- | --------------------------------------------------------------------------------- |
|
|
1757
|
+
| `start` | `Promise<void>` | Enables the Network domain and subscribes to its events. Idempotent. |
|
|
1758
|
+
| `body` | `Promise<Uint8Array>` | Reads one observed response body as bytes. |
|
|
1759
|
+
| `text` | `Promise<string>` | Reads one observed response body as text. |
|
|
1760
|
+
| `json` | `Promise<unknown>` | Reads one observed response body as parsed JSON. |
|
|
1761
|
+
| `route` | `Promise<void>` | Intercepts requests matching the query and hands each one to the handler. |
|
|
1762
|
+
| `unroute` | `Promise<void>` | Removes one handler's routes, or every route when given none. |
|
|
1763
|
+
| `headers` | `Promise<void>` | Applies extra HTTP headers to every request the page makes. |
|
|
1764
|
+
| `offline` | `Promise<void>` | Emulates an offline connection, or restores connectivity. |
|
|
1765
|
+
| `credentials` | `Promise<void>` | Applies HTTP basic-auth credentials, or clears them when given none. |
|
|
1766
|
+
| `destroy` | `Promise<void>` | Removes every route, unsubscribes, and disables the domains this manager enabled. |
|
|
1767
|
+
|
|
1768
|
+
```ts
|
|
1769
|
+
await page.network.start()
|
|
1770
|
+
page.emitter.on('response', async (response) => {
|
|
1771
|
+
log(await page.network.body(response.id))
|
|
1772
|
+
log(await page.network.text(response.id))
|
|
1773
|
+
log(await page.network.json(response.id))
|
|
1774
|
+
})
|
|
1775
|
+
const handler = (route) => route.continue()
|
|
1776
|
+
await page.network.route({ url: '**/api' }, handler)
|
|
1777
|
+
await page.network.unroute(handler)
|
|
1778
|
+
await page.network.headers({ 'x-trace': 'on' })
|
|
1779
|
+
await page.network.offline(true)
|
|
1780
|
+
await page.network.credentials({ username: 'ada', password: 'secret' })
|
|
1781
|
+
await page.network.destroy()
|
|
1782
|
+
```
|
|
1783
|
+
|
|
1784
|
+
#### `BrowserCookieManagerInterface`
|
|
1785
|
+
|
|
1786
|
+
Cookie state scoped to one browser context.
|
|
1787
|
+
|
|
1788
|
+
| Method | Returns | Summary |
|
|
1789
|
+
| --------- | ----------------------------------- | --------------------------------------------------------------------------------- |
|
|
1790
|
+
| `cookies` | `Promise<readonly BrowserCookie[]>` | Reads the context cookies, optionally narrowed to the given URLs. |
|
|
1791
|
+
| `set` | `Promise<void>` | Writes the given cookies into the context. |
|
|
1792
|
+
| `clear` | `Promise<void>` | Deletes the context cookies matching the filter, or every cookie when given none. |
|
|
1793
|
+
|
|
1794
|
+
```ts
|
|
1795
|
+
await context.cookies.set([{ name: 'session', value: 'abc', url: 'https://example.com/' }])
|
|
1796
|
+
log(await context.cookies.cookies(['https://example.com/']))
|
|
1797
|
+
await context.cookies.clear({ name: 'session' })
|
|
1798
|
+
```
|
|
1799
|
+
|
|
1800
|
+
#### `BrowserPermissionManagerInterface`
|
|
1801
|
+
|
|
1802
|
+
Permission overrides scoped to one browser context.
|
|
1803
|
+
|
|
1804
|
+
| Method | Returns | Summary |
|
|
1805
|
+
| ------- | --------------- | ------------------------------------------------------------------------------ |
|
|
1806
|
+
| `grant` | `Promise<void>` | Grants each named permission, optionally for one origin, as its own CDP frame. |
|
|
1807
|
+
| `deny` | `Promise<void>` | Denies each named permission, optionally for one origin, as its own CDP frame. |
|
|
1808
|
+
| `clear` | `Promise<void>` | Resets every permission override on the context. |
|
|
1809
|
+
|
|
1810
|
+
```ts
|
|
1811
|
+
await context.permissions.grant(['geolocation'], 'https://example.com')
|
|
1812
|
+
await context.permissions.deny(['notifications'], 'https://example.com')
|
|
1813
|
+
await context.permissions.clear()
|
|
1814
|
+
```
|
|
1815
|
+
|
|
1816
|
+
#### `BrowserStorageManagerInterface`
|
|
1817
|
+
|
|
1818
|
+
Cookie and web-storage state for one browser context, as one serializable value.
|
|
1819
|
+
|
|
1820
|
+
| Method | Returns | Summary |
|
|
1821
|
+
| --------- | ------------------------------ | ----------------------------------------------------------------------- |
|
|
1822
|
+
| `state` | `Promise<BrowserStorageState>` | Reads the context cookies and the per-origin local and session storage. |
|
|
1823
|
+
| `restore` | `Promise<void>` | Writes a previously read state back into the context. |
|
|
1824
|
+
| `clear` | `Promise<void>` | Drops the storage of one origin, or of every origin when given none. |
|
|
1825
|
+
|
|
1826
|
+
```ts
|
|
1827
|
+
const state = await context.storage.state({ origins: ['https://example.com'] })
|
|
1828
|
+
await context.storage.restore(state)
|
|
1829
|
+
await context.storage.clear('https://example.com')
|
|
1830
|
+
```
|
|
1831
|
+
|
|
1832
|
+
#### `BrowserEmulationManagerInterface`
|
|
1833
|
+
|
|
1834
|
+
Emulation overrides inherited by every page of one context. The offline and
|
|
1835
|
+
header overrides route through each page's network manager, so applying either
|
|
1836
|
+
starts that page's Network domain.
|
|
1837
|
+
|
|
1838
|
+
| Method | Returns | Summary |
|
|
1839
|
+
| -------- | --------------- | ---------------------------------------------------------------------------------------- |
|
|
1840
|
+
| `apply` | `Promise<void>` | Clears the superseded overrides and applies the given ones to every page of the context. |
|
|
1841
|
+
| `clear` | `Promise<void>` | Removes every override this manager applied. |
|
|
1842
|
+
| `attach` | `Promise<void>` | Applies the retained overrides to a newly created page. |
|
|
1843
|
+
|
|
1844
|
+
```ts
|
|
1845
|
+
await context.emulation.apply({ locale: 'fr-FR', offline: true, headers: { 'x-test': 'one' } })
|
|
1846
|
+
await context.emulation.attach(page)
|
|
1847
|
+
await context.emulation.clear()
|
|
1848
|
+
```
|
|
1849
|
+
|
|
1850
|
+
## Contract
|
|
1851
|
+
|
|
1852
|
+
These invariants hold across the browser layer (`src/core` + `src/server`) ↔ `browser.md`:
|
|
1853
|
+
|
|
1854
|
+
1. **Doc ↔ source bijection.** Every `function` / `class` / `const` /
|
|
1855
|
+
`interface` / `type` / error row in the `### Core` and `### Server`
|
|
1856
|
+
`## Surface` tables is a real export of the browser layer (`src/core` or
|
|
1857
|
+
`src/server`), and every export of either appears as a Surface row —
|
|
1858
|
+
exhaustive in each direction.
|
|
1859
|
+
2. **Core is environment-agnostic.** `src/core` imports only
|
|
1860
|
+
`@orkestrel/emitter`, `@orkestrel/contract`, and `@orkestrel/html` — no
|
|
1861
|
+
`node:*`, no `WebSocket`, no filesystem. `@orkestrel/html` is string → AST →
|
|
1862
|
+
string work with no host of its own, so `article()` distills a captured
|
|
1863
|
+
document without leaving core: `content()` and `article()` share one
|
|
1864
|
+
size-guarded `outerHTML` capture, and `article()` evaluates nothing else —
|
|
1865
|
+
no URL, no title, no body text. Every CDP method call
|
|
1866
|
+
and event flows through the injected `CDPTransportInterface`; core never
|
|
1867
|
+
assumes a runtime.
|
|
1868
|
+
Host-side CDP boundaries use `@orkestrel/contract` total guards for
|
|
1869
|
+
records, arrays, strings, finite numbers, integers, booleans, errors, and
|
|
1870
|
+
class instances. Synchronous JSON and URL operations cross through
|
|
1871
|
+
`parseJSON` or `attempt`; asynchronous `try` / `catch` remains only where
|
|
1872
|
+
promise rejection and transactional cleanup must be coordinated. Raw
|
|
1873
|
+
`typeof` and `instanceof` checks appear only inside compiled expressions
|
|
1874
|
+
that execute in the remote page, where host package imports are
|
|
1875
|
+
unavailable.
|
|
1876
|
+
The `browser → html` edge is one-way and stays that way: `@orkestrel/browser`
|
|
1877
|
+
must never become a dependency of `@orkestrel/html`. `BrowserSnapshot`
|
|
1878
|
+
navigates CDP DOM snapshots rather than HTML source, so it never moves into
|
|
1879
|
+
`@orkestrel/html`. Nor does the snapshot entity ever gain rendering,
|
|
1880
|
+
extraction, or distillation — `article()` on the frame is where distillation
|
|
1881
|
+
lives, and it is the only place it lives.
|
|
1882
|
+
3. **The transport is a dumb text pipe.** `CDPTransportInterface` does no
|
|
1883
|
+
JSON framing of its own — `CDPClient` owns request/response correlation
|
|
1884
|
+
(`id`), timeout handling, and event dispatch (global + session-scoped
|
|
1885
|
+
subscriptions) over the transport's raw `message` / `close` / `error`
|
|
1886
|
+
events.
|
|
1887
|
+
4. **Captured bytes never touch a filesystem in core.** A page accepts an
|
|
1888
|
+
optional `BrowserWriterInterface`, injected through `BrowserContext`, and
|
|
1889
|
+
calls `write(path, bytes)` only when a screenshot, PDF, trace, or HAR
|
|
1890
|
+
request carries a `path`; the server supplies `createBrowserWriter`, an
|
|
1891
|
+
`fs`-backed implementation, through `Browser`.
|
|
1892
|
+
5. **Server owns the connection lifecycle.** `Browser.connect()` tries, in
|
|
1893
|
+
order: an explicit `cdp.endpoint`; a passive probe of
|
|
1894
|
+
`{cdp.host}:{cdp.port}` (defaulting to `127.0.0.1:{cdp.port}` through
|
|
1895
|
+
`BROWSER_DEFAULT_HOST`) (`discover()`); then launching a new browser
|
|
1896
|
+
process with raw-CDP flags
|
|
1897
|
+
(`findSystemBrowser` / `launchBrowserProcess` / `waitForCDPReady`). A
|
|
1898
|
+
found existing browser is preferred over a fresh launch. `engine` is
|
|
1899
|
+
classified through `parseBrowserEngine` (explicit `executable`) or the
|
|
1900
|
+
discovered `SystemBrowser`'s engine (launch) or `browserToEngine` on the
|
|
1901
|
+
discovered `/json/version` browser string (CDP discovery); `BrowserOptions.engine`
|
|
1902
|
+
narrows `findSystemBrowser` discovery to a preferred engine when launching,
|
|
1903
|
+
and the thrown `BrowserConnectionError` carries the requested `engine` in
|
|
1904
|
+
`context` when no matching browser is found; launch discovery also consults
|
|
1905
|
+
`BrowserOptions.browsers` candidate-source overrides when given. A
|
|
1906
|
+
`disconnect()` on either kind of launch retains process ownership without
|
|
1907
|
+
killing it — the same instance can reconnect through the retained endpoint
|
|
1908
|
+
and remains responsible for termination. `BrowserCDPOptions.discover`
|
|
1909
|
+
(default `true`) set to `false` skips passive discovery and probes the
|
|
1910
|
+
port directly, rejecting with a coded `BrowserConnectionError` naming the
|
|
1911
|
+
occupied port if something is already listening there, rather than
|
|
1912
|
+
silently attaching to it.
|
|
1913
|
+
6. **Lifecycle events are observable, never inferred from state polling.**
|
|
1914
|
+
`BrowserInterface.emitter` fires `idle` / `discover` / `connect` /
|
|
1915
|
+
`disconnect` / `launch` / `page` / `context` / `error` / `destroy`; `BrowserCodegenInterface.emitter`
|
|
1916
|
+
fires `start` / `stop` / `action` / `clear`; `CDPClientInterface.emitter`
|
|
1917
|
+
fires `connect` / `close` / `drop` / `error`. Each isolates a listener throw
|
|
1918
|
+
through `@orkestrel/emitter`'s emitter, never a domain event. An external
|
|
1919
|
+
disconnect (transport loss while an owned process stays alive, or the
|
|
1920
|
+
owned process exiting on its own) always emits a coded `error` before
|
|
1921
|
+
`disconnect`; transport loss with the process still alive is resumable —
|
|
1922
|
+
the browser is not killed and the same `Browser` instance can `connect()`
|
|
1923
|
+
again (for example, rediscovering it over CDP), while a process exit is terminal
|
|
1924
|
+
for that instance.
|
|
1925
|
+
7. **Errors carry a machine-readable `code` + optional `context`.**
|
|
1926
|
+
`BrowserError` (core) is the base; `BrowserSelectorError` / `CDPError` /
|
|
1927
|
+
`CDPConnectionError` / `CDPTimeoutError` / `BrowserResultLimitError` (core)
|
|
1928
|
+
narrow selector, protocol, connectivity, timeout, and oversized-result
|
|
1929
|
+
faults; `BrowserConnectionError` / `BrowserNotConnectedError` /
|
|
1930
|
+
`BrowserDestroyedError` (server) narrow connection-lifecycle faults. Each
|
|
1931
|
+
ships an `is*` type guard.
|
|
1932
|
+
8. **Oversized evaluate/content results fail clean, never crash the session.**
|
|
1933
|
+
`BrowserPage.evaluate()` wraps its expression with
|
|
1934
|
+
`compileGuardedEvaluateExpression(expression, BROWSER_RESULT_LIMIT)`, and
|
|
1935
|
+
`.content()` wraps its HTML (`outerHTML`) and its visible-text
|
|
1936
|
+
(`innerText`) sub-evaluations the same way — only `title` and `url` are
|
|
1937
|
+
not size-guarded. `article()` shares that one HTML capture and so inherits
|
|
1938
|
+
its guard exactly: an oversized document fails `content()` and `article()`
|
|
1939
|
+
identically. It does not inherit the body-text guard, because it never
|
|
1940
|
+
evaluates `innerText` — a document whose visible text alone exceeds the
|
|
1941
|
+
limit fails `content()` while `article()` still returns.
|
|
1942
|
+
The guard stringifies the in-page result and throws a
|
|
1943
|
+
`BROWSER_RESULT_LIMIT_SENTINEL_PREFIX` (`[[ORKESTREL_BROWSER_RESULT_LIMIT]]`)
|
|
1944
|
+
followed by the serialized length before an oversized result could
|
|
1945
|
+
overflow the CDP transport frame; `BrowserPage` recognizes that
|
|
1946
|
+
sentinel (`BROWSER_RESULT_LIMIT_PATTERN`) and rejects with a coded
|
|
1947
|
+
`BrowserResultLimitError` instead — the underlying CDP connection and
|
|
1948
|
+
browser process are unaffected. The crash-safety guarantee therefore
|
|
1949
|
+
applies to `evaluate()`, to both the HTML and text fields of `.content()`,
|
|
1950
|
+
and to `article()`'s HTML capture.
|
|
1951
|
+
9. **Codegen normalizes and compiles deterministically.**
|
|
1952
|
+
`normalizeCodegenActions` collapses consecutive `fill`s on the same
|
|
1953
|
+
selector to the latest value (including `contenteditable` fills, captured
|
|
1954
|
+
the same way as inputs/textareas); `compileCodegenScript` emits one
|
|
1955
|
+
`page.<action>(...)` statement per normalized action, `'javascript'`
|
|
1956
|
+
(bare `async function run(page) {...}`) or `'typescript'`
|
|
1957
|
+
(`import('@orkestrel/browser').BrowserPageInterface`-typed) per
|
|
1958
|
+
`BrowserCodegenScriptOptions.language` (default `'javascript'`).
|
|
1959
|
+
10. **Doc ↔ source method bijection.** The `## Methods` tables list exactly
|
|
1960
|
+
the public methods of each behavioral interface — `CDPTransportInterface`,
|
|
1961
|
+
`CDPClientInterface`, `BrowserContextInterface`, `BrowserFrameInterface`,
|
|
1962
|
+
`BrowserPageInterface`, `BrowserSnapshotInterface`,
|
|
1963
|
+
`BrowserCodegenInterface`, `BrowserTransitionInterface`,
|
|
1964
|
+
`BrowserInterface`, `BrowserWebSocketInterface`,
|
|
1965
|
+
`BrowserDownloadInterface`, `BrowserWriterInterface`,
|
|
1966
|
+
`BrowserNavigationManagerInterface`, `BrowserHandleInterface`,
|
|
1967
|
+
`BrowserScriptManagerInterface`, `BrowserAccessibilityInterface`,
|
|
1968
|
+
`BrowserTracingInterface`, `BrowserCoverageInterface`,
|
|
1969
|
+
`BrowserPerformanceInterface`, `BrowserProfilerInterface`,
|
|
1970
|
+
`BrowserDiagnosticsInterface`, `BrowserClockInterface`,
|
|
1971
|
+
`BrowserLocatorInterface`, `BrowserSelectorManagerInterface`,
|
|
1972
|
+
`BrowserKeyboardInterface`, `BrowserMouseInterface`,
|
|
1973
|
+
`BrowserTouchInterface`, `BrowserDialogInterface`,
|
|
1974
|
+
`BrowserFileChooserInterface`, `BrowserWorkerInterface`,
|
|
1975
|
+
`BrowserRouteInterface`, `BrowserHARManagerInterface`,
|
|
1976
|
+
`BrowserNetworkManagerInterface`, `BrowserCookieManagerInterface`,
|
|
1977
|
+
`BrowserPermissionManagerInterface`, `BrowserStorageManagerInterface`,
|
|
1978
|
+
`BrowserEmulationManagerInterface` — exhaustive in each direction, and each
|
|
1979
|
+
implementing class (`WebSocketCDPTransport`, `CDPClient`, `BrowserContext`,
|
|
1980
|
+
`BrowserFrame`, `BrowserPage`, `BrowserSnapshot`, `BrowserCodegen`,
|
|
1981
|
+
`BrowserTransition`, `Browser`, `BrowserWebSocket`, `BrowserDownload`,
|
|
1982
|
+
`FileBrowserWriter`, `BrowserNavigationManager`, `BrowserHandle`,
|
|
1983
|
+
`BrowserScriptManager`, `BrowserAccessibility`, `BrowserTracing`,
|
|
1984
|
+
`BrowserCoverage`, `BrowserPerformance`, `BrowserProfiler`,
|
|
1985
|
+
`BrowserDiagnostics`, `BrowserClock`, `BrowserLocator`,
|
|
1986
|
+
`BrowserSelectorManager`, `BrowserKeyboard`, `BrowserMouse`,
|
|
1987
|
+
`BrowserTouch`, `BrowserDialog`, `BrowserFileChooser`, `BrowserWorker`,
|
|
1988
|
+
`BrowserRoute`, `BrowserHARManager`, `BrowserNetworkManager`,
|
|
1989
|
+
`BrowserCookieManager`, `BrowserPermissionManager`,
|
|
1990
|
+
`BrowserStorageManager`, `BrowserEmulationManager`) exposes the same public
|
|
1991
|
+
methods, no more.
|
|
1992
|
+
`BrowserPageInterface` extends `BrowserFrameInterface`, so its table
|
|
1993
|
+
repeats every inherited member and points at the frame's own table for the
|
|
1994
|
+
behavior. Every remaining export is a function or a data bag rather than a
|
|
1995
|
+
behavioral interface with methods — the factories, `decodeBase64` /
|
|
1996
|
+
`compileGuardedEvaluateExpression` / `parseCodegenActionPayload` /
|
|
1997
|
+
`parseCodegenNavigateAction` / `compileCodegenScript` / `findSystemBrowser` /
|
|
1998
|
+
`launchBrowserProcess` / `waitForCDPReady` / `fetchCDPTargets` are
|
|
1999
|
+
functions; the options interfaces / event maps / results / `CDPTarget` /
|
|
2000
|
+
`BrowserViewport` are data bags — so they contribute no `## Methods` row.
|
|
2001
|
+
11. **The WebSocket CDP transport is a thin bridge (`src/server`).**
|
|
2002
|
+
`WebSocketCDPTransport` connects a Node `WebSocket` to the given CDP
|
|
2003
|
+
debugger URL, races the connection attempt against `timeout`
|
|
2004
|
+
(default `BROWSER_DEFAULT_TIMEOUT_MS`), and bridges the socket's
|
|
2005
|
+
`message` / `close` / `error` events onto its `CDPTransportEventMap`
|
|
2006
|
+
emitter unchanged (no framing of its own). `start()` rejects with a
|
|
2007
|
+
`BrowserConnectionError` (URL in `context`) on socket error, non-open
|
|
2008
|
+
close, or timeout — never a bare error.
|
|
2009
|
+
12. **`Browser.destroy()` escalates SIGTERM → SIGKILL; `close()` is graceful.**
|
|
2010
|
+
On POSIX, each launch owns an isolated process group so Chromium
|
|
2011
|
+
subprocesses cannot outlive their parent and keep writing the profile.
|
|
2012
|
+
`destroy()` sends `SIGTERM` to the process serving the endpoint, which on
|
|
2013
|
+
POSIX means that process's whole group; if it has not exited or the group
|
|
2014
|
+
has not drained after `BROWSER_KILL_GRACE_MS`, the same target is
|
|
2015
|
+
force-killed with `SIGKILL` and given the same bounded exit window.
|
|
2016
|
+
On Windows a launch owns no process group, so each step signals one process
|
|
2017
|
+
by identifier. Node ignores the signal name there and terminates that
|
|
2018
|
+
process abruptly, so the `SIGTERM` step is already an uncatchable terminate
|
|
2019
|
+
and the `SIGKILL` step repeats the terminate only when the process is still
|
|
2020
|
+
running after the grace period. Terminating a Chromium browser process
|
|
2021
|
+
takes its renderer, GPU, and utility subprocesses with it, so that single
|
|
2022
|
+
signal drains the tree the launch created.
|
|
2023
|
+
`close()` instead sends CDP `Browser.close` first (best-effort, whether
|
|
2024
|
+
the process is owned or merely CDP-attached) and only escalates to the
|
|
2025
|
+
same kill sequence if an owned process fails to exit within the grace
|
|
2026
|
+
period — the graceful path for shutting down a browser this instance may
|
|
2027
|
+
not own. In the worst case an owned, unresponsive process tree makes
|
|
2028
|
+
`close()` apply `BROWSER_KILL_GRACE_MS` after `Browser.close`, again after
|
|
2029
|
+
`SIGTERM`, and again after `SIGKILL`.
|
|
2030
|
+
`BrowserInterface.owned` is `true` for a launched or explicitly adopted
|
|
2031
|
+
session, `false` for an active attachment, and `undefined` when no session
|
|
2032
|
+
is represented. `BrowserInterface.pid` is the id of the process serving the
|
|
2033
|
+
session's CDP endpoint; it stays readable across a `'persistent'` session's
|
|
2034
|
+
`disconnect()` and only becomes `undefined` after `destroy()`/`close()` or
|
|
2035
|
+
an observed process exit — never on `disconnect()` alone. It is
|
|
2036
|
+
`undefined` from the start on a plain CDP attach (`connection === 'cdp'`),
|
|
2037
|
+
which never owns a process.
|
|
2038
|
+
13. **A launch owns the process that serves its endpoint, not the process it
|
|
2039
|
+
spawned.** Those are the same process for Chrome and Chromium, whose
|
|
2040
|
+
spawned process is the browser. Microsoft Edge on Windows instead
|
|
2041
|
+
re-executes itself with the same `--remote-debugging-port` and exits 0
|
|
2042
|
+
before the endpoint answers, so `connect()` treats that clean exit as a
|
|
2043
|
+
hand-off rather than a death: it keeps waiting for the endpoint on the same
|
|
2044
|
+
`timeout` budget, then reads the `browser` entry of CDP
|
|
2045
|
+
`SystemInfo.getProcessInfo` and owns the process named there. That process
|
|
2046
|
+
is what `pid` reports and what `destroy()` terminates, and the isolated
|
|
2047
|
+
profile is removable because nothing in the tree still holds it. The
|
|
2048
|
+
failure path is unchanged: a spawned process that exits with a nonzero code
|
|
2049
|
+
or a signal rejects immediately with a `BrowserConnectionError` naming the
|
|
2050
|
+
exit, a clean exit that produces no endpoint within `timeout` rejects with
|
|
2051
|
+
the readiness failure, and an endpoint that names no browser process
|
|
2052
|
+
rejects after a best-effort CDP `Browser.close`, rather than owning a
|
|
2053
|
+
browser it cannot terminate.
|
|
2054
|
+
14. **A snapshot is serializable data plus navigation.** `BrowserSnapshot`
|
|
2055
|
+
holds exactly the `BrowserSnapshotInput` members `documents` and `styles`, so
|
|
2056
|
+
`JSON.stringify(snapshot)` yields `{ documents, styles }` and nothing else,
|
|
2057
|
+
and `createBrowserSnapshot(parsed)` turns that JSON back into a navigable
|
|
2058
|
+
entity whose walks and `path()` results match the original's. Navigation
|
|
2059
|
+
reads plain data: every method takes and returns bare `BrowserNode` values,
|
|
2060
|
+
never a wrapper node entity, and the constructor copies and freezes the
|
|
2061
|
+
`documents` and `styles` arrays so a caller's later mutation cannot reach the
|
|
2062
|
+
snapshot. Containment
|
|
2063
|
+
is derived, not declared — a node contains a candidate exactly when
|
|
2064
|
+
`snapshot.ancestors(candidate)` includes it — so no membership flag or
|
|
2065
|
+
`contains`-style member can drift from the ancestry walk.
|
|
2066
|
+
|
|
2067
|
+
## Patterns
|
|
2068
|
+
|
|
2069
|
+
### Automate a page end-to-end
|
|
2070
|
+
|
|
2071
|
+
This demonstration launches a headless browser, fills and submits a search form, waits for the
|
|
2072
|
+
results, and reads the resulting content.
|
|
2073
|
+
|
|
2074
|
+
```ts
|
|
2075
|
+
import { createBrowser } from '@orkestrel/browser/server'
|
|
2076
|
+
|
|
2077
|
+
const browser = createBrowser({ headless: true })
|
|
2078
|
+
await browser.connect()
|
|
2079
|
+
|
|
2080
|
+
const page = await browser.create({ url: 'https://example.com' })
|
|
2081
|
+
await page.fill('#search', 'orkestrel')
|
|
2082
|
+
await page.click('#submit')
|
|
2083
|
+
await page.wait('#results')
|
|
2084
|
+
const content = await page.content()
|
|
2085
|
+
|
|
2086
|
+
await browser.destroy()
|
|
2087
|
+
```
|
|
2088
|
+
|
|
2089
|
+
### Record and replay interactions with codegen
|
|
2090
|
+
|
|
2091
|
+
This demonstration records a click and a fill on a page, then compiles the recorded actions into
|
|
2092
|
+
a replayable script.
|
|
2093
|
+
|
|
2094
|
+
```ts
|
|
2095
|
+
const page = await browser.create({ url: 'https://example.com' })
|
|
2096
|
+
const codegen = await page.codegen()
|
|
2097
|
+
|
|
2098
|
+
await page.click('#menu')
|
|
2099
|
+
await page.fill('#search', 'orkestrel')
|
|
2100
|
+
|
|
2101
|
+
const actions = await codegen.stop()
|
|
2102
|
+
const script = codegen.script({ language: 'typescript' })
|
|
2103
|
+
await codegen.destroy()
|
|
2104
|
+
```
|
|
2105
|
+
|
|
2106
|
+
### Reattach to a running session
|
|
2107
|
+
|
|
2108
|
+
A `'persistent'` (profile-backed) launch survives `disconnect()` — the
|
|
2109
|
+
browser process keeps running, so a later `Browser` can reattach to it through
|
|
2110
|
+
CDP discovery on the same fixed port. A reattached instance connects as
|
|
2111
|
+
`'cdp'`, so its own `destroy()` detaches locally and does nothing more — it never sends a
|
|
2112
|
+
remote close, because another client may still be using the browser:
|
|
2113
|
+
|
|
2114
|
+
```ts
|
|
2115
|
+
import { createBrowser } from '@orkestrel/browser/server'
|
|
2116
|
+
|
|
2117
|
+
const port = 9222
|
|
2118
|
+
const browser = createBrowser({ profile: './profile', cdp: { port } })
|
|
2119
|
+
await browser.connect() // launches (no browser yet listening on `port`)
|
|
2120
|
+
const pid = browser.pid // supervise this process externally if desired
|
|
2121
|
+
|
|
2122
|
+
await browser.disconnect() // retains ownership without killing the browser
|
|
2123
|
+
|
|
2124
|
+
// ...later, in this process or another...
|
|
2125
|
+
const reattached = createBrowser({ cdp: { port } })
|
|
2126
|
+
await reattached.connect() // discovers the still-running browser over CDP
|
|
2127
|
+
const urls = reattached
|
|
2128
|
+
.context()
|
|
2129
|
+
?.pages()
|
|
2130
|
+
.map((page) => page.url) // correct immediately, no navigate()/content() needed
|
|
2131
|
+
await reattached.destroy() // detaches locally and nothing more; the browser process keeps running
|
|
2132
|
+
await browser.destroy() // the original owner terminates and awaits its process
|
|
2133
|
+
```
|
|
2134
|
+
|
|
2135
|
+
An ephemeral launch (no `profile`) can also disconnect and reconnect while its
|
|
2136
|
+
owning `Browser` instance and process remain alive. A transport-loss disconnect
|
|
2137
|
+
is likewise resumable — the same `browser` instance can `connect()` again
|
|
2138
|
+
without a fresh `createBrowser()`.
|
|
2139
|
+
|
|
2140
|
+
When the original owner is unavailable, a connected CDP client can explicitly
|
|
2141
|
+
assume responsibility before disconnecting. Ownership is state, not a string
|
|
2142
|
+
mode: `owned` is `true` for launched/adopted sessions, `false` for an active
|
|
2143
|
+
attachment, and `undefined` when no session is represented.
|
|
2144
|
+
|
|
2145
|
+
```ts
|
|
2146
|
+
const browser = createBrowser({ cdp: { port } })
|
|
2147
|
+
await browser.connect()
|
|
2148
|
+
browser.adopt()
|
|
2149
|
+
await browser.disconnect()
|
|
2150
|
+
await browser.connect()
|
|
2151
|
+
await browser.destroy() // closes the adopted remote browser
|
|
2152
|
+
```
|
|
2153
|
+
|
|
2154
|
+
### Gracefully shut down a reattached session
|
|
2155
|
+
|
|
2156
|
+
Use `close()` instead of `destroy()` to terminate a browser this instance
|
|
2157
|
+
merely attached to (or launched) — it sends CDP
|
|
2158
|
+
`Browser.close` and, when this instance owns the process, awaits its exit
|
|
2159
|
+
before falling back to the kill-escalation `destroy()` uses:
|
|
2160
|
+
|
|
2161
|
+
```ts
|
|
2162
|
+
const reattached = createBrowser({ cdp: { port } })
|
|
2163
|
+
await reattached.connect() // discovers the still-running browser over CDP
|
|
2164
|
+
|
|
2165
|
+
await reattached.close() // best-effort CDP Browser.close; because this instance never owned the process, it does not wait for the remote exit
|
|
2166
|
+
// a further connect() on this instance throws BrowserDestroyedError, same as after destroy()
|
|
2167
|
+
```
|
|
2168
|
+
|
|
2169
|
+
### Drive the core client directly over an injected transport
|
|
2170
|
+
|
|
2171
|
+
Useful when embedding in a non-Node environment, or in a test with a fake
|
|
2172
|
+
transport that satisfies `CDPTransportInterface`.
|
|
2173
|
+
|
|
2174
|
+
```ts
|
|
2175
|
+
import { createCDPClient } from '@orkestrel/browser'
|
|
2176
|
+
|
|
2177
|
+
const client = createCDPClient({ transport: myTransport })
|
|
2178
|
+
await client.connect()
|
|
2179
|
+
|
|
2180
|
+
const result = await client.send('Page.navigate', { url: 'https://example.com' })
|
|
2181
|
+
client.subscribe('Page.frameNavigated', (params) => log(params))
|
|
2182
|
+
|
|
2183
|
+
await client.close()
|
|
2184
|
+
```
|
|
2185
|
+
|
|
2186
|
+
## Tests
|
|
2187
|
+
|
|
2188
|
+
- [`tests/guides.test.ts`](../tests/guides.test.ts) — the `## Surface` ↔ `src/core` and `src/server` bijection over value and type exports, each `## Methods` table against its interface's call-signature members, and the equality gate: every `Summary` cell against its declaration's description paragraph, the titled `Connect to a browser and drive a page` fence against the `@example` block of that title (pinned so the titled pair cannot be retired silently), and the README pitch against this guide's tagline.
|
|
2189
|
+
- [`tests/src/core/CDPClient.test.ts`](../tests/src/core/CDPClient.test.ts) and [`tests/src/core/factories.test.ts`](../tests/src/core/factories.test.ts) — the JSON-RPC framing, session scoping, timeout, reconnect, and teardown paths of `CDPClient` over an in-memory transport, and the factories that build it.
|
|
2190
|
+
- [`tests/src/core/BrowserContext.test.ts`](../tests/src/core/BrowserContext.test.ts), [`tests/src/core/BrowserPage.test.ts`](../tests/src/core/BrowserPage.test.ts), [`tests/src/core/BrowserFrame.test.ts`](../tests/src/core/BrowserFrame.test.ts), and [`tests/src/core/BrowserTransition.test.ts`](../tests/src/core/BrowserTransition.test.ts) — the context, page, and frame lifecycles, the destructive target diff `sync()` performs, and the shared transition every joining caller awaits.
|
|
2191
|
+
- [`tests/src/core/BrowserLocator.test.ts`](../tests/src/core/BrowserLocator.test.ts), [`tests/src/core/BrowserSelectorManager.test.ts`](../tests/src/core/BrowserSelectorManager.test.ts), [`tests/src/core/BrowserHandle.test.ts`](../tests/src/core/BrowserHandle.test.ts), and [`tests/src/core/compilers.test.ts`](../tests/src/core/compilers.test.ts) — strict semantic location, remote-handle retention and disposal, and the in-page expressions the click, fill, select, wait, and visibility compilers emit.
|
|
2192
|
+
- [`tests/src/core/BrowserKeyboard.test.ts`](../tests/src/core/BrowserKeyboard.test.ts), [`tests/src/core/BrowserMouse.test.ts`](../tests/src/core/BrowserMouse.test.ts), and [`tests/src/core/BrowserTouch.test.ts`](../tests/src/core/BrowserTouch.test.ts) — trusted keyboard, mouse, and touch input, the modifier and pressed-button masks they carry, and the chord grammar `extractBrowserChord` accepts.
|
|
2193
|
+
- [`tests/src/core/BrowserNetworkManager.test.ts`](../tests/src/core/BrowserNetworkManager.test.ts), [`tests/src/core/BrowserRoute.test.ts`](../tests/src/core/BrowserRoute.test.ts), [`tests/src/core/BrowserHARManager.test.ts`](../tests/src/core/BrowserHARManager.test.ts), [`tests/src/core/BrowserWebSocket.test.ts`](../tests/src/core/BrowserWebSocket.test.ts), and [`tests/src/core/BrowserDownload.test.ts`](../tests/src/core/BrowserDownload.test.ts) — request observation, interception and fulfilment, HAR recording and replay, observed WebSocket frames, and download progress.
|
|
2194
|
+
- [`tests/src/core/BrowserSnapshot.test.ts`](../tests/src/core/BrowserSnapshot.test.ts), [`tests/src/core/BrowserAccessibility.test.ts`](../tests/src/core/BrowserAccessibility.test.ts), and [`tests/src/core/parsers.test.ts`](../tests/src/core/parsers.test.ts) — snapshot walking, structural relationships, search, and paths; accessibility-tree capture; and the coercions every protocol parser applies to off-shape input.
|
|
2195
|
+
- [`tests/src/core/BrowserClock.test.ts`](../tests/src/core/BrowserClock.test.ts), [`tests/src/core/BrowserCoverage.test.ts`](../tests/src/core/BrowserCoverage.test.ts), [`tests/src/core/BrowserProfiler.test.ts`](../tests/src/core/BrowserProfiler.test.ts), [`tests/src/core/BrowserTracing.test.ts`](../tests/src/core/BrowserTracing.test.ts), [`tests/src/core/BrowserPerformance.test.ts`](../tests/src/core/BrowserPerformance.test.ts), and [`tests/src/core/BrowserDiagnostics.test.ts`](../tests/src/core/BrowserDiagnostics.test.ts) — the virtual clock and the diagnostics capabilities beneath one page, including the teardown that discards a failure from an already-stopped capability.
|
|
2196
|
+
- [`tests/src/core/BrowserCookieManager.test.ts`](../tests/src/core/BrowserCookieManager.test.ts), [`tests/src/core/BrowserStorageManager.test.ts`](../tests/src/core/BrowserStorageManager.test.ts), [`tests/src/core/BrowserPermissionManager.test.ts`](../tests/src/core/BrowserPermissionManager.test.ts), and [`tests/src/core/BrowserEmulationManager.test.ts`](../tests/src/core/BrowserEmulationManager.test.ts) — the context-scoped cookie, web-storage, permission, and emulation overrides, and the overrides a newly created page inherits.
|
|
2197
|
+
- [`tests/src/core/BrowserScriptManager.test.ts`](../tests/src/core/BrowserScriptManager.test.ts), [`tests/src/core/BrowserCodegen.test.ts`](../tests/src/core/BrowserCodegen.test.ts), [`tests/src/core/BrowserDialog.test.ts`](../tests/src/core/BrowserDialog.test.ts), [`tests/src/core/BrowserFileChooser.test.ts`](../tests/src/core/BrowserFileChooser.test.ts), [`tests/src/core/BrowserWorker.test.ts`](../tests/src/core/BrowserWorker.test.ts), and [`tests/src/core/BrowserNavigationManager.test.ts`](../tests/src/core/BrowserNavigationManager.test.ts) — init scripts and host bindings, action recording and script compilation, dialog and file-chooser handling, attached workers, and the URL and predicate waits that survive ordinary navigation events.
|
|
2198
|
+
- [`tests/src/core/helpers.test.ts`](../tests/src/core/helpers.test.ts) and [`tests/src/core/errors.test.ts`](../tests/src/core/errors.test.ts) — the pure decoders, validators, and compilers of `src/core`, and the guards that narrow a caught value to each core error.
|
|
2199
|
+
- [`tests/src/server/Browser.test.ts`](../tests/src/server/Browser.test.ts), [`tests/src/server/helpers.test.ts`](../tests/src/server/helpers.test.ts), [`tests/src/server/factories.test.ts`](../tests/src/server/factories.test.ts), and [`tests/src/server/errors.test.ts`](../tests/src/server/errors.test.ts) — the discover, connect, launch, adopt, disconnect, destroy, and close lifecycle against a spawned stand-in process; system-browser discovery, profile resolution, and CDP readiness polling; and the guards that narrow a caught value to each server error.
|
|
2200
|
+
- [`tests/src/server/transports/WebSocketCDPTransport.test.ts`](../tests/src/server/transports/WebSocketCDPTransport.test.ts) and [`tests/src/server/writers/FileBrowserWriter.test.ts`](../tests/src/server/writers/FileBrowserWriter.test.ts) — the `WebSocket`-backed transport against a real in-process CDP server, and the filesystem writer that creates its missing parent directories.
|