craftdriver 1.4.0 → 1.6.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +17 -3
  2. package/README.md +6 -2
  3. package/dist/cli/daemon.d.ts.map +1 -1
  4. package/dist/cli/daemon.js +4 -0
  5. package/dist/cli/daemon.js.map +1 -1
  6. package/dist/cli/mcp/server.d.ts.map +1 -1
  7. package/dist/cli/mcp/server.js +4 -0
  8. package/dist/cli/mcp/server.js.map +1 -1
  9. package/dist/cli/parseArgs.d.ts +2 -2
  10. package/dist/cli/parseArgs.d.ts.map +1 -1
  11. package/dist/cli/parseArgs.js +1 -1
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/bidi/storage.d.ts +13 -0
  17. package/dist/lib/bidi/storage.d.ts.map +1 -1
  18. package/dist/lib/bidi/storage.js +81 -32
  19. package/dist/lib/bidi/storage.js.map +1 -1
  20. package/dist/lib/browser.d.ts +48 -3
  21. package/dist/lib/browser.d.ts.map +1 -1
  22. package/dist/lib/browser.js +212 -86
  23. package/dist/lib/browser.js.map +1 -1
  24. package/dist/lib/browserContext.d.ts +2 -2
  25. package/dist/lib/browserContext.d.ts.map +1 -1
  26. package/dist/lib/browserContext.js +1 -1
  27. package/dist/lib/builder.d.ts +16 -2
  28. package/dist/lib/builder.d.ts.map +1 -1
  29. package/dist/lib/builder.js +46 -2
  30. package/dist/lib/builder.js.map +1 -1
  31. package/dist/lib/capabilities.d.ts +20 -2
  32. package/dist/lib/capabilities.d.ts.map +1 -1
  33. package/dist/lib/capabilities.js +109 -48
  34. package/dist/lib/capabilities.js.map +1 -1
  35. package/dist/lib/driver.d.ts +33 -2
  36. package/dist/lib/driver.d.ts.map +1 -1
  37. package/dist/lib/driver.js +91 -2
  38. package/dist/lib/driver.js.map +1 -1
  39. package/dist/lib/driverManager.d.ts +28 -0
  40. package/dist/lib/driverManager.d.ts.map +1 -1
  41. package/dist/lib/driverManager.js +60 -0
  42. package/dist/lib/driverManager.js.map +1 -1
  43. package/dist/lib/elementHandle.d.ts.map +1 -1
  44. package/dist/lib/elementHandle.js +34 -0
  45. package/dist/lib/elementHandle.js.map +1 -1
  46. package/dist/lib/http.d.ts.map +1 -1
  47. package/dist/lib/http.js +31 -10
  48. package/dist/lib/http.js.map +1 -1
  49. package/dist/lib/launchTarget.d.ts +22 -3
  50. package/dist/lib/launchTarget.d.ts.map +1 -1
  51. package/dist/lib/launchTarget.js +159 -9
  52. package/dist/lib/launchTarget.js.map +1 -1
  53. package/dist/lib/remote.d.ts +55 -0
  54. package/dist/lib/remote.d.ts.map +1 -0
  55. package/dist/lib/remote.js +127 -0
  56. package/dist/lib/remote.js.map +1 -0
  57. package/dist/lib/safari.d.ts +90 -0
  58. package/dist/lib/safari.d.ts.map +1 -0
  59. package/dist/lib/safari.js +136 -0
  60. package/dist/lib/safari.js.map +1 -0
  61. package/dist/lib/tracing.d.ts +1 -1
  62. package/dist/lib/tracing.d.ts.map +1 -1
  63. package/dist/lib/tracing.js.map +1 -1
  64. package/dist/lib/types.d.ts +63 -0
  65. package/dist/lib/types.d.ts.map +1 -1
  66. package/dist/lib/vibiumTrace.d.ts +1 -1
  67. package/dist/lib/vibiumTrace.d.ts.map +1 -1
  68. package/dist/lib/webelement.d.ts.map +1 -1
  69. package/dist/lib/webelement.js +118 -2
  70. package/dist/lib/webelement.js.map +1 -1
  71. package/docs/api-reference.md +6 -2
  72. package/docs/browser-api.md +5 -4
  73. package/docs/driver-configuration.md +60 -0
  74. package/docs/getting-started.md +30 -10
  75. package/docs/index.md +2 -1
  76. package/docs/keyboard-mouse.md +7 -5
  77. package/docs/public/examples/displayed.html +86 -0
  78. package/docs/recipes/run-on-browserstack.md +265 -0
  79. package/docs/recipes.md +15 -1
  80. package/docs/remote-webdriver.md +308 -0
  81. package/docs/safari.md +118 -0
  82. package/docs/standards.md +18 -0
  83. package/docs/why-craftdriver.md +3 -1
  84. package/docs/zero-config-drivers.md +12 -0
  85. package/package.json +5 -1
  86. package/skills/craftdriver/SKILL.md +4 -1
  87. package/skills/craftdriver/cheatsheet.md +4 -1
