craftdriver 1.0.3 → 1.1.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 +25 -3
- package/README.md +80 -160
- package/dist/lib/browser.d.ts +22 -0
- package/dist/lib/browser.d.ts.map +1 -1
- package/dist/lib/browser.js +14 -1
- package/dist/lib/browser.js.map +1 -1
- package/dist/lib/chrome.d.ts +15 -3
- package/dist/lib/chrome.d.ts.map +1 -1
- package/dist/lib/chrome.js +4 -2
- package/dist/lib/chrome.js.map +1 -1
- package/dist/lib/driver.d.ts.map +1 -1
- package/dist/lib/driver.js +2 -0
- package/dist/lib/driver.js.map +1 -1
- package/dist/lib/driverManager.d.ts +31 -0
- package/dist/lib/driverManager.d.ts.map +1 -1
- package/dist/lib/driverManager.js +165 -31
- package/dist/lib/driverManager.js.map +1 -1
- package/dist/lib/firefox.d.ts +4 -3
- package/dist/lib/firefox.d.ts.map +1 -1
- package/dist/lib/firefox.js.map +1 -1
- package/dist/lib/http.d.ts +1 -1
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +35 -7
- package/dist/lib/http.js.map +1 -1
- package/dist/lib/timing.d.ts +13 -0
- package/dist/lib/timing.d.ts.map +1 -1
- package/dist/lib/timing.js +13 -0
- package/dist/lib/timing.js.map +1 -1
- package/dist/lib/types.d.ts +2 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/docs/agents.md +92 -0
- package/docs/api-reference.md +108 -46
- package/docs/browser-api.md +2 -1
- package/docs/browser-context.md +4 -7
- package/docs/browser-logs.md +158 -0
- package/docs/cli.md +26 -26
- package/docs/driver-configuration.md +103 -4
- package/docs/element-api.md +37 -6
- package/docs/emulation.md +6 -2
- package/docs/index.md +64 -0
- package/docs/keyboard-mouse.md +28 -10
- package/docs/mobile-emulation.md +5 -2
- package/docs/network.md +203 -0
- package/docs/public/craftdriver-mark.svg +15 -0
- package/docs/public/social-card.svg +27 -0
- package/docs/recipes/accessibility-gate.md +53 -0
- package/docs/recipes/console-error-gate.md +57 -0
- package/docs/recipes/file-upload-download.md +58 -0
- package/docs/recipes/login-once-reuse-session.md +73 -0
- package/docs/recipes/mobile-flow-with-network-and-logs.md +57 -0
- package/docs/recipes/mock-api-and-assert-network.md +60 -0
- package/docs/recipes/multi-user-contexts.md +58 -0
- package/docs/recipes/trace-failing-test.md +64 -0
- package/docs/recipes/virtual-clock-time-sensitive-ui.md +60 -0
- package/docs/recipes/vitest-browser-lifecycle.md +56 -0
- package/docs/recipes.md +33 -0
- package/docs/selectors.md +22 -1
- package/docs/session-management.md +18 -1
- package/docs/standards.md +40 -0
- package/docs/why-craftdriver.md +28 -0
- package/docs/zero-config-drivers.md +64 -0
- package/package.json +19 -5
- package/docs/bidi-features.md +0 -470
package/docs/agents.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# AI Agent Guide
|
|
2
|
+
|
|
3
|
+
CraftDriver ships agent-facing tooling in the npm package. You can use the library directly, drive the browser from the shell, expose tools through MCP, or drop assistant rules into a project.
|
|
4
|
+
|
|
5
|
+
## Which Surface Should I Use?
|
|
6
|
+
|
|
7
|
+
| Agent environment | Best surface | Why |
|
|
8
|
+
| -------------------------- | ------------------ | -------------------------------------------------------------------------------- |
|
|
9
|
+
| Shell-capable coding agent | CLI | Simple commands, persistent daemon, JSON output when piped. |
|
|
10
|
+
| MCP-aware host | MCP server | Typed tools, compact accessibility snapshots, artifact spilling for screenshots. |
|
|
11
|
+
| Code-writing assistant | `craftdriver init` | Project rules teach selector preference, auto-waiting, and error-code handling. |
|
|
12
|
+
| Custom orchestrator | Skill pack | Small always-on `SKILL.md` with deeper references loaded on demand. |
|
|
13
|
+
|
|
14
|
+
## CLI
|
|
15
|
+
|
|
16
|
+
The CLI is good for agents that can run shell commands.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx craftdriver daemon start
|
|
20
|
+
npx craftdriver go http://127.0.0.1:8080/login.html
|
|
21
|
+
npx craftdriver snapshot
|
|
22
|
+
npx craftdriver fill 'label=Username' alice
|
|
23
|
+
npx craftdriver fill 'label=Password' hunter2
|
|
24
|
+
npx craftdriver click 'role=button[name=Sign in]'
|
|
25
|
+
npx craftdriver text '#result'
|
|
26
|
+
npx craftdriver daemon stop
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
State survives between calls while the daemon is running, so an agent can explore, act, inspect, and refine.
|
|
30
|
+
|
|
31
|
+
Read the full [CLI reference](./cli.md).
|
|
32
|
+
|
|
33
|
+
## MCP Server
|
|
34
|
+
|
|
35
|
+
MCP-aware hosts can use `craftdriver mcp`.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
claude mcp add craftdriver -- npx -y craftdriver mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```jsonc
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"craftdriver": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["-y", "craftdriver", "mcp"],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Mutating tools return compact accessibility snapshot diffs, so the agent can see what changed without a separate read. Large artifacts such as screenshots are written to disk instead of inlined into model context.
|
|
53
|
+
|
|
54
|
+
Read the full [MCP reference](./mcp.md).
|
|
55
|
+
|
|
56
|
+
## Assistant Bootstrap Files
|
|
57
|
+
|
|
58
|
+
Use `craftdriver init` inside a project that uses CraftDriver:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx craftdriver init agents
|
|
62
|
+
npx craftdriver init copilot
|
|
63
|
+
npx craftdriver init claude
|
|
64
|
+
npx craftdriver init cursor
|
|
65
|
+
npx craftdriver init gemini
|
|
66
|
+
npx craftdriver init all
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The generated files tell assistants to:
|
|
70
|
+
|
|
71
|
+
- prefer semantic selectors before brittle CSS
|
|
72
|
+
- rely on auto-waiting instead of sleeps
|
|
73
|
+
- inspect stable `CraftdriverError.code` values
|
|
74
|
+
- use the CLI or MCP server for live browser work
|
|
75
|
+
- keep test code aligned with the public TypeScript API
|
|
76
|
+
|
|
77
|
+
## Skill Pack
|
|
78
|
+
|
|
79
|
+
The npm tarball includes a tiered skill pack under `skills/craftdriver/`:
|
|
80
|
+
|
|
81
|
+
| File | Purpose |
|
|
82
|
+
| --------------- | -------------------------------------------------------------------------------------- |
|
|
83
|
+
| `SKILL.md` | Always-on rules and routing, kept small for model context. |
|
|
84
|
+
| `cheatsheet.md` | Fast command and API reference for tests. |
|
|
85
|
+
| `patterns.md` | Worked recipes such as login, uploads, network waits, a11y, tracing, and virtual time. |
|
|
86
|
+
| `cli.md` | Agent-facing CLI reference. |
|
|
87
|
+
|
|
88
|
+
Point compatible agents at:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
node_modules/craftdriver/skills/craftdriver/SKILL.md
|
|
92
|
+
```
|
package/docs/api-reference.md
CHANGED
|
@@ -1,71 +1,133 @@
|
|
|
1
1
|
# API reference
|
|
2
2
|
|
|
3
|
-
Every symbol re-exported from [`src/index.ts`](../src/index.ts)
|
|
3
|
+
Every symbol re-exported from [`src/index.ts`](../src/index.ts), grouped by the feature area most users look for first.
|
|
4
4
|
Generated by `scripts/gen-api-reference.mjs` — do not edit by hand.
|
|
5
5
|
|
|
6
6
|
Run `npm run docs:api` to regenerate. CI fails when this file is out of date.
|
|
7
7
|
|
|
8
|
+
Start with [`Browser`](./browser-api.md), [`By`](./selectors.md) / [`Locator`](./selectors.md), and the feature guide that matches the job you are automating.
|
|
9
|
+
|
|
10
|
+
## Browser And Pages
|
|
11
|
+
|
|
12
|
+
Launch browsers, move between pages and frames, handle dialogs, and wait for navigation.
|
|
13
|
+
|
|
8
14
|
| Symbol | Kind | Summary | Docs |
|
|
9
15
|
|---|---|---|---|
|
|
10
|
-
| `A11y` | class | Ergonomic wrapper around axe-core. Obtain instances via the `.a11y` accessor on `Browser`, `ElementHandle`, or `Locator` — never construct directly. | [accessibility](accessibility.md) |
|
|
11
|
-
| `A11yError` | class | Thrown by `A11y.check()` when violations are found. | [accessibility](accessibility.md) |
|
|
12
|
-
| `A11yImpact` | type | Severity buckets reported by axe-core. | [accessibility](accessibility.md) |
|
|
13
|
-
| `A11yOptions` | type | — | [accessibility](accessibility.md) |
|
|
14
|
-
| `A11yResult` | type | — | [accessibility](accessibility.md) |
|
|
15
|
-
| `A11yViolation` | type | — | [accessibility](accessibility.md) |
|
|
16
|
-
| `A11yViolationNode` | type | — | [accessibility](accessibility.md) |
|
|
17
16
|
| `Browser` | class | — | [browser-api](browser-api.md) |
|
|
17
|
+
| `LaunchOptions` | type | — | [browser-api](browser-api.md) |
|
|
18
|
+
| `LoadState` | type | When to consider a navigation complete. - `'load'` — page `load` event has fired (default) - `'domcontentloaded'` — `DOMContentLoaded` has fired (faster, no waiting for images/fonts) - `'networkidle'` — `load` + no in-flight requests for 500 ms - `'none'` — do not wait; return as soon as the navigation is initiated | [browser-api](browser-api.md) |
|
|
19
|
+
| `Page` | class | — | [browser-api](browser-api.md) |
|
|
20
|
+
| `Frame` | class | — | [browser-api](browser-api.md) |
|
|
21
|
+
| `Dialog` | type | Represents an open browser dialog (alert / confirm / prompt). Passed to handlers registered with `browser.onDialog()`. | [browser-api](browser-api.md) |
|
|
22
|
+
| `DialogType` | type | The type of a browser dialog. | [browser-api](browser-api.md) |
|
|
23
|
+
| `Download` | type | A file downloaded during a `waitForDownload()` call. | [browser-api](browser-api.md) |
|
|
24
|
+
|
|
25
|
+
## Locators And Elements
|
|
26
|
+
|
|
27
|
+
Find page content with semantic locators and selector helpers.
|
|
28
|
+
|
|
29
|
+
| Symbol | Kind | Summary | Docs |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| `By` | class | — | [selectors](selectors.md) |
|
|
32
|
+
| `Locator` | class | — | [selectors](selectors.md) |
|
|
33
|
+
|
|
34
|
+
## Input
|
|
35
|
+
|
|
36
|
+
Drive keyboard, mouse, and low-level key values.
|
|
37
|
+
|
|
38
|
+
| Symbol | Kind | Summary | Docs |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `Key` | const | — | [keyboard-mouse](keyboard-mouse.md) |
|
|
41
|
+
| `Keyboard` | class | — | [keyboard-mouse](keyboard-mouse.md) |
|
|
42
|
+
| `Mouse` | class | — | [keyboard-mouse](keyboard-mouse.md) |
|
|
43
|
+
|
|
44
|
+
## Contexts And Sessions
|
|
45
|
+
|
|
46
|
+
Isolate users, manage cookies, and save or restore browser state.
|
|
47
|
+
|
|
48
|
+
| Symbol | Kind | Summary | Docs |
|
|
49
|
+
|---|---|---|---|
|
|
18
50
|
| `BrowserContext` | class | — | [browser-context](browser-context.md) |
|
|
19
51
|
| `BrowserContextConfig` | type | Per-context options stored at creation time. | [browser-context](browser-context.md) |
|
|
20
52
|
| `BrowserContextHooks` | type | Internal hooks the owning {@link Browser } passes to a new context. | [browser-context](browser-context.md) |
|
|
21
|
-
| `By` | class | — | [selectors](selectors.md) |
|
|
22
|
-
| `ChromeService` | class | — | [getting-started](getting-started.md) |
|
|
23
|
-
| `ChromeServiceOptions` | type | — | [getting-started](getting-started.md) |
|
|
24
53
|
| `ClearCookiesFilter` | type | Filter applied to {@link BrowserContext.clearCookies}. | [browser-context](browser-context.md) |
|
|
54
|
+
| `ContextStorageStateOptions` | type | Options for {@link BrowserContext.storageState}. | [browser-context](browser-context.md) |
|
|
55
|
+
| `InitScriptHandle` | type | A handle returned by {@link BrowserContext.addInitScript}. | [browser-context](browser-context.md) |
|
|
56
|
+
| `RoutePattern` | type | Pattern accepted by {@link BrowserContext.route}. Same shape as the browser-level interceptor. | [browser-context](browser-context.md) |
|
|
57
|
+
| `Cookie` | type | — | [session-management](session-management.md) |
|
|
58
|
+
| `CookieInput` | type | — | [session-management](session-management.md) |
|
|
59
|
+
| `SessionState` | type | — | [session-management](session-management.md) |
|
|
60
|
+
| `SessionStateManager` | class | — | [session-management](session-management.md) |
|
|
61
|
+
| `StorageStateOptions` | type | — | [session-management](session-management.md) |
|
|
62
|
+
|
|
63
|
+
## Network
|
|
64
|
+
|
|
65
|
+
Mock, intercept, observe, and assert browser network traffic.
|
|
66
|
+
|
|
67
|
+
| Symbol | Kind | Summary | Docs |
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
| `NetworkInterceptor` | class | — | [network](network.md) |
|
|
70
|
+
| `MockResponse` | type | — | [network](network.md) |
|
|
71
|
+
| `InterceptedRequest` | type | — | [network](network.md) |
|
|
72
|
+
| `InterceptedResponse` | type | — | [network](network.md) |
|
|
73
|
+
|
|
74
|
+
## Logs And Tracing
|
|
75
|
+
|
|
76
|
+
Capture console output, JavaScript errors, and trace artifacts.
|
|
77
|
+
|
|
78
|
+
| Symbol | Kind | Summary | Docs |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `LogMonitor` | class | — | [browser-logs](browser-logs.md) |
|
|
81
|
+
| `ConsoleMessage` | type | — | [browser-logs](browser-logs.md) |
|
|
82
|
+
| `JavaScriptError` | type | — | [browser-logs](browser-logs.md) |
|
|
83
|
+
| `LogMessage` | type | — | [browser-logs](browser-logs.md) |
|
|
84
|
+
| `TraceStartOptions` | type | — | [tracing](tracing.md) |
|
|
85
|
+
| `TraceScreenshotMode` | type | Screenshot mode for tracing. | [tracing](tracing.md) |
|
|
86
|
+
| `TraceEvent` | type | — | [tracing](tracing.md) |
|
|
87
|
+
|
|
88
|
+
## Emulation And Time
|
|
89
|
+
|
|
90
|
+
Configure devices, emulation overrides, and deterministic browser time.
|
|
91
|
+
|
|
92
|
+
| Symbol | Kind | Summary | Docs |
|
|
93
|
+
|---|---|---|---|
|
|
94
|
+
| `devices` | const | Common mobile device presets | [browser-api](browser-api.md) |
|
|
95
|
+
| `DeviceMetrics` | type | Device metrics for custom mobile emulation | [browser-api](browser-api.md) |
|
|
96
|
+
| `DeviceName` | type | — | [browser-api](browser-api.md) |
|
|
97
|
+
| `MobileEmulation` | type | Mobile emulation configuration | [browser-api](browser-api.md) |
|
|
98
|
+
| `EmulateOptions` | type | Options for {@link Browser.emulate}. Every field is independent; only the keys you pass are applied, others stay at their previous value. Passing `null` for a field clears the override for that field. | [browser-api](browser-api.md) |
|
|
25
99
|
| `Clock` | class | Controls the virtual clock inside the browser page. | [clock](clock.md) |
|
|
26
100
|
| `ClockInstallOptions` | type | Options for {@link Clock.install}. | [clock](clock.md) |
|
|
27
101
|
| `ClockTime` | type | Accepted forms for a point in time. | [clock](clock.md) |
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
102
|
+
|
|
103
|
+
## Accessibility
|
|
104
|
+
|
|
105
|
+
Run axe-core accessibility checks and inspect violation details.
|
|
106
|
+
|
|
107
|
+
| Symbol | Kind | Summary | Docs |
|
|
108
|
+
|---|---|---|---|
|
|
109
|
+
| `A11y` | class | Ergonomic wrapper around axe-core. Obtain instances via the `.a11y` accessor on `Browser`, `ElementHandle`, or `Locator` — never construct directly. | [accessibility](accessibility.md) |
|
|
110
|
+
| `A11yError` | class | Thrown by `A11y.check()` when violations are found. | [accessibility](accessibility.md) |
|
|
111
|
+
| `A11yImpact` | type | Severity buckets reported by axe-core. | [accessibility](accessibility.md) |
|
|
112
|
+
| `A11yOptions` | type | — | [accessibility](accessibility.md) |
|
|
113
|
+
| `A11yResult` | type | — | [accessibility](accessibility.md) |
|
|
114
|
+
| `A11yViolation` | type | — | [accessibility](accessibility.md) |
|
|
115
|
+
| `A11yViolationNode` | type | — | [accessibility](accessibility.md) |
|
|
116
|
+
|
|
117
|
+
## Errors And Driver Services
|
|
118
|
+
|
|
119
|
+
Handle stable CraftDriver errors or customize browser driver services.
|
|
120
|
+
|
|
121
|
+
| Symbol | Kind | Summary | Docs |
|
|
122
|
+
|---|---|---|---|
|
|
32
123
|
| `CraftdriverError` | class | Base class for every error thrown from the public API. | [error-codes](error-codes.md) |
|
|
33
124
|
| `CraftdriverErrorOptions` | type | — | [error-codes](error-codes.md) |
|
|
34
|
-
| `DeviceMetrics` | type | Device metrics for custom mobile emulation | [browser-api](browser-api.md) |
|
|
35
|
-
| `DeviceName` | type | — | [browser-api](browser-api.md) |
|
|
36
|
-
| `devices` | const | Common mobile device presets | [browser-api](browser-api.md) |
|
|
37
|
-
| `Dialog` | type | Represents an open browser dialog (alert / confirm / prompt). Passed to handlers registered with `browser.onDialog()`. | [browser-api](browser-api.md) |
|
|
38
|
-
| `DialogType` | type | The type of a browser dialog. | [browser-api](browser-api.md) |
|
|
39
|
-
| `Download` | type | A file downloaded during a `waitForDownload()` call. | [browser-api](browser-api.md) |
|
|
40
|
-
| `EmulateOptions` | type | Options for {@link Browser.emulate}. Every field is independent; only the keys you pass are applied, others stay at their previous value. Passing `null` for a field clears the override for that field. | [browser-api](browser-api.md) |
|
|
41
125
|
| `ErrorCode` | const | Stable, machine-readable error codes for the public craftdriver API. | [error-codes](error-codes.md) |
|
|
42
126
|
| `ErrorCodeName` | type | — | [error-codes](error-codes.md) |
|
|
43
127
|
| `ErrorCodeValue` | type | — | [error-codes](error-codes.md) |
|
|
128
|
+
| `ChromeService` | class | — | [getting-started](getting-started.md) |
|
|
129
|
+
| `ChromeServiceOptions` | type | — | [getting-started](getting-started.md) |
|
|
44
130
|
| `FirefoxService` | class | — | [getting-started](getting-started.md) |
|
|
45
131
|
| `FirefoxServiceOptions` | type | — | [getting-started](getting-started.md) |
|
|
46
|
-
| `Frame` | class | — | [browser-api](browser-api.md) |
|
|
47
|
-
| `InitScriptHandle` | type | A handle returned by {@link BrowserContext.addInitScript}. | [browser-context](browser-context.md) |
|
|
48
|
-
| `InterceptedRequest` | type | — | [bidi-features](bidi-features.md) |
|
|
49
|
-
| `InterceptedResponse` | type | — | [bidi-features](bidi-features.md) |
|
|
50
|
-
| `JavaScriptError` | type | — | [bidi-features](bidi-features.md) |
|
|
51
|
-
| `Key` | const | — | [keyboard-mouse](keyboard-mouse.md) |
|
|
52
|
-
| `Keyboard` | class | — | [keyboard-mouse](keyboard-mouse.md) |
|
|
53
|
-
| `LaunchOptions` | type | — | [browser-api](browser-api.md) |
|
|
54
|
-
| `LoadState` | type | When to consider a navigation complete. - `'load'` — page `load` event has fired (default) - `'domcontentloaded'` — `DOMContentLoaded` has fired (faster, no waiting for images/fonts) - `'networkidle'` — `load` + no in-flight requests for 500 ms - `'none'` — do not wait; return as soon as the navigation is initiated | [browser-api](browser-api.md) |
|
|
55
|
-
| `Locator` | class | — | [selectors](selectors.md) |
|
|
56
|
-
| `LogMessage` | type | — | [bidi-features](bidi-features.md) |
|
|
57
|
-
| `LogMonitor` | class | — | [bidi-features](bidi-features.md) |
|
|
58
|
-
| `MobileEmulation` | type | Mobile emulation configuration | [browser-api](browser-api.md) |
|
|
59
|
-
| `MockResponse` | type | — | [bidi-features](bidi-features.md) |
|
|
60
|
-
| `Mouse` | class | — | [keyboard-mouse](keyboard-mouse.md) |
|
|
61
|
-
| `NetworkInterceptor` | class | — | [bidi-features](bidi-features.md) |
|
|
62
|
-
| `Page` | class | — | [browser-api](browser-api.md) |
|
|
63
|
-
| `RoutePattern` | type | Pattern accepted by {@link BrowserContext.route}. Same shape as the browser-level interceptor. | [browser-context](browser-context.md) |
|
|
64
|
-
| `SessionState` | type | — | [bidi-features](bidi-features.md) |
|
|
65
|
-
| `SessionStateManager` | class | — | [bidi-features](bidi-features.md) |
|
|
66
|
-
| `StorageStateOptions` | type | — | [bidi-features](bidi-features.md) |
|
|
67
|
-
| `TraceEvent` | type | — | [tracing](tracing.md) |
|
|
68
|
-
| `TraceScreenshotMode` | type | Screenshot mode for tracing. | [tracing](tracing.md) |
|
|
69
|
-
| `TraceStartOptions` | type | — | [tracing](tracing.md) |
|
|
70
132
|
|
|
71
133
|
Total exports: **60**.
|
package/docs/browser-api.md
CHANGED
|
@@ -29,10 +29,11 @@ const browser = await Browser.launch({
|
|
|
29
29
|
|--------|------|---------|-------------|
|
|
30
30
|
| `browserName` | `'chrome' \| 'chromium' \| 'firefox'` | `'chrome'` | Browser to launch |
|
|
31
31
|
| `enableBiDi` | `boolean` | `true` | Use WebDriver BiDi. Set `false` only when running against a browser that does not support it — every BiDi-only feature then throws a `requires BiDi` error if called. |
|
|
32
|
-
| `captureLogs` | `boolean` | `false` | Start console/error log capture immediately at launch instead of lazily on first `browser.logs`/`onConsole`/`onError`/`waitForConsole` touch. See [
|
|
32
|
+
| `captureLogs` | `boolean` | `false` | Start console/error log capture immediately at launch instead of lazily on first `browser.logs`/`onConsole`/`onError`/`waitForConsole` touch. See [Console Logs And JavaScript Errors](./browser-logs.md). |
|
|
33
33
|
| `storageState` | `string` | — | Path to a session-state JSON file to load on startup |
|
|
34
34
|
| `mobileEmulation` | `MobileEmulation \| DeviceName` | — | Mobile device emulation settings (Chrome/Chromium only) |
|
|
35
35
|
| `downloadsDir` | `string` | temp dir | Directory where downloaded files are saved |
|
|
36
|
+
| `browserPath` | `string` | — | Custom browser binary to launch (Chrome/Chromium/Firefox) — see [Driver Configuration → Browser Binary Configuration](./driver-configuration.md#browser-binary-configuration) |
|
|
36
37
|
|
|
37
38
|
## Navigation
|
|
38
39
|
|
package/docs/browser-context.md
CHANGED
|
@@ -262,19 +262,16 @@ this context.
|
|
|
262
262
|
the listener reference than the unsubscribe function.
|
|
263
263
|
|
|
264
264
|
```typescript
|
|
265
|
-
|
|
266
|
-
// including popups. No more "why did my test pass with a 500 in a popup".
|
|
267
|
-
const errors: string[] = [];
|
|
265
|
+
const opened: string[] = [];
|
|
268
266
|
ctx.on('page', (page) => {
|
|
269
|
-
page.
|
|
270
|
-
if (msg.type() === 'error') errors.push(`${page.url()}: ${msg.text()}`);
|
|
271
|
-
});
|
|
267
|
+
void page.url().then((url) => opened.push(url));
|
|
272
268
|
});
|
|
273
269
|
|
|
274
270
|
const main = await ctx.newPage({ url: '/checkout' });
|
|
275
271
|
const receipt = await ctx.waitForPage(() => main.find('#print').click());
|
|
276
272
|
await receipt.waitForLoadState('load');
|
|
277
|
-
|
|
273
|
+
|
|
274
|
+
expect(opened.some((url) => url.endsWith('/checkout'))).toBe(true);
|
|
278
275
|
```
|
|
279
276
|
|
|
280
277
|
### `BrowserContext.addInitScript(script): Promise<InitScriptHandle>`
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Console Logs And JavaScript Errors
|
|
2
|
+
|
|
3
|
+
Use `browser.logs` to capture what the page writes to the console and what
|
|
4
|
+
JavaScript errors the browser reports. This is useful for failing tests on
|
|
5
|
+
unexpected client-side errors, debugging flaky flows, or asserting that an app
|
|
6
|
+
emitted a known log message.
|
|
7
|
+
|
|
8
|
+
> **Requires the default browser event connection.** Console and JavaScript
|
|
9
|
+
> error capture requires `enableBiDi: true` (the default) and a browser that
|
|
10
|
+
> supports WebDriver BiDi. If you launch with `enableBiDi: false`, these
|
|
11
|
+
> methods throw a clear `requires BiDi` error.
|
|
12
|
+
|
|
13
|
+
## Capture Timing
|
|
14
|
+
|
|
15
|
+
Capture is lazy by default. CraftDriver subscribes to log events the first time
|
|
16
|
+
you touch `browser.logs.onLog()`, `.onConsole()`, `.onError()`, `.on()`,
|
|
17
|
+
`.waitForConsole()`, or `.waitForError()`.
|
|
18
|
+
|
|
19
|
+
Messages emitted before that first touch are not captured, so this can return an
|
|
20
|
+
empty array:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
await browser.navigateTo('https://example.com');
|
|
24
|
+
const messages = browser.logs.getMessages();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Start capture before the action that logs:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
const warning = browser.logs.waitForConsole((msg) => msg.level === 'warn');
|
|
31
|
+
|
|
32
|
+
await browser.getByRole('button', { name: 'Show warning' }).click();
|
|
33
|
+
expect((await warning).text).toContain('Heads up');
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or start capture immediately at launch:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const browser = await Browser.launch({
|
|
40
|
+
browserName: 'chrome',
|
|
41
|
+
captureLogs: true,
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Read Collected Messages
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
const messages = browser.logs.getMessages();
|
|
49
|
+
|
|
50
|
+
for (const msg of messages) {
|
|
51
|
+
console.log(`[${msg.level}] ${msg.text}`);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Each console message has:
|
|
56
|
+
|
|
57
|
+
| Property | Description |
|
|
58
|
+
| -------- | ----------- |
|
|
59
|
+
| `type` | Always `'console'` |
|
|
60
|
+
| `level` | `'debug'`, `'info'`, `'warn'`, or `'error'` |
|
|
61
|
+
| `text` | Message text |
|
|
62
|
+
| `method` | Console method, such as `'log'`, `'warn'`, or `'error'` |
|
|
63
|
+
| `args` | Arguments passed to `console.*` |
|
|
64
|
+
| `timestamp` | When the message was logged |
|
|
65
|
+
| `stackTrace` | Optional stack frames |
|
|
66
|
+
|
|
67
|
+
Filter by level:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const warnings = browser.logs.getLogsByLevel('warn');
|
|
71
|
+
const errors = browser.logs.getLogsByLevel('error');
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Read JavaScript Errors
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const errors = browser.logs.getErrors();
|
|
78
|
+
|
|
79
|
+
for (const error of errors) {
|
|
80
|
+
console.log(`Error: ${error.text}`);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Each JavaScript error has:
|
|
85
|
+
|
|
86
|
+
| Property | Description |
|
|
87
|
+
| -------- | ----------- |
|
|
88
|
+
| `type` | Always `'javascript'` |
|
|
89
|
+
| `level` | Always `'error'` |
|
|
90
|
+
| `text` | Error message |
|
|
91
|
+
| `timestamp` | When the error occurred |
|
|
92
|
+
| `stackTrace` | Optional stack frames with function, URL, line, and column |
|
|
93
|
+
|
|
94
|
+
## Wait For A Log Or Error
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const consoleMessage = browser.logs.waitForConsole((msg) => {
|
|
98
|
+
return msg.level === 'info' && msg.text.includes('Saved');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await browser.getByRole('button', { name: 'Save' }).click();
|
|
102
|
+
expect((await consoleMessage).text).toContain('Saved');
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const pageError = browser.logs.waitForError((error) => {
|
|
107
|
+
return error.text.includes('Cannot read properties');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await browser.getByRole('button', { name: 'Trigger error' }).click();
|
|
111
|
+
expect((await pageError).text).toContain('Cannot read properties');
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Subscribe In Real Time
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const unsubscribeConsole = browser.logs.onConsole((msg) => {
|
|
118
|
+
if (msg.level === 'error') {
|
|
119
|
+
console.log('Console error:', msg.text);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const unsubscribeErrors = browser.logs.onError((error) => {
|
|
124
|
+
console.log('JavaScript error:', error.text);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Later:
|
|
128
|
+
unsubscribeConsole();
|
|
129
|
+
unsubscribeErrors();
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Fail On Unexpected Errors
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
await browser.navigateTo('https://example.com');
|
|
136
|
+
await browser.getByRole('button', { name: 'Run flow' }).click();
|
|
137
|
+
|
|
138
|
+
browser.logs.assertNoErrors();
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
You can also inspect errors yourself:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const errors = browser.logs.getErrors();
|
|
145
|
+
expect(errors).toHaveLength(0);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Other Helpers
|
|
149
|
+
|
|
150
|
+
| Method | Description |
|
|
151
|
+
| ------ | ----------- |
|
|
152
|
+
| `onLog(handler)` | Subscribe to all log messages |
|
|
153
|
+
| `on(level, handler)` | Subscribe to one level: `debug`, `info`, `warn`, or `error` |
|
|
154
|
+
| `getLogs()` | Return all captured console and JavaScript error messages |
|
|
155
|
+
| `clearLogs()` | Clear all collected console messages and errors |
|
|
156
|
+
| `waitForConsole(predicate, timeout?)` | Wait for a matching console message |
|
|
157
|
+
| `waitForError(predicate?, timeout?)` | Wait for a JavaScript error |
|
|
158
|
+
| `assertNoErrors()` | Throw if any JavaScript errors were captured |
|
package/docs/cli.md
CHANGED
|
@@ -83,21 +83,21 @@ Run `craftdriver --help` for the full list.
|
|
|
83
83
|
|
|
84
84
|
CSS is the default. Switch kind with a `prefix=value` form:
|
|
85
85
|
|
|
86
|
-
| Prefix
|
|
87
|
-
|
|
|
88
|
-
| _none_, `css=`
|
|
89
|
-
| `xpath=`
|
|
90
|
-
| `role=`
|
|
91
|
-
| `text=`
|
|
92
|
-
| `text*=`
|
|
93
|
-
| `label=`
|
|
94
|
-
| `placeholder=`
|
|
95
|
-
| `alt=`
|
|
96
|
-
| `title=`
|
|
97
|
-
| `testid=`
|
|
98
|
-
| `id=`
|
|
99
|
-
| `name=`
|
|
100
|
-
| `ref=`
|
|
86
|
+
| Prefix | Maps to | Example |
|
|
87
|
+
| -------------- | --------------------------------------- | -------------------------------- |
|
|
88
|
+
| _none_, `css=` | `By.css` | `'.product-list li'` |
|
|
89
|
+
| `xpath=` | `By.xpath` | `'xpath=//button[1]'` |
|
|
90
|
+
| `role=` | `By.role` (+ `[name=...]` for the name) | `'role=button[name=Submit]'` |
|
|
91
|
+
| `text=` | `By.text` (exact) | `'text=Sign In'` |
|
|
92
|
+
| `text*=` | `By.partialText` | `'text*=Sign'` |
|
|
93
|
+
| `label=` | `By.labelText` | `'label=Email'` |
|
|
94
|
+
| `placeholder=` | `By.placeholder` | `'placeholder=name@example.com'` |
|
|
95
|
+
| `alt=` | `By.altText` | `'alt=Logo'` |
|
|
96
|
+
| `title=` | `By.title` | `'title=Help'` |
|
|
97
|
+
| `testid=` | `By.testId` | `'testid=login-btn'` |
|
|
98
|
+
| `id=` | `By.id` | `'id=submit'` |
|
|
99
|
+
| `name=` | `By.name` | `'name=email'` |
|
|
100
|
+
| `ref=` | snapshot ref (`craftdriver snapshot`) | `'ref=e5'` |
|
|
101
101
|
|
|
102
102
|
Anything else is treated as a CSS selector, so attribute selectors with
|
|
103
103
|
`=` inside (e.g. `'button[type=submit]'`) work as expected.
|
|
@@ -148,11 +148,11 @@ code: NO_MATCH
|
|
|
148
148
|
|
|
149
149
|
## Exit codes
|
|
150
150
|
|
|
151
|
-
| Code | Meaning
|
|
152
|
-
| ---- |
|
|
153
|
-
| `0` | success (or `exists` matched at least one element)
|
|
154
|
-
| `1` | assertion / timeout / `NO_MATCH` / `exists` matched zero elements
|
|
155
|
-
| `2` | usage error (missing argument, unknown command)
|
|
151
|
+
| Code | Meaning |
|
|
152
|
+
| ---- | ----------------------------------------------------------------- |
|
|
153
|
+
| `0` | success (or `exists` matched at least one element) |
|
|
154
|
+
| `1` | assertion / timeout / `NO_MATCH` / `exists` matched zero elements |
|
|
155
|
+
| `2` | usage error (missing argument, unknown command) |
|
|
156
156
|
|
|
157
157
|
## Fail-fast defaults
|
|
158
158
|
|
|
@@ -221,12 +221,12 @@ For agents that load skills explicitly (Claude Code's Skills system,
|
|
|
221
221
|
Copilot agent customization, custom orchestrators), the npm tarball
|
|
222
222
|
ships a tiered skill pack under `skills/craftdriver/`:
|
|
223
223
|
|
|
224
|
-
| File
|
|
225
|
-
|
|
|
226
|
-
| [`SKILL.md`](
|
|
227
|
-
| [`cheatsheet.md`](
|
|
228
|
-
| [`patterns.md`](
|
|
229
|
-
| [`cli.md`](
|
|
224
|
+
| File | Purpose |
|
|
225
|
+
| ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
226
|
+
| [`SKILL.md`](https://github.com/dtopuzov/craftdriver/blob/main/skills/craftdriver/SKILL.md) | Always-on, ≤ 500 tokens. Selector order, error-code-first, auto-wait. |
|
|
227
|
+
| [`cheatsheet.md`](https://github.com/dtopuzov/craftdriver/blob/main/skills/craftdriver/cheatsheet.md) | Command-by-command reference for writing tests. |
|
|
228
|
+
| [`patterns.md`](https://github.com/dtopuzov/craftdriver/blob/main/skills/craftdriver/patterns.md) | Worked recipes (login, upload, network-wait, a11y, tracing, clock). |
|
|
229
|
+
| [`cli.md`](https://github.com/dtopuzov/craftdriver/blob/main/skills/craftdriver/cli.md) | Agent-facing CLI reference. |
|
|
230
230
|
|
|
231
231
|
Point your agent at `node_modules/craftdriver/skills/craftdriver/SKILL.md`
|
|
232
232
|
or copy it into your project. The other files are referenced from
|