craftdriver 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/README.md +157 -45
- package/bin/craftdriver.mjs +26 -0
- package/dist/cli/client.d.ts +17 -0
- package/dist/cli/client.d.ts.map +1 -0
- package/dist/cli/client.js +88 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/daemon.d.ts +15 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +145 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/defaults.d.ts +10 -0
- package/dist/cli/defaults.d.ts.map +1 -0
- package/dist/cli/defaults.js +42 -0
- package/dist/cli/defaults.js.map +1 -0
- package/dist/cli/dispatcher.d.ts +28 -0
- package/dist/cli/dispatcher.d.ts.map +1 -0
- package/dist/cli/dispatcher.js +319 -0
- package/dist/cli/dispatcher.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +404 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +24 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +192 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp/artifacts.d.ts +43 -0
- package/dist/cli/mcp/artifacts.d.ts.map +1 -0
- package/dist/cli/mcp/artifacts.js +104 -0
- package/dist/cli/mcp/artifacts.js.map +1 -0
- package/dist/cli/mcp/server.d.ts +34 -0
- package/dist/cli/mcp/server.d.ts.map +1 -0
- package/dist/cli/mcp/server.js +214 -0
- package/dist/cli/mcp/server.js.map +1 -0
- package/dist/cli/mcp/tools.d.ts +34 -0
- package/dist/cli/mcp/tools.d.ts.map +1 -0
- package/dist/cli/mcp/tools.js +236 -0
- package/dist/cli/mcp/tools.js.map +1 -0
- package/dist/cli/parseArgs.d.ts +37 -0
- package/dist/cli/parseArgs.d.ts.map +1 -0
- package/dist/cli/parseArgs.js +215 -0
- package/dist/cli/parseArgs.js.map +1 -0
- package/dist/cli/protocol.d.ts +34 -0
- package/dist/cli/protocol.d.ts.map +1 -0
- package/dist/cli/protocol.js +2 -0
- package/dist/cli/protocol.js.map +1 -0
- package/dist/cli/selector.d.ts +29 -0
- package/dist/cli/selector.d.ts.map +1 -0
- package/dist/cli/selector.js +100 -0
- package/dist/cli/selector.js.map +1 -0
- package/dist/cli/snapshot.d.ts +48 -0
- package/dist/cli/snapshot.d.ts.map +1 -0
- package/dist/cli/snapshot.js +179 -0
- package/dist/cli/snapshot.js.map +1 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/a11y.d.ts +81 -0
- package/dist/lib/a11y.d.ts.map +1 -0
- package/dist/lib/a11y.js +171 -0
- package/dist/lib/a11y.js.map +1 -0
- package/dist/lib/bidi/index.d.ts +26 -1
- package/dist/lib/bidi/index.d.ts.map +1 -1
- package/dist/lib/bidi/index.js +49 -0
- package/dist/lib/bidi/index.js.map +1 -1
- package/dist/lib/bidi/logs.d.ts +2 -2
- package/dist/lib/bidi/logs.d.ts.map +1 -1
- package/dist/lib/bidi/logs.js +2 -2
- package/dist/lib/bidi/logs.js.map +1 -1
- package/dist/lib/bidi/network.d.ts +74 -1
- package/dist/lib/bidi/network.d.ts.map +1 -1
- package/dist/lib/bidi/network.js +222 -4
- package/dist/lib/bidi/network.js.map +1 -1
- package/dist/lib/bidi/storage.d.ts +5 -3
- package/dist/lib/bidi/storage.d.ts.map +1 -1
- package/dist/lib/bidi/storage.js +14 -7
- package/dist/lib/bidi/storage.js.map +1 -1
- package/dist/lib/bidi/types.d.ts +27 -6
- package/dist/lib/bidi/types.d.ts.map +1 -1
- package/dist/lib/browser.d.ts +637 -16
- package/dist/lib/browser.d.ts.map +1 -1
- package/dist/lib/browser.js +1428 -102
- package/dist/lib/browser.js.map +1 -1
- package/dist/lib/browserContext.d.ts +486 -0
- package/dist/lib/browserContext.d.ts.map +1 -0
- package/dist/lib/browserContext.js +937 -0
- package/dist/lib/browserContext.js.map +1 -0
- package/dist/lib/builder.d.ts +3 -0
- package/dist/lib/builder.d.ts.map +1 -1
- package/dist/lib/builder.js +31 -4
- package/dist/lib/builder.js.map +1 -1
- package/dist/lib/by.d.ts +18 -2
- package/dist/lib/by.d.ts.map +1 -1
- package/dist/lib/by.js +20 -2
- package/dist/lib/by.js.map +1 -1
- package/dist/lib/chrome.d.ts +13 -1
- package/dist/lib/chrome.d.ts.map +1 -1
- package/dist/lib/chrome.js +13 -17
- package/dist/lib/chrome.js.map +1 -1
- package/dist/lib/clock.d.ts +115 -0
- package/dist/lib/clock.d.ts.map +1 -0
- package/dist/lib/clock.js +407 -0
- package/dist/lib/clock.js.map +1 -0
- package/dist/lib/driver.d.ts +43 -0
- package/dist/lib/driver.d.ts.map +1 -1
- package/dist/lib/driver.js +120 -0
- package/dist/lib/driver.js.map +1 -1
- package/dist/lib/driverManager.d.ts +25 -0
- package/dist/lib/driverManager.d.ts.map +1 -0
- package/dist/lib/driverManager.js +399 -0
- package/dist/lib/driverManager.js.map +1 -0
- package/dist/lib/elementHandle.d.ts +67 -3
- package/dist/lib/elementHandle.d.ts.map +1 -1
- package/dist/lib/elementHandle.js +209 -67
- package/dist/lib/elementHandle.js.map +1 -1
- package/dist/lib/errors.d.ts +71 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +73 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/expect.d.ts +6 -1
- package/dist/lib/expect.d.ts.map +1 -1
- package/dist/lib/expect.js +55 -37
- package/dist/lib/expect.js.map +1 -1
- package/dist/lib/firefox.d.ts +18 -0
- package/dist/lib/firefox.d.ts.map +1 -0
- package/dist/lib/firefox.js +33 -0
- package/dist/lib/firefox.js.map +1 -0
- package/dist/lib/frame.d.ts +57 -0
- package/dist/lib/frame.d.ts.map +1 -0
- package/dist/lib/frame.js +277 -0
- package/dist/lib/frame.js.map +1 -0
- package/dist/lib/keyboard.d.ts +1 -1
- package/dist/lib/keyboard.d.ts.map +1 -1
- package/dist/lib/keyboard.js +1 -1
- package/dist/lib/keyboard.js.map +1 -1
- package/dist/lib/locator.d.ts +71 -2
- package/dist/lib/locator.d.ts.map +1 -1
- package/dist/lib/locator.js +289 -31
- package/dist/lib/locator.js.map +1 -1
- package/dist/lib/mouse.d.ts +1 -1
- package/dist/lib/mouse.d.ts.map +1 -1
- package/dist/lib/mouse.js +1 -1
- package/dist/lib/mouse.js.map +1 -1
- package/dist/lib/page.d.ts +107 -0
- package/dist/lib/page.d.ts.map +1 -0
- package/dist/lib/page.js +388 -0
- package/dist/lib/page.js.map +1 -0
- package/dist/lib/tracing.d.ts +128 -0
- package/dist/lib/tracing.d.ts.map +1 -0
- package/dist/lib/tracing.js +272 -0
- package/dist/lib/tracing.js.map +1 -0
- package/dist/lib/wait.d.ts.map +1 -1
- package/dist/lib/wait.js +14 -1
- package/dist/lib/wait.js.map +1 -1
- package/dist/lib/webelement.d.ts +2 -0
- package/dist/lib/webelement.d.ts.map +1 -1
- package/dist/lib/webelement.js +18 -0
- package/dist/lib/webelement.js.map +1 -1
- package/docs/accessibility.md +177 -0
- package/docs/api-reference.md +71 -0
- package/docs/assertions.md +182 -0
- package/docs/bidi-features.md +462 -0
- package/docs/browser-api.md +673 -0
- package/docs/browser-context.md +522 -0
- package/docs/cli.md +233 -0
- package/docs/clock.md +245 -0
- package/docs/dialogs.md +143 -0
- package/docs/driver-configuration.md +64 -0
- package/docs/element-api.md +219 -0
- package/docs/emulation.md +155 -0
- package/docs/error-codes.md +67 -0
- package/docs/getting-started.md +168 -0
- package/docs/keyboard-mouse.md +250 -0
- package/docs/mcp.md +250 -0
- package/docs/mobile-emulation.md +194 -0
- package/docs/screenshots.md +146 -0
- package/docs/selectors.md +382 -0
- package/docs/session-management.md +229 -0
- package/docs/tracing.md +282 -0
- package/package.json +23 -6
- package/skills/craftdriver/SKILL.md +84 -0
- package/skills/craftdriver/cheatsheet.md +194 -0
- package/skills/craftdriver/cli.md +104 -0
- package/skills/craftdriver/patterns.md +139 -0
package/dist/lib/page.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page — a top-level browsing context (a tab or a popup window).
|
|
3
|
+
*
|
|
4
|
+
* Maps 1-to-1 onto a WebDriver BiDi top-level `browsingContext`. Obtain via
|
|
5
|
+
* `browser.openPage()`, `browser.pages()`, or `browser.waitForPage()`.
|
|
6
|
+
* All element methods are automatically scoped to this page.
|
|
7
|
+
*
|
|
8
|
+
* BiDi path: actions target the page's browsing-context id directly.
|
|
9
|
+
* Classic fallback: switchToWindow → action (window switch is permanent until switched back).
|
|
10
|
+
*/
|
|
11
|
+
import { By } from './by.js';
|
|
12
|
+
import { ElementHandle } from './elementHandle.js';
|
|
13
|
+
import { Locator } from './locator.js';
|
|
14
|
+
import { expectSelector } from './expect.js';
|
|
15
|
+
import { until } from './wait.js';
|
|
16
|
+
import { CraftdriverError, ErrorCode } from './errors.js';
|
|
17
|
+
export class Page {
|
|
18
|
+
driver;
|
|
19
|
+
getDefaultTimeout;
|
|
20
|
+
/**
|
|
21
|
+
* BiDi browsing-context id (in BiDi mode) **or** window handle (Classic mode).
|
|
22
|
+
*/
|
|
23
|
+
contextId;
|
|
24
|
+
conn;
|
|
25
|
+
/** Owning user context. Set when the page was created via a BrowserContext. */
|
|
26
|
+
_owner;
|
|
27
|
+
constructor(driver, contextId, getDefaultTimeout, conn, owner) {
|
|
28
|
+
this.driver = driver;
|
|
29
|
+
this.contextId = contextId;
|
|
30
|
+
this.getDefaultTimeout = getDefaultTimeout;
|
|
31
|
+
this.conn = conn;
|
|
32
|
+
this._owner = owner;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The {@link BrowserContext} this page belongs to.
|
|
36
|
+
*
|
|
37
|
+
* Always defined in BiDi mode — pages created via `browser.openPage()`,
|
|
38
|
+
* `browser.waitForPage()`, `browser.pages()`, and `browser.activePage()`
|
|
39
|
+
* report `browser.defaultContext`; pages created via a non-default
|
|
40
|
+
* context report that context. Only `undefined` for pages obtained from
|
|
41
|
+
* the Classic-mode fallbacks where user contexts don't exist.
|
|
42
|
+
*/
|
|
43
|
+
context() {
|
|
44
|
+
return this._owner;
|
|
45
|
+
}
|
|
46
|
+
/** Switch the Classic driver to this window for element operations. */
|
|
47
|
+
async _activate() {
|
|
48
|
+
const prev = await this.driver.getCurrentWindowHandle();
|
|
49
|
+
if (prev !== this.contextId) {
|
|
50
|
+
await this.driver.switchToWindow(this.contextId);
|
|
51
|
+
}
|
|
52
|
+
return prev;
|
|
53
|
+
}
|
|
54
|
+
/** Switch back to the previous window after a Classic action. */
|
|
55
|
+
async _restoreTo(handle) {
|
|
56
|
+
if (handle !== this.contextId) {
|
|
57
|
+
await this.driver.switchToWindow(handle);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async _withWindow(fn) {
|
|
61
|
+
const prev = await this._activate();
|
|
62
|
+
try {
|
|
63
|
+
return await fn();
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
await this._restoreTo(prev);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// ── URL / title / navigation ──────────────────────────────────────────────
|
|
70
|
+
async url() {
|
|
71
|
+
if (this.conn) {
|
|
72
|
+
const tree = await this.conn.send('browsingContext.getTree', { root: this.contextId });
|
|
73
|
+
return tree.contexts?.[0]?.url ?? '';
|
|
74
|
+
}
|
|
75
|
+
return this._withWindow(() => this.driver.getCurrentUrl());
|
|
76
|
+
}
|
|
77
|
+
async title() {
|
|
78
|
+
if (this.conn) {
|
|
79
|
+
return this.evaluate('return document.title');
|
|
80
|
+
}
|
|
81
|
+
return this._withWindow(() => this.driver.getTitle());
|
|
82
|
+
}
|
|
83
|
+
async navigateTo(url) {
|
|
84
|
+
const resolved = this._resolveUrl(url);
|
|
85
|
+
if (this.conn) {
|
|
86
|
+
await this.conn.send('browsingContext.navigate', {
|
|
87
|
+
context: this.contextId,
|
|
88
|
+
url: resolved,
|
|
89
|
+
wait: 'complete',
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await this._withWindow(async () => {
|
|
94
|
+
await this.driver.navigateTo(resolved);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolve `url` against the owning context's `baseURL`, if any.
|
|
99
|
+
* Absolute URLs are returned as-is.
|
|
100
|
+
*/
|
|
101
|
+
_resolveUrl(url) {
|
|
102
|
+
const baseURL = this._owner?.baseURL;
|
|
103
|
+
if (!baseURL)
|
|
104
|
+
return url;
|
|
105
|
+
try {
|
|
106
|
+
// If `url` is already absolute this returns it unchanged.
|
|
107
|
+
return new URL(url, baseURL).href;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return url;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Navigate back one step in this page's session history.
|
|
115
|
+
* BiDi: `browsingContext.traverseHistory({ delta: -1 })`.
|
|
116
|
+
* Classic fallback: `POST /session/{id}/back` (per-window switch).
|
|
117
|
+
*/
|
|
118
|
+
async goBack() {
|
|
119
|
+
if (this.conn) {
|
|
120
|
+
await this.conn.send('browsingContext.traverseHistory', {
|
|
121
|
+
context: this.contextId,
|
|
122
|
+
delta: -1,
|
|
123
|
+
});
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
await this._withWindow(() => this.driver.back());
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Navigate forward one step in this page's session history.
|
|
130
|
+
* BiDi: `browsingContext.traverseHistory({ delta: +1 })`.
|
|
131
|
+
* Classic fallback: `POST /session/{id}/forward`.
|
|
132
|
+
*/
|
|
133
|
+
async goForward() {
|
|
134
|
+
if (this.conn) {
|
|
135
|
+
await this.conn.send('browsingContext.traverseHistory', {
|
|
136
|
+
context: this.contextId,
|
|
137
|
+
delta: 1,
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
await this._withWindow(() => this.driver.forward());
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Reload this page.
|
|
145
|
+
* BiDi: `browsingContext.reload` waiting for `complete`.
|
|
146
|
+
* Classic fallback: `POST /session/{id}/refresh`.
|
|
147
|
+
*/
|
|
148
|
+
async reload() {
|
|
149
|
+
if (this.conn) {
|
|
150
|
+
await this.conn.send('browsingContext.reload', {
|
|
151
|
+
context: this.contextId,
|
|
152
|
+
wait: 'complete',
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
await this._withWindow(() => this.driver.refresh());
|
|
157
|
+
}
|
|
158
|
+
async waitForLoadState(state = 'load', opts) {
|
|
159
|
+
const timeout = opts?.timeout ?? 30000;
|
|
160
|
+
if (this.conn) {
|
|
161
|
+
const readyState = await this.evaluate('return document.readyState');
|
|
162
|
+
const satisfied = state === 'load'
|
|
163
|
+
? readyState === 'complete'
|
|
164
|
+
: readyState === 'interactive' || readyState === 'complete';
|
|
165
|
+
if (satisfied)
|
|
166
|
+
return;
|
|
167
|
+
const eventName = state === 'load' ? 'browsingContext.load' : 'browsingContext.domContentLoaded';
|
|
168
|
+
const ctxId = this.contextId;
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const timer = setTimeout(() => { off(); reject(new Error(`waitForLoadState timed out after ${timeout}ms`)); }, timeout);
|
|
171
|
+
const off = this.conn.on(eventName, (params) => {
|
|
172
|
+
if (params.context === ctxId) {
|
|
173
|
+
clearTimeout(timer);
|
|
174
|
+
off();
|
|
175
|
+
resolve();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// Classic
|
|
181
|
+
return this._withWindow(async () => {
|
|
182
|
+
const deadline = Date.now() + timeout;
|
|
183
|
+
while (Date.now() < deadline) {
|
|
184
|
+
const rs = await this.driver.executeScript('return document.readyState', []);
|
|
185
|
+
if (rs === 'complete' || (state === 'domcontentloaded' && rs === 'interactive'))
|
|
186
|
+
return;
|
|
187
|
+
await new Promise(r => setTimeout(r, 100));
|
|
188
|
+
}
|
|
189
|
+
throw new CraftdriverError(ErrorCode.TIMEOUT_WAITING_LOAD, `waitForLoadState timed out after ${timeout}ms`, { detail: { state, timeout } });
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
// ── Evaluate ─────────────────────────────────────────────────────────────
|
|
193
|
+
async evaluate(fn, ...args) {
|
|
194
|
+
const fnSrc = typeof fn === 'function' ? fn.toString() : fn;
|
|
195
|
+
if (this.conn) {
|
|
196
|
+
const target = { context: this.contextId };
|
|
197
|
+
let result;
|
|
198
|
+
if (typeof fn === 'function') {
|
|
199
|
+
result = await this.conn.send('script.callFunction', {
|
|
200
|
+
functionDeclaration: fnSrc,
|
|
201
|
+
target,
|
|
202
|
+
arguments: args.map(serializeLocalValue),
|
|
203
|
+
awaitPromise: true,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
result = await this.conn.send('script.callFunction', {
|
|
208
|
+
functionDeclaration: `function() { ${fnSrc} }`,
|
|
209
|
+
target,
|
|
210
|
+
arguments: [],
|
|
211
|
+
awaitPromise: true,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (result.type === 'exception') {
|
|
215
|
+
throw new CraftdriverError(ErrorCode.EVAL_THREW, `evaluate() threw an exception: ${result.exceptionDetails?.text ?? 'unknown error'}`, { detail: { exception: result.exceptionDetails?.text ?? null } });
|
|
216
|
+
}
|
|
217
|
+
if (!result.result)
|
|
218
|
+
return undefined;
|
|
219
|
+
return unwrapRemoteValue(result.result);
|
|
220
|
+
}
|
|
221
|
+
return this._withWindow(async () => {
|
|
222
|
+
if (typeof fn === 'function') {
|
|
223
|
+
return this.driver.executeScript(`return (${fnSrc}).apply(null, Array.from(arguments))`, args);
|
|
224
|
+
}
|
|
225
|
+
return this.driver.executeScript(fn, args);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
// ── Content ──────────────────────────────────────────────────────────────
|
|
229
|
+
/**
|
|
230
|
+
* Return the full HTML serialization of the page (`document.documentElement.outerHTML`).
|
|
231
|
+
*/
|
|
232
|
+
async content() {
|
|
233
|
+
return this.evaluate('return document.documentElement.outerHTML');
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Replace the page contents with the given HTML and wait until the
|
|
237
|
+
* specified load state is reached.
|
|
238
|
+
*
|
|
239
|
+
* Implementation: navigates to a `data:text/html` URL so the new
|
|
240
|
+
* document goes through a real navigation (load events fire correctly).
|
|
241
|
+
*
|
|
242
|
+
* @param html The HTML document to load.
|
|
243
|
+
* @param opts.waitUntil Load state to wait for. Defaults to `'load'`.
|
|
244
|
+
*/
|
|
245
|
+
async setContent(html, opts) {
|
|
246
|
+
const waitUntil = opts?.waitUntil ?? 'load';
|
|
247
|
+
const url = `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
|
|
248
|
+
if (this.conn) {
|
|
249
|
+
const bidiWait = waitUntil === 'none' ? 'none'
|
|
250
|
+
: waitUntil === 'domcontentloaded' ? 'interactive'
|
|
251
|
+
: 'complete';
|
|
252
|
+
await this.conn.send('browsingContext.navigate', {
|
|
253
|
+
context: this.contextId,
|
|
254
|
+
url,
|
|
255
|
+
wait: bidiWait,
|
|
256
|
+
});
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
await this._withWindow(async () => {
|
|
260
|
+
await this.driver.navigateTo(url);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// ── Element methods ──────────────────────────────────────────────────────
|
|
264
|
+
_makeContextSwitcher() {
|
|
265
|
+
// Always switch Classic window to this context for element operations.
|
|
266
|
+
// In Chrome, BiDi context IDs equal Classic window handles.
|
|
267
|
+
let savedHandle;
|
|
268
|
+
return {
|
|
269
|
+
in: async () => {
|
|
270
|
+
savedHandle = await this._activate();
|
|
271
|
+
},
|
|
272
|
+
out: async () => {
|
|
273
|
+
await this._restoreTo(savedHandle);
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
find(selector) {
|
|
278
|
+
const by = typeof selector === 'string' ? By.css(selector) : selector;
|
|
279
|
+
const handle = new ElementHandle(this.driver, by, this.getDefaultTimeout);
|
|
280
|
+
const sw = this._makeContextSwitcher();
|
|
281
|
+
if (sw)
|
|
282
|
+
handle.withContext(sw);
|
|
283
|
+
return handle;
|
|
284
|
+
}
|
|
285
|
+
locator(selector) {
|
|
286
|
+
const by = typeof selector === 'string' ? By.css(selector) : selector;
|
|
287
|
+
const loc = new Locator(this.driver, by, this.getDefaultTimeout);
|
|
288
|
+
const sw = this._makeContextSwitcher();
|
|
289
|
+
if (sw)
|
|
290
|
+
loc.withContext(sw);
|
|
291
|
+
return loc;
|
|
292
|
+
}
|
|
293
|
+
expect(selector) {
|
|
294
|
+
const by = typeof selector === 'string' ? By.css(selector) : selector;
|
|
295
|
+
return expectSelector(this.driver, by, this.getDefaultTimeout, this._makeContextSwitcher());
|
|
296
|
+
}
|
|
297
|
+
async findAll(selector) {
|
|
298
|
+
const by = typeof selector === 'string' ? By.css(selector) : selector;
|
|
299
|
+
const webElements = await this._withWindow(() => this.driver.findElements(by));
|
|
300
|
+
return webElements.map((we) => ElementHandle.fromWebElement(this.driver, we, this.getDefaultTimeout));
|
|
301
|
+
}
|
|
302
|
+
async click(selector, opts) {
|
|
303
|
+
const by = typeof selector === 'string' ? By.css(selector) : selector;
|
|
304
|
+
return this._withWindow(async () => {
|
|
305
|
+
const el = await this.driver.wait(until.elementIsVisible(by), {
|
|
306
|
+
timeout: opts?.timeout ?? this.getDefaultTimeout(),
|
|
307
|
+
});
|
|
308
|
+
await el.click();
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
async fill(selector, text, opts) {
|
|
312
|
+
const by = typeof selector === 'string' ? By.css(selector) : selector;
|
|
313
|
+
return this._withWindow(async () => {
|
|
314
|
+
const el = await this.driver.wait(until.elementIsVisible(by), {
|
|
315
|
+
timeout: opts?.timeout ?? this.getDefaultTimeout(),
|
|
316
|
+
});
|
|
317
|
+
await el.click();
|
|
318
|
+
await el.clear();
|
|
319
|
+
await el.sendKeys(text);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/** Return the BiDi browsing-context id (or Classic window handle) for this page. */
|
|
323
|
+
id() {
|
|
324
|
+
return this.contextId;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// ── BiDi serialization helpers ───────────────────────────────────────────────
|
|
328
|
+
function serializeLocalValue(v) {
|
|
329
|
+
if (v === undefined)
|
|
330
|
+
return { type: 'undefined' };
|
|
331
|
+
if (v === null)
|
|
332
|
+
return { type: 'null' };
|
|
333
|
+
if (typeof v === 'string')
|
|
334
|
+
return { type: 'string', value: v };
|
|
335
|
+
if (typeof v === 'boolean')
|
|
336
|
+
return { type: 'boolean', value: v };
|
|
337
|
+
if (typeof v === 'bigint')
|
|
338
|
+
return { type: 'bigint', value: String(v) };
|
|
339
|
+
if (typeof v === 'number') {
|
|
340
|
+
if (Number.isNaN(v))
|
|
341
|
+
return { type: 'number', value: 'NaN' };
|
|
342
|
+
if (v === Infinity)
|
|
343
|
+
return { type: 'number', value: 'Infinity' };
|
|
344
|
+
if (v === -Infinity)
|
|
345
|
+
return { type: 'number', value: '-Infinity' };
|
|
346
|
+
if (Object.is(v, -0))
|
|
347
|
+
return { type: 'number', value: '-0' };
|
|
348
|
+
return { type: 'number', value: v };
|
|
349
|
+
}
|
|
350
|
+
if (Array.isArray(v))
|
|
351
|
+
return { type: 'array', value: v.map(serializeLocalValue) };
|
|
352
|
+
if (typeof v === 'object') {
|
|
353
|
+
return {
|
|
354
|
+
type: 'object',
|
|
355
|
+
value: Object.entries(v).map(([k, val]) => [k, serializeLocalValue(val)]),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
throw new CraftdriverError(ErrorCode.EVAL_BAD_ARG, `evaluate() argument of type "${typeof v}" is not JSON-serializable.`, { detail: { argType: typeof v } });
|
|
359
|
+
}
|
|
360
|
+
function unwrapRemoteValue(v) {
|
|
361
|
+
switch (v.type) {
|
|
362
|
+
case 'undefined': return undefined;
|
|
363
|
+
case 'null': return null;
|
|
364
|
+
case 'string': return v.value;
|
|
365
|
+
case 'boolean': return v.value;
|
|
366
|
+
case 'bigint': return BigInt(v.value);
|
|
367
|
+
case 'number': {
|
|
368
|
+
if (v.value === 'NaN')
|
|
369
|
+
return NaN;
|
|
370
|
+
if (v.value === 'Infinity')
|
|
371
|
+
return Infinity;
|
|
372
|
+
if (v.value === '-Infinity')
|
|
373
|
+
return -Infinity;
|
|
374
|
+
if (v.value === '-0')
|
|
375
|
+
return -0;
|
|
376
|
+
return v.value;
|
|
377
|
+
}
|
|
378
|
+
case 'array': return (v.value ?? []).map(unwrapRemoteValue);
|
|
379
|
+
case 'object':
|
|
380
|
+
return Object.fromEntries((v.value ?? []).map(([k, val]) => [
|
|
381
|
+
typeof k === 'string' ? k : String(unwrapRemoteValue(k)),
|
|
382
|
+
unwrapRemoteValue(val),
|
|
383
|
+
]));
|
|
384
|
+
case 'date': return new Date(v.value);
|
|
385
|
+
default: return null;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/lib/page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracer — append-only, crash-resilient session recorder for bug
|
|
3
|
+
* investigation.
|
|
4
|
+
*
|
|
5
|
+
* Streams events to `<outDir>/trace.ndjson` synchronously, one line per
|
|
6
|
+
* event. Screenshots are written to `<outDir>/screenshots/NNNN.png` as
|
|
7
|
+
* their captures resolve. There is **no finalisation step** — if the
|
|
8
|
+
* test throws (or the process is killed) every event up to that point is
|
|
9
|
+
* already on disk and the partial file is still valid NDJSON.
|
|
10
|
+
*
|
|
11
|
+
* **BiDi-only.** Tracing relies on the same subscriptions that power
|
|
12
|
+
* `browser.logs` and `browser.network` and is unavailable in Classic mode.
|
|
13
|
+
*/
|
|
14
|
+
import type { Browser } from './browser.js';
|
|
15
|
+
import type { BiDiConnection } from './bidi/connection.js';
|
|
16
|
+
/** Screenshot mode for tracing. */
|
|
17
|
+
export type TraceScreenshotMode = boolean | 'auto' | 'off';
|
|
18
|
+
export interface TraceStartOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Output directory. Created if missing. The trace itself lives at
|
|
21
|
+
* `<outDir>/trace.ndjson`; screenshots, if any, at
|
|
22
|
+
* `<outDir>/screenshots/NNNN.png`.
|
|
23
|
+
*/
|
|
24
|
+
outDir: string;
|
|
25
|
+
/**
|
|
26
|
+
* Snap screenshots tied to evidence moments rather than a timer:
|
|
27
|
+
* - `'auto'` / `true` *(default)* — one PNG before every logged action
|
|
28
|
+
* and one on every page error.
|
|
29
|
+
* - `'off'` / `false` — no screenshots.
|
|
30
|
+
*/
|
|
31
|
+
screenshots?: TraceScreenshotMode;
|
|
32
|
+
/** Log public-API actions (click, fill, navigateTo, …). Default true. */
|
|
33
|
+
actions?: boolean;
|
|
34
|
+
/** Record network request/response events. Default true. */
|
|
35
|
+
network?: boolean;
|
|
36
|
+
/** Capture console + page errors. Default true. */
|
|
37
|
+
console?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type TraceEvent = {
|
|
40
|
+
t: number;
|
|
41
|
+
type: 'meta';
|
|
42
|
+
startedAt?: string;
|
|
43
|
+
endedAt?: string;
|
|
44
|
+
opts?: unknown;
|
|
45
|
+
} | {
|
|
46
|
+
t: number;
|
|
47
|
+
type: 'console';
|
|
48
|
+
level: string;
|
|
49
|
+
text: string;
|
|
50
|
+
} | {
|
|
51
|
+
t: number;
|
|
52
|
+
type: 'error';
|
|
53
|
+
text: string;
|
|
54
|
+
} | {
|
|
55
|
+
t: number;
|
|
56
|
+
type: 'request';
|
|
57
|
+
url: string;
|
|
58
|
+
method: string;
|
|
59
|
+
requestId?: string;
|
|
60
|
+
} | {
|
|
61
|
+
t: number;
|
|
62
|
+
type: 'response';
|
|
63
|
+
url: string;
|
|
64
|
+
status: number;
|
|
65
|
+
mimeType?: string;
|
|
66
|
+
fromCache?: true;
|
|
67
|
+
requestId?: string;
|
|
68
|
+
} | {
|
|
69
|
+
t: number;
|
|
70
|
+
type: 'navigation';
|
|
71
|
+
url: string;
|
|
72
|
+
context?: string;
|
|
73
|
+
} | {
|
|
74
|
+
t: number;
|
|
75
|
+
type: 'screenshot';
|
|
76
|
+
file: string;
|
|
77
|
+
actionIndex?: number;
|
|
78
|
+
reason: 'action' | 'error';
|
|
79
|
+
} | {
|
|
80
|
+
t: number;
|
|
81
|
+
type: 'action';
|
|
82
|
+
name: string;
|
|
83
|
+
args?: unknown[];
|
|
84
|
+
selector?: string;
|
|
85
|
+
};
|
|
86
|
+
export declare class Tracer {
|
|
87
|
+
private browser;
|
|
88
|
+
private conn;
|
|
89
|
+
private startedAtMs;
|
|
90
|
+
private startedAtIso;
|
|
91
|
+
private outDir;
|
|
92
|
+
private fd;
|
|
93
|
+
private unsubs;
|
|
94
|
+
private screenshotIndex;
|
|
95
|
+
private screenshotDirEnsured;
|
|
96
|
+
private running;
|
|
97
|
+
private actionsEnabled;
|
|
98
|
+
private screenshotMode;
|
|
99
|
+
private actionIndex;
|
|
100
|
+
/** Tracks in-flight screenshot captures so `stop()` can drain them. */
|
|
101
|
+
private pendingCaptures;
|
|
102
|
+
constructor(browser: Browser, conn: BiDiConnection);
|
|
103
|
+
get isRunning(): boolean;
|
|
104
|
+
start(opts: TraceStartOptions): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Record a public-API action. Fire-and-forget — the event is written
|
|
107
|
+
* **synchronously** to `trace.ndjson` before returning, so a thrown
|
|
108
|
+
* `expect` on the next line cannot lose it. When `screenshots: 'auto'`
|
|
109
|
+
* is on, also enqueues a pre-action screenshot capture (async; doesn't
|
|
110
|
+
* block the caller).
|
|
111
|
+
*
|
|
112
|
+
* Zero-cost when no tracer is running or `actions: false`.
|
|
113
|
+
*/
|
|
114
|
+
recordAction(name: string, args?: unknown[], selector?: string): void;
|
|
115
|
+
private scheduleScreenshot;
|
|
116
|
+
/**
|
|
117
|
+
* Stop tracing cleanly: drain in-flight screenshots, write the closing
|
|
118
|
+
* `meta` line, and close the file. If the test throws and `stop()` is
|
|
119
|
+
* never called, the file is still a valid NDJSON trace — just without
|
|
120
|
+
* the closing marker.
|
|
121
|
+
*/
|
|
122
|
+
stop(): Promise<void>;
|
|
123
|
+
/** Close the file without writing an end marker. Used by `Browser.quit()`. */
|
|
124
|
+
abort(): void;
|
|
125
|
+
private push;
|
|
126
|
+
private writeLine;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/lib/tracing.ts"],"names":[],"mappings":"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"}
|