package/docs/safari.md ADDED
@@ -0,0 +1,118 @@
1
+ # Safari
2
+
3
+ CraftDriver drives **real desktop Safari on macOS** through W3C WebDriver
4
+ Classic.
5
+
6
+ ## One-time setup
7
+
8
+ Safari's driver (`safaridriver`) ships with macOS — **nothing to install or
9
+ download**. You only have to turn on automation **once per machine**:
10
+
11
+ ```bash
12
+ safaridriver --enable
13
+ ```
14
+
15
+ This is the single prerequisite.
16
+
17
+ CraftDriver never runs `--enable` for you. If automation isn't enabled, a
18
+ launch fails immediately with that exact remedy rather than hanging.
19
+
20
+ ## Quick start
21
+
22
+ ```typescript
23
+ import { Browser } from 'craftdriver';
24
+
25
+ const browser = await Browser.launch({ browserName: 'safari' });
26
+ await browser.navigateTo('http://127.0.0.1:8080/login.html');
27
+ await browser.getByLabel('Username').fill('alice');
28
+ await browser.getByLabel('Password').fill('secret');
29
+ await browser.getByRole('button', { name: 'Sign in' }).click();
30
+ await browser.expect('#welcome').toHaveText('Welcome back, alice!');
31
+ await browser.quit();
32
+ ```
33
+
34
+ Same API as every other browser — locators, actions, assertions, and
35
+ auto-waiting all work unchanged.
36
+
37
+ ## What works
38
+
39
+ Navigation, locators, and element queries · click / fill / clear / keyboard /
40
+ desktop mouse · `evaluate()` (sync & async JS) · frames and iframes · window &
41
+ popup enumeration · **imperative dialogs** (`getAlertText` / `acceptAlert` /
42
+ `dismissAlert` / `sendAlertText`) · viewport and element screenshots · cookies
43
+ and storage (via the standard Classic cookie endpoints) · accessibility checks.
44
+
45
+ ## What isn't supported
46
+
47
+ Safari exposes no WebDriver BiDi endpoint, so everything event- or
48
+ BiDi-driven is unavailable — and each of these throws a clear
49
+ [`UNSUPPORTED`](./error-codes.md) error immediately, never a silent hang:
50
+
51
+ - network mocking / interception and request/response waits
52
+ - console & JavaScript-error capture, tracing
53
+ - BiDi user contexts and emulation (permissions, geolocation,
54
+ locale/timezone, offline, color-scheme)
55
+ - init/preload scripts and the virtual clock
56
+ - event-driven dialogs (`onDialog` / `waitForDialog`) — use the imperative
57
+ methods above
58
+ - full-page screenshots and `openPage()`
59
+ - CraftDriver-managed downloads (`waitForDownload`)
60
+
61
+ Desktop Safari is also **not** iPhone/iPad Safari — there is no mobile or
62
+ touch emulation.
63
+
64
+ ## Limitations to plan around
65
+
66
+ - **macOS-only.** There is no Safari for Linux or Windows, and none is coming.
67
+ Trying to launch Safari off macOS throws `UNSUPPORTED`.
68
+ - **Headed only.** No headless mode — every launch opens a visible automation
69
+ window (with a purple banner). Don't interact with it while a test runs.
70
+ Setting `HEADLESS=true` with Safari is rejected up front.
71
+ - **Serial only.** Only one Safari WebDriver session can be active on a Mac at
72
+ a time. A second concurrent launch is refused with an actionable error
73
+ (never a hang) — run Safari tests serially.
74
+
75
+ ## Safari Technology Preview
76
+
77
+ STP ships its own `safaridriver`; point `SafariService` at it. This is also
78
+ the one way to get a **second concurrent session** on one Mac — stable Safari
79
+ and STP each run one session at the same time.
80
+
81
+ ```typescript
82
+ import { Browser, SafariService } from 'craftdriver';
83
+
84
+ const browser = await Browser.launch({
85
+ browserName: 'safari',
86
+ safariService: new SafariService({
87
+ binaryPath: '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver',
88
+ }),
89
+ });
90
+ ```
91
+
92
+ Enable automation once for STP too: `/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver --enable`.
93
+
94
+ ## Running Safari tests
95
+
96
+ Run Safari **serially** — one session at a time. With Vitest that's
97
+ `--maxWorkers=1`:
98
+
99
+ ```bash
100
+ vitest run --maxWorkers=1
101
+ ```
102
+
103
+ Keep it headed (don't set `HEADLESS`), on macOS with Remote Automation enabled.
104
+ In CI, use a macOS runner; parallelism across Safari needs **separate macOS
105
+ hosts**.
106
+
107
+ ## Troubleshooting
108
+
109
+ | Symptom | Fix |
110
+ | --- | --- |
111
+ | `You must enable 'Allow remote automation'…` | Run `safaridriver --enable` once (see [setup](#one-time-setup)). |
112
+ | Second launch fails while one session is open | Expected — Safari is serial. Serialize your tests, or use STP for a second session. |
113
+ | `Could not find 'safaridriver'` | You're not on macOS, or Safari is missing. For a non-standard install, set `CRAFTDRIVER_SAFARIDRIVER_PATH` or `SafariService({ binaryPath })`. |
114
+
115
+ ## See also
116
+
117
+ - [Driver Configuration → Safari](./driver-configuration.md#safari-macos-driver-ships-with-the-browser) — the no-download driver-resolution chain.
118
+ - [WebDriver Standards](./standards.md#safari-is-classic-only) — why Safari is Classic-only.
package/docs/standards.md CHANGED
@@ -16,6 +16,24 @@ That protocol choice is the center of the project. CraftDriver tries to provide
16
16
 
17
17
  CraftDriver picks the practical protocol path behind a single public API. You call `browser.click()`, `browser.navigateTo()`, `browser.network.mock()`, or `browser.startTrace()`; the library handles the transport details.
18
18
 
19
+ ### Remote sessions use the same two protocols
20
+
21
+ `Browser.launch({ remote })` connects to a W3C-compatible remote endpoint
22
+ (a self-hosted Selenium Grid, BrowserStack, or another cloud provider). The
23
+ same protocols are used, but the endpoint decides which browser features and
24
+ BiDi proxying are available. Remote uploads and downloads also have a
25
+ different lifecycle. See [Remote WebDriver](./remote-webdriver.md).
26
+
27
+ ### Safari is Classic-only
28
+
29
+ Apple does not currently document a supported WebDriver BiDi endpoint for
30
+ Safari or Safari Technology Preview. A local Safari launch therefore rejects
31
+ `enableBiDi: true` and BiDi-only methods fail with `UNSUPPORTED`. Remote
32
+ Safari defaults to Classic too; an explicit remote opt-in is forwarded because
33
+ the remote endpoint owns negotiation, and it is usable only if that endpoint
34
+ returns a working `webSocketUrl`. See the [Safari guide](./safari.md) for the
35
+ local Classic feature set.
36
+
19
37
  ## Why It Matters
20
38
 
21
39
  Standards-based automation gives projects a few useful properties:
@@ -5,7 +5,7 @@ CraftDriver is for writing boringly reliable automation against real browsers, w
5
5
  ## What It Cares About
6
6
 
7
7
  - 🍺 **Focused Node.js API** - browser automation without a giant framework around it.
8
- - 🧭 **Real browsers** - drives installed Chrome, Chromium, and Firefox instead of patched browser engine builds.
8
+ - 🧭 **Real browsers** - drives installed Chrome, Chromium, and Firefox instead of patched browser engine builds, plus real [Safari on macOS](./safari.md).
9
9
  - 🌐 **Standards that age well** - W3C WebDriver standards stay stable while browser-private protocols change.
10
10
  - 🚦 **Readable, auto-waited flows** - role, label, text, test id, CSS, XPath, click, fill, and expect.
11
11
  - 📡 **Network control** - mock, block, intercept, and wait for browser requests and responses.
@@ -13,6 +13,8 @@ CraftDriver is for writing boringly reliable automation against real browsers, w
13
13
  - ⏱️ **Virtual clock** - freeze or fast-forward `Date`, timers, and time-sensitive UI.
14
14
  - ♿ **Accessibility audits** - run axe-core checks on pages, elements, and locators.
15
15
  - 🧾 **Trace evidence** - capture actions, console output, errors, network events, and screenshots.
16
+ - ⚛️ **Electron apps** - drive packaged Electron desktop app renderers, matched to the app's bundled Chromium.
17
+ - ☁️ **Remote WebDriver** - use the Browser API with a self-hosted Selenium Grid or a cloud provider like [BrowserStack](https://www.browserstack.com/).
16
18
  - 🤖 **Agent-friendly** - CLI, MCP, and assistant rules when coding agents need the browser.
17
19
 
18
20
  ## Good Fits
@@ -62,3 +62,15 @@ Manual configuration is useful when:
62
62
  [Driver Configuration → Browser Binary Configuration](./driver-configuration.md#browser-binary-configuration)
63
63
 
64
64
  See [Driver Configuration](./driver-configuration.md) for the full reference.
65
+
66
+ ## Safari: nothing to resolve, nothing to download
67
+
68
+ The auto-download model above doesn't apply to `browserName: 'safari'`.
69
+ `safaridriver` ships as part of macOS/Safari itself — there's no version to
70
+ match, no binary to fetch, and no cache to warm. CraftDriver only ever
71
+ **locates** the driver Apple already installed. The single prerequisite is
72
+ turning automation on once per Mac with `safaridriver --enable`.
73
+
74
+ See the [**Safari guide**](./safari.md) for setup and capabilities, and
75
+ [Driver Configuration → Safari](./driver-configuration.md#safari-macos-driver-ships-with-the-browser)
76
+ for the driver-resolution chain.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "craftdriver",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Modern WebDriver automation library for NodeJS",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -17,8 +17,11 @@
17
17
  "test:firefox": "BROWSER_NAME=firefox HEADLESS=true vitest run --maxWorkers=2",
18
18
  "test:chrome": "BROWSER_NAME=chrome vitest run",
19
19
  "test:chromium": "BROWSER_NAME=chromium vitest run",
20
+ "test:safari": "BROWSER_NAME=safari vitest run tests/safari.test.ts --maxWorkers=1",
20
21
  "test:recipes": "HEADLESS=true vitest run --config vitest.recipes.config.ts",
21
22
  "test:electron": "vitest run --config vitest.electron.config.ts",
23
+ "test:browserstack": "vitest run --config vitest.browserstack.config.ts",
24
+ "test:grid": "vitest run --config vitest.grid.config.ts",
22
25
  "bench": "HEADLESS=true vitest run --config vitest.perf.config.ts",
23
26
  "clean": "rimraf dist",
24
27
  "serve": "http-server ./examples -a 127.0.0.1 -p 8080 -c-1 --cors",
@@ -40,6 +43,7 @@
40
43
  "firefox",
41
44
  "chrome",
42
45
  "chromium",
46
+ "safari",
43
47
  "electron",
44
48
  "electron-testing",
45
49
  "desktop-app-testing",
@@ -36,7 +36,10 @@ break the moment markup shifts.
36
36
  4. BiDi features (`network`, `logs`, tracing, init scripts, true load
37
37
  events) work out of the box — `enableBiDi` defaults to `true`. They only
38
38
  break if you explicitly pass `enableBiDi: false`; the error code on the
39
- wrong transport is `UNSUPPORTED`.
39
+ wrong transport is `UNSUPPORTED`. Exception: `browserName: 'safari'`
40
+ defaults `enableBiDi` to `false` and rejects `true` — Safari is
41
+ Classic-only (macOS, headed, one session at a time). See
42
+ [docs/safari.md](../../docs/safari.md).
40
43
  5. Tests fetch from the example server. Start it in a separate
41
44
  terminal: `npm run examples:start` before `npm test`.
42
45
 
@@ -10,11 +10,14 @@ list.
10
10
  import { Browser } from 'craftdriver';
11
11
 
12
12
  const browser = await Browser.launch({
13
- browserName: 'chrome', // 'chrome' | 'chromium' | 'firefox'
13
+ browserName: 'chrome', // 'chrome' | 'chromium' | 'firefox' | 'safari'
14
14
  headless: true,
15
15
  // enableBiDi defaults to true — network / logs / tracing / init scripts
16
16
  // all need it, so only set enableBiDi: false if you must disable it.
17
17
  });
18
+ // 'safari' is macOS-only, headed only (no `headless`),
19
+ // one session at a time, WebDriver Classic only (enableBiDi is rejected).
20
+ // See docs/safari.md.
18
21
  try {
19
22
  await browser.navigateTo('https://example.com');
20
23
  // ...