@testdriverai/agent 7.11.229-canary → 7.11.232-test

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 (100) hide show
  1. package/docs/_data/examples-manifest.json +16 -16
  2. package/docs/_scripts/generate-examples.js +38 -45
  3. package/docs/agent.mdx +174 -93
  4. package/docs/assert.mdx +73 -269
  5. package/docs/aws-setup.mdx +196 -314
  6. package/docs/bring-your-own-machine.mdx +139 -206
  7. package/docs/cache.mdx +144 -151
  8. package/docs/caching.mdx +99 -89
  9. package/docs/captcha.mdx +126 -111
  10. package/docs/ci-cd.mdx +154 -543
  11. package/docs/click.mdx +74 -229
  12. package/docs/client.mdx +177 -231
  13. package/docs/copilot/auto-healing.mdx +86 -370
  14. package/docs/copilot/running-tests.mdx +121 -930
  15. package/docs/customizing-devices.mdx +74 -251
  16. package/docs/dashcam.mdx +72 -405
  17. package/docs/debugging-with-screenshots.mdx +105 -371
  18. package/docs/docs.json +79 -22
  19. package/docs/double-click.mdx +48 -68
  20. package/docs/errors.mdx +102 -176
  21. package/docs/events.mdx +170 -327
  22. package/docs/examples/{hover-text-with-description.mdx → add-to-cart.mdx} +30 -35
  23. package/docs/examples/assert.mdx +28 -41
  24. package/docs/examples/click-button.mdx +71 -0
  25. package/docs/examples/{hover-image.mdx → click-icon.mdx} +32 -28
  26. package/docs/examples/element-not-found.mdx +27 -26
  27. package/docs/examples/findall-coffee-icons.mdx +28 -32
  28. package/docs/examples/installer.mdx +61 -25
  29. package/docs/examples/launch-vscode-linux.mdx +28 -51
  30. package/docs/examples/navigate-and-scroll.mdx +82 -0
  31. package/docs/examples/parse.mdx +24 -28
  32. package/docs/examples/press-keys.mdx +28 -25
  33. package/docs/examples/scroll.mdx +25 -27
  34. package/docs/examples/type.mdx +26 -21
  35. package/docs/exec.mdx +92 -256
  36. package/docs/extract.mdx +69 -170
  37. package/docs/find.mdx +140 -736
  38. package/docs/focus-application.mdx +69 -246
  39. package/docs/generating-tests.mdx +103 -137
  40. package/docs/guide/best-practices-polling.mdx +65 -141
  41. package/docs/hosted.mdx +80 -144
  42. package/docs/hover.mdx +62 -235
  43. package/docs/locating-elements.mdx +74 -369
  44. package/docs/making-assertions.mdx +116 -74
  45. package/docs/mcp-setup.mdx +80 -63
  46. package/docs/mouse-down.mdx +48 -125
  47. package/docs/mouse-up.mdx +47 -129
  48. package/docs/options.mdx +75 -48
  49. package/docs/parse.mdx +95 -184
  50. package/docs/performing-actions.mdx +104 -94
  51. package/docs/press-keys.mdx +59 -299
  52. package/docs/provision.mdx +137 -182
  53. package/docs/quickstart-claude.mdx +85 -0
  54. package/docs/quickstart-github.mdx +62 -32
  55. package/docs/quickstart-manual.mdx +60 -33
  56. package/docs/quickstart-vscode.mdx +97 -0
  57. package/docs/quickstart.mdx +26 -9
  58. package/docs/redraw.mdx +101 -165
  59. package/docs/reusable-code.mdx +97 -200
  60. package/docs/right-click.mdx +47 -89
  61. package/docs/screenshot.mdx +47 -201
  62. package/docs/screenshots.mdx +87 -137
  63. package/docs/scroll.mdx +71 -154
  64. package/docs/secrets.mdx +96 -91
  65. package/docs/self-hosted.mdx +83 -142
  66. package/docs/snippets/enterprise.mdx +15 -0
  67. package/docs/styles.css +68 -0
  68. package/docs/test-results-json.mdx +167 -204
  69. package/docs/type.mdx +56 -304
  70. package/docs/variables.mdx +121 -81
  71. package/docs/wait.mdx +33 -31
  72. package/docs/what-is-testdriver.mdx +80 -32
  73. package/examples/{hover-text-with-description.test.mjs → add-to-cart.test.mjs} +4 -5
  74. package/examples/assert.test.mjs +3 -20
  75. package/examples/{hover-text.test.mjs → click-button.test.mjs} +3 -4
  76. package/examples/{hover-image.test.mjs → click-icon.test.mjs} +5 -6
  77. package/examples/element-not-found.test.mjs +3 -5
  78. package/examples/findall-coffee-icons.test.mjs +3 -3
  79. package/examples/installer.test.mjs +1 -1
  80. package/examples/launch-vscode-linux.test.mjs +6 -33
  81. package/examples/{scroll-keyboard.test.mjs → navigate-and-scroll.test.mjs} +4 -5
  82. package/examples/parse.test.mjs +1 -2
  83. package/examples/press-keys.test.mjs +4 -4
  84. package/examples/scroll.test.mjs +3 -6
  85. package/examples/type.test.mjs +5 -2
  86. package/lib/provision.js +6 -2
  87. package/package.json +1 -1
  88. package/sdk.d.ts +4 -2
  89. package/sdk.js +1 -1
  90. package/docs/claude-mcp-plugin.mdx +0 -244
  91. package/docs/elements.mdx +0 -606
  92. package/docs/examples/ai.mdx +0 -78
  93. package/docs/examples/captcha-api.mdx +0 -92
  94. package/docs/examples/chrome-extension.mdx +0 -156
  95. package/docs/examples/drag-and-drop.mdx +0 -100
  96. package/docs/examples/formatted-logging.mdx +0 -74
  97. package/docs/examples/hover-text.mdx +0 -70
  98. package/docs/examples/match-image.mdx +0 -97
  99. package/docs/examples/scroll-keyboard.mdx +0 -80
  100. package/docs/examples/scroll-until-text.mdx +0 -109
@@ -1,314 +1,269 @@
1
1
  ---
2
- title: "Spawning a sandbox"
3
- sidebarTitle: "Spawning a sandbox"
4
- description: "Launch browsers, desktop apps, and extensions in your sandbox"
2
+ title: "Launch apps in the sandbox"
3
+ sidebarTitle: "Launching apps"
4
+ description: "Start Chrome, a Chrome extension, VS Code, an Electron app, or an installer in the sandbox."
5
5
  icon: "rocket"
6
6
  mode: "wide"
7
7
  ---
8
8
 
9
- ## Overview
10
-
11
- The Provision API sets up applications in your sandbox before the tests run. It downloads, installs, and starts browsers, desktop apps, VS Code, Chrome extensions, and more.
12
-
13
- Use the provision methods through `testdriver.provision.*`:
9
+ Start the app you want to test with a `provision` method. Call one at the beginning of each test.
14
10
 
15
11
  ```javascript
16
- await testdriver.provision.chrome({ url: 'https://example.com' });
12
+ await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
17
13
  ```
18
14
 
19
- ## Methods
15
+ Every provision method:
20
16
 
21
- ### chrome()
17
+ - Launches or installs the app in the sandbox. The Chrome methods also wait until Chrome is ready.
18
+ - Starts the [Dashcam](/dashcam) recording, unless you turned it off with `dashcam: false`.
19
+ - Does nothing when the client was created with `reconnect: true`, because the app is already running.
22
20
 
23
- Start Google Chrome with an optional URL.
21
+ | Method | Use it to test |
22
+ | --- | --- |
23
+ | [`chrome()`](#chrome-options) | A website |
24
+ | [`chromeExtension()`](#chromeextension-options) | A Chrome extension |
25
+ | [`vscode()`](#vscode-options) | VS Code or a VS Code extension |
26
+ | [`installer()`](#installer-options) | A desktop app you download and install |
27
+ | [`electron()`](#electron-options) | An Electron app |
28
+ | [`dashcam()`](#dashcam-options) | Custom recording settings |
24
29
 
25
- ```javascript
26
- await testdriver.provision.chrome(options?)
30
+ ## chrome(options)
31
+
32
+ Opens Chrome at a URL.
33
+
34
+ ```typescript
35
+ testdriver.provision.chrome(options?: ProvisionChromeOptions): Promise<void>
27
36
  ```
28
37
 
29
38
  <ParamField path="options" type="ProvisionChromeOptions">
30
39
  <Expandable title="properties">
31
40
  <ParamField path="url" type="string" default="http://testdriver-sandbox.vercel.app/">
32
- The URL to go to after Chrome starts.
41
+ The page to open.
33
42
  </ParamField>
34
-
35
- <ParamField path="maximized" type="boolean" default={true}>
36
- Start Chrome with the window at the maximum size.
43
+ <ParamField path="maximized" type="boolean" default="true">
44
+ Start with the window maximized.
37
45
  </ParamField>
38
-
39
- <ParamField path="guest" type="boolean" default={false}>
40
- Start Chrome in the guest profile mode.
46
+ <ParamField path="guest" type="boolean" default="false">
47
+ Use Chrome's guest profile, with no saved data.
41
48
  </ParamField>
42
49
  </Expandable>
43
50
  </ParamField>
44
51
 
52
+ Chrome also records the site's network traffic in the Dashcam replay.
53
+
45
54
  ```javascript
46
- // Basic
47
- await testdriver.provision.chrome({ url: 'https://example.com' });
48
-
49
- // With guest mode
50
- await testdriver.provision.chrome({
51
- url: 'https://example.com',
52
- guest: true,
53
- maximized: true,
54
- });
55
+ await testdriver.provision.chrome({ url: 'https://example.com', guest: true });
55
56
  ```
56
57
 
57
- ### chromeExtension()
58
+ ## chromeExtension(options)
58
59
 
59
- Install and start a Chrome extension. You can install it from a local unpacked directory. Or you can install it from the Chrome Web Store by the extension ID.
60
+ Opens Chrome with an extension loaded.
60
61
 
61
- ```javascript
62
- await testdriver.provision.chromeExtension(options)
62
+ ```typescript
63
+ testdriver.provision.chromeExtension(options: ProvisionChromeExtensionOptions): Promise<void>
63
64
  ```
64
65
 
65
66
  <ParamField path="options" type="ProvisionChromeExtensionOptions" required>
66
- One of `extensionPath` or `extensionId` is required.
67
+ Pass either `extensionId` or `extensionPath`. It throws if you pass neither.
67
68
 
68
69
  <Expandable title="properties">
69
- <ParamField path="extensionPath" type="string">
70
- Local path to an unpacked extension directory. The extension files are uploaded to the sandbox.
71
- </ParamField>
72
-
73
70
  <ParamField path="extensionId" type="string">
74
- Chrome Web Store extension ID to install.
71
+ A Chrome Web Store extension ID. TestDriver downloads the extension into the sandbox.
75
72
  </ParamField>
76
-
77
- <ParamField path="maximized" type="boolean" default={true}>
78
- Launch Chrome in maximized window mode.
73
+ <ParamField path="extensionPath" type="string">
74
+ The path to an unpacked extension **inside the sandbox**. Nothing is copied from your machine, so get the files there first, for example with [`exec()`](/exec).
75
+ </ParamField>
76
+ <ParamField path="maximized" type="boolean" default="true">
77
+ Start with the window maximized.
79
78
  </ParamField>
80
79
  </Expandable>
81
80
  </ParamField>
82
81
 
82
+ From the Chrome Web Store:
83
+
83
84
  ```javascript
84
- // From local directory
85
85
  await testdriver.provision.chromeExtension({
86
- extensionPath: './my-extension',
86
+ extensionId: 'cjpalhdlnbpafiamejdnhcphjbkeiagm', // uBlock Origin
87
87
  });
88
+ ```
88
89
 
89
- // From Chrome Web Store
90
- await testdriver.provision.chromeExtension({
91
- extensionId: 'abcdefghijklmnop',
90
+ From source:
91
+
92
+ ```javascript
93
+ await testdriver.exec({
94
+ language: 'sh',
95
+ code: 'git clone https://github.com/your-org/your-extension.git /tmp/your-extension',
92
96
  });
97
+ await testdriver.provision.chromeExtension({ extensionPath: '/tmp/your-extension' });
93
98
  ```
94
99
 
95
- ### vscode()
100
+ ## vscode(options)
96
101
 
97
- Launch Visual Studio Code with an optional workspace and extensions.
102
+ Opens VS Code, optionally with a folder and extensions.
98
103
 
99
- ```javascript
100
- await testdriver.provision.vscode(options?)
104
+ ```typescript
105
+ testdriver.provision.vscode(options?: ProvisionVSCodeOptions): Promise<void>
101
106
  ```
102
107
 
103
108
  <ParamField path="options" type="ProvisionVSCodeOptions">
104
109
  <Expandable title="properties">
105
110
  <ParamField path="workspace" type="string">
106
- Path to a workspace folder or `.code-workspace` file to open.
111
+ A folder or `.code-workspace` file in the sandbox to open.
107
112
  </ParamField>
108
-
109
- <ParamField path="extensions" type="string[]" default={[]}>
110
- Array of VS Code extension IDs to install before launching.
113
+ <ParamField path="extensions" type="string[]" default="[]">
114
+ Marketplace extension IDs to install before VS Code opens.
111
115
  </ParamField>
112
116
  </Expandable>
113
117
  </ParamField>
114
118
 
115
119
  ```javascript
116
120
  await testdriver.provision.vscode({
117
- workspace: '/home/testdriver/project',
118
- extensions: ['ms-python.python', 'esbenp.prettier-vscode'],
121
+ workspace: '/tmp/my-project',
122
+ extensions: ['esbenp.prettier-vscode'],
119
123
  });
120
124
  ```
121
125
 
122
- ### installer()
126
+ ## installer(options)
123
127
 
124
- Download and run an application installer. Supports `.msi`, `.exe`, `.deb`, `.rpm`, `.appimage`, `.sh`, `.dmg`, and `.pkg` formats.
128
+ Downloads a file into the sandbox, installs it, and returns the downloaded file's path.
125
129
 
126
- ```javascript
127
- await testdriver.provision.installer(options)
130
+ ```typescript
131
+ testdriver.provision.installer(options: ProvisionInstallerOptions): Promise<string>
128
132
  ```
129
133
 
130
134
  <ParamField path="options" type="ProvisionInstallerOptions" required>
131
135
  <Expandable title="properties">
132
136
  <ParamField path="url" type="string" required>
133
- Download URL for the installer.
137
+ Where to download the file from.
134
138
  </ParamField>
135
-
136
139
  <ParamField path="filename" type="string">
137
- Override the auto-detected filename from the URL.
140
+ The name to save the file as. By default, it comes from the download.
138
141
  </ParamField>
139
-
140
142
  <ParamField path="appName" type="string">
141
- Application name to focus after installation completes.
143
+ The app to bring to the front after installing.
142
144
  </ParamField>
143
-
144
- <ParamField path="launch" type="boolean" default={true}>
145
- Whether to launch the app after installation. For a `.deb` on Linux, the app is started from its `.desktop` entry (or, when `appName` is set and there is no `.desktop` entry, from its `/usr/bin` binary) and then `appName` is focused. On Windows and macOS, `appName` is focused.
145
+ <ParamField path="launch" type="boolean" default="true">
146
+ Start the app after installing it.
147
+
148
+ - **`.deb` on Linux:** starts the app from its `.desktop` entry. If there isn't one and you set `appName`, it starts the package's first `/usr/bin` program.
149
+ - **`.sh` scripts:** runs the script.
150
+ - **Everywhere:** focuses `appName`, if you set it.
151
+
152
+ With `false`, packages are still installed, and a script is only made executable.
146
153
  </ParamField>
147
154
  </Expandable>
148
155
  </ParamField>
149
156
 
150
- **Behavior:**
151
- - Downloads the installer from the URL
152
- - Auto-detects the install method based on file extension
153
- - Runs the appropriate install command (e.g., `msiexec` for `.msi`, `dpkg` for `.deb`)
154
- - For `.deb` packages, installs any missing dependencies with `apt-get install -f` and fails if the package isn't fully installed
155
- - For `.deb` packages on Linux with `launch: true`, starts the app in the background
156
- - Focuses `appName` when it's set and `launch` is `true`
157
+ TestDriver picks the install method from the file extension:
158
+
159
+ | OS | Extension | What happens |
160
+ | --- | --- | --- |
161
+ | Windows | `.msi` | Installed quietly with `msiexec` |
162
+ | Windows | `.exe` | Run with `/S` for a silent install |
163
+ | Linux | `.deb` | Installed with `dpkg`. Missing dependencies are installed with `apt-get`, and the step fails if the package still isn't fully installed |
164
+ | Linux | `.rpm` | Installed with `rpm` |
165
+ | Linux | `.AppImage` | Made executable |
166
+ | Linux | `.sh` | Made executable and run (only made executable with `launch: false`) |
167
+ | macOS | `.dmg`, `.pkg` | Copied to Applications, or installed with `installer` |
168
+
169
+ Other file types are downloaded but not installed.
157
170
 
158
171
  ```javascript
159
- // Windows MSI installer
172
+ // Install bat, then check that it runs (bat has no window, so nothing is launched)
160
173
  await testdriver.provision.installer({
161
- url: 'https://example.com/app-setup.msi',
162
- appName: 'MyApp',
174
+ url: 'https://github.com/sharkdp/bat/releases/download/v0.24.0/bat_0.24.0_amd64.deb',
163
175
  });
176
+ const output = await testdriver.exec({ language: 'sh', code: 'bat --version' });
177
+ console.log(output); // for example "bat 0.24.0"
178
+ ```
179
+
180
+ Install a desktop app and start it:
164
181
 
165
- // Linux DEB package: installs dependencies, starts the app, focuses it
182
+ ```javascript
183
+ // Installs Yaak and its dependencies, starts it, and brings its window to the front
166
184
  await testdriver.provision.installer({
167
- url: 'https://example.com/app.deb',
168
- appName: 'MyApp',
185
+ url: 'https://github.com/mountain-loop/yaak/releases/download/v2026.9.0/yaak_2026.9.0_amd64.deb',
186
+ appName: 'Yaak',
169
187
  });
170
188
  ```
171
189
 
172
- ### electron()
190
+ ## electron(options)
173
191
 
174
- Launch an Electron application.
192
+ Opens an Electron app that's already in the sandbox.
175
193
 
176
- ```javascript
177
- await testdriver.provision.electron(options)
194
+ ```typescript
195
+ testdriver.provision.electron(options: ProvisionElectronOptions): Promise<void>
178
196
  ```
179
197
 
180
198
  <ParamField path="options" type="ProvisionElectronOptions" required>
181
199
  <Expandable title="properties">
182
200
  <ParamField path="appPath" type="string" required>
183
- Path to the Electron application directory or executable.
201
+ The path to the app in the sandbox. It throws if this is missing.
184
202
  </ParamField>
185
-
186
- <ParamField path="args" type="string[]" default={[]}>
187
- Additional command-line arguments to pass to the Electron app.
203
+ <ParamField path="args" type="string[]" default="[]">
204
+ Extra command-line arguments for the app.
188
205
  </ParamField>
189
206
  </Expandable>
190
207
  </ParamField>
191
208
 
192
209
  ```javascript
193
- await testdriver.provision.electron({
194
- appPath: '/home/testdriver/my-electron-app',
195
- args: ['--no-sandbox'],
196
- });
210
+ await testdriver.provision.electron({ appPath: '/tmp/my-electron-app', args: ['--no-sandbox'] });
197
211
  ```
198
212
 
199
- ### dashcam()
213
+ ## dashcam(options)
200
214
 
201
- Start Dashcam recording with custom options. Usually called automatically by other provision methods, but can be called directly for custom configurations.
215
+ Starts the Dashcam recording with your own settings. The other provision methods start it for you, so call this only to change the log file, the log name, or the recording's title.
202
216
 
203
- ```javascript
204
- await testdriver.provision.dashcam(options?)
217
+ ```typescript
218
+ testdriver.provision.dashcam(options?: ProvisionDashcamOptions): Promise<void>
205
219
  ```
206
220
 
207
221
  <ParamField path="options" type="ProvisionDashcamOptions">
208
222
  <Expandable title="properties">
209
223
  <ParamField path="logPath" type="string">
210
- Path to the TestDriver log file. Defaults to `/tmp/testdriver.log` (Linux) or `C:\Users\testdriver\testdriver.log` (Windows).
224
+ A log file in the sandbox to include in the replay. Defaults to `/tmp/testdriver.log` on Linux, or `C:\Users\testdriver\testdriver.log` on Windows.
211
225
  </ParamField>
212
-
213
226
  <ParamField path="logName" type="string" default="TestDriver Log">
214
- Display name for the log file in the Dashcam replay.
227
+ The log's name in the replay.
215
228
  </ParamField>
216
-
217
- <ParamField path="webLogs" type="boolean" default={true}>
218
- Enable web traffic log capture.
229
+ <ParamField path="webLogs" type="boolean" default="true">
230
+ Record network traffic. It covers the site opened with `chrome()`, or all traffic otherwise.
219
231
  </ParamField>
220
-
221
232
  <ParamField path="title" type="string">
222
- Recording title for the Dashcam session.
233
+ A title for the recording.
223
234
  </ParamField>
224
235
  </Expandable>
225
236
  </ParamField>
226
237
 
227
238
  ```javascript
228
- await testdriver.provision.dashcam({
229
- title: 'Login Flow Test',
230
- logPath: '/tmp/my-app.log',
231
- logName: 'Application Log',
232
- webLogs: true,
233
- });
239
+ await testdriver.provision.dashcam({ title: 'Checkout flow', logPath: '/tmp/my-app.log', logName: 'App log' });
234
240
  ```
235
241
 
236
- ## Types
242
+ ## Complete example
237
243
 
238
- ```typescript
239
- interface ProvisionChromeOptions {
240
- url?: string; // Default: "http://testdriver-sandbox.vercel.app/"
241
- maximized?: boolean; // Default: true
242
- guest?: boolean; // Default: false
243
- }
244
-
245
- interface ProvisionChromeExtensionOptions {
246
- extensionPath?: string; // Local unpacked extension path
247
- extensionId?: string; // Chrome Web Store ID
248
- maximized?: boolean; // Default: true
249
- }
250
-
251
- interface ProvisionVSCodeOptions {
252
- workspace?: string; // Workspace path
253
- extensions?: string[]; // Extension IDs to install
254
- }
255
-
256
- interface ProvisionInstallerOptions {
257
- url: string; // Download URL (required)
258
- filename?: string; // Override filename
259
- appName?: string; // App name to focus
260
- launch?: boolean; // Default: true
261
- }
262
-
263
- interface ProvisionElectronOptions {
264
- appPath: string; // Path to Electron app (required)
265
- args?: string[]; // Additional args
266
- }
267
-
268
- interface ProvisionDashcamOptions {
269
- logPath?: string; // Log file path
270
- logName?: string; // Default: "TestDriver Log"
271
- webLogs?: boolean; // Default: true
272
- title?: string; // Recording title
273
- }
274
- ```
275
-
276
- ## Complete Example
244
+ ```javascript tests/extension.test.mjs
245
+ import { describe, expect, it } from 'vitest';
246
+ import { TestDriver } from 'testdriverai/vitest/hooks';
277
247
 
278
- ```javascript
279
- import { describe, it, beforeAll, afterAll } from 'vitest';
280
- import TestDriver from 'testdriverai';
281
-
282
- describe('Chrome Extension Test', () => {
283
- let testdriver;
248
+ describe('Loom extension', () => {
249
+ it('appears in the extensions menu', async (context) => {
250
+ const testdriver = TestDriver(context);
284
251
 
285
- beforeAll(async () => {
286
- testdriver = new TestDriver({
287
- os: 'linux',
288
- resolution: '1920x1080',
289
- });
290
-
291
- await testdriver.ready();
292
-
293
- // Install extension and open Chrome
294
252
  await testdriver.provision.chromeExtension({
295
- extensionPath: './my-extension',
253
+ extensionId: 'liecbddmkiiihnedobmlmillhodjkdmb',
296
254
  });
297
-
298
- // Start Dashcam with custom logs
299
- await testdriver.provision.dashcam({
300
- title: 'Extension Test',
301
- webLogs: true,
302
- });
303
- });
304
255
 
305
- afterAll(async () => {
306
- await testdriver.disconnect();
307
- });
256
+ await testdriver.find('puzzle-piece extensions icon in the Chrome toolbar').click();
308
257
 
309
- it('tests the extension popup', async () => {
310
- await testdriver.find('extension icon').click();
311
- await testdriver.find('popup content').click();
258
+ const loom = await testdriver.find('Loom in the extensions dropdown');
259
+ expect(loom.found()).toBe(true);
312
260
  });
313
261
  });
314
262
  ```
263
+
264
+ ## Related
265
+
266
+ - [Client & connection](/client): create and connect the client
267
+ - [exec()](/exec): run commands in the sandbox, for example to fetch files before provisioning
268
+ - [Dashcam](/dashcam): how runs are recorded
269
+ - [Examples](/examples/installer): complete tests that install and launch apps
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: "Add TestDriver to Claude Code"
3
+ sidebarTitle: "Claude Code"
4
+ description: "Install one plugin to get the TestDriver MCP server, agent, and skills in Claude Code."
5
+ icon: "terminal"
6
+ ---
7
+
8
+ Install the TestDriver plugin, and Claude Code can write, run, and debug end-to-end tests in a live sandbox.
9
+
10
+ The plugin bundles three things:
11
+
12
+ - The TestDriver MCP server
13
+ - The `testdriver` agent, which builds tests step by step
14
+ - Skills that teach Claude the TestDriver SDK
15
+
16
+ ## Before you begin
17
+
18
+ - **[Claude Code](https://code.claude.com)** and **Node.js 20.19 or later**, which runs the MCP server.
19
+ - **A TestDriver API key.** Create one at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys).
20
+ - **A project with the TestDriver SDK installed**, so the agent can run the tests it writes. If you don't have one yet, see [Set up a project](/quickstart-manual).
21
+
22
+ <Steps>
23
+ <Step title="Set your API key">
24
+
25
+ The plugin's MCP server reads your key from the `TD_API_KEY` environment variable. Add it to your shell profile (such as `~/.zshrc`) so every Claude Code session can use it:
26
+
27
+ ```bash
28
+ export TD_API_KEY="your_api_key"
29
+ ```
30
+
31
+ Open a new terminal, or run `source ~/.zshrc`, before you start Claude Code.
32
+
33
+ </Step>
34
+ <Step title="Install the plugin">
35
+
36
+ TestDriver is a community plugin. In Claude Code, run `/plugin`, open the **Discover** tab, search for **TestDriver**, and install it.
37
+
38
+ You can also install it from TestDriver's own marketplace:
39
+
40
+ ```text
41
+ /plugin marketplace add testdriverai/testdriverai
42
+ /plugin install testdriver@testdriver
43
+ ```
44
+
45
+ </Step>
46
+ <Step title="Check the connection">
47
+
48
+ Run `/mcp` in Claude Code. The `testdriver` server should be listed as connected.
49
+
50
+ If it isn't, check that `TD_API_KEY` is set in the terminal you started Claude Code from.
51
+
52
+ </Step>
53
+ <Step title="Write your first test">
54
+
55
+ Ask for the TestDriver agent by name:
56
+
57
+ ```text
58
+ Use the testdriver agent to write a test that logs in to https://testdriver-sandbox.vercel.app/login and adds an item to the cart.
59
+ ```
60
+
61
+ The agent starts a sandbox and performs each step. It writes the code into a test file under `tests/`, then runs it with Vitest until it passes.
62
+
63
+ </Step>
64
+ </Steps>
65
+
66
+ <Tip>
67
+ Only need TestDriver's tools in chat, without the agent or skills? Add the hosted server instead. It signs in through your browser and needs no API key. See [MCP Setup](/mcp-setup).
68
+ </Tip>
69
+
70
+ ## Next steps
71
+
72
+ <CardGroup cols={2}>
73
+ <Card title="Generate tests with AI" icon="compass" href="/generating-tests">
74
+ Prompt the agent and steer it while it works.
75
+ </Card>
76
+ <Card title="Make assertions" icon="circle-check" href="/making-assertions">
77
+ Check what's on screen in plain language.
78
+ </Card>
79
+ <Card title="Run tests" icon="play" href="/copilot/running-tests">
80
+ Run your tests locally and choose a device.
81
+ </Card>
82
+ <Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
83
+ Run your tests on every pull request.
84
+ </Card>
85
+ </CardGroup>
@@ -1,54 +1,84 @@
1
1
  ---
2
2
  title: "Add TestDriver to GitHub"
3
3
  sidebarTitle: "Add to GitHub"
4
- description: "Drop-in UI tests for any GitHub repository."
4
+ description: "Get an AI code review on every pull request, backed by a real run of your app."
5
5
  icon: "github"
6
6
  ---
7
7
 
8
- Drop-in UI tests for any GitHub repository. Mention `@testdriverai` in a pull request or issue and it writes, runs, and commits UI tests, then catches regressions before they merge. No local install required.
8
+ Install the TestDriver GitHub app, and the TestDriver agent reviews every pull request in your repository.
9
9
 
10
- <Card
11
- title="Add to GitHub"
12
- icon="github"
13
- href="https://go.testdriver.ai/github"
14
- arrow
15
- horizontal
16
- >
17
- Install the TestDriver GitHub App and start testing in minutes.
18
- </Card>
10
+ - It reads the diff for bugs.
11
+ - When a user would see the change, it runs your app in a real sandbox to prove what it finds.
12
+ - It writes and maintains end-to-end tests whenever you ask.
13
+
14
+ There's nothing to install locally.
15
+
16
+ ## Before you begin
17
+
18
+ - **A GitHub repository** where you can install apps (you own it, or you're an admin of its organization).
19
+ - **A TestDriver account.** You create one or sign in during installation.
20
+ - **A paid plan or trial for automatic reviews.** On the free plan, the agent still reviews a pull request when you @mention it. See [pricing](https://testdriver.ai/pricing).
19
21
 
20
22
  <Steps>
21
- <Step title="Install the GitHub App">
22
- Click **Add to GitHub** above and choose the repositories you want to test. You can add more repositories later from your GitHub organization settings.
23
+ <Step title="Install the GitHub app">
24
+
25
+ Open [TestDriver on GitHub](https://go.testdriver.ai/github). Install the app on the repositories you want reviewed, and sign in to TestDriver when prompted.
26
+
27
+ You can add more repositories later from your GitHub settings.
28
+
29
+ </Step>
30
+ <Step title="Get your first tests">
31
+
32
+ Choose a repository to set up. TestDriver opens a **Set up TestDriver** issue in it.
33
+
34
+ The agent picks up the issue, writes a few sample tests for your app, and runs them. It opens a pull request with the tests and their recordings. Review it and merge it like any other pull request.
35
+
23
36
  </Step>
37
+ <Step title="Open a pull request">
24
38
 
25
- <Step title="Mention @testdriverai">
26
- Open a pull request or an issue and describe the test you want in a comment:
39
+ From now on, every pull request you open gets a review without anyone asking. The agent reads the change and runs it when there's something to drive.
40
+
41
+ It posts a single review comment with:
42
+
43
+ - A summary
44
+ - A walkthrough of the changed files
45
+ - Any bugs it found, each labelled `observed` (seen during a run) or `suspected` (inferred from the code)
46
+
47
+ Pushing new commits triggers a fresh review.
48
+
49
+ The review is a comment, so it never approves or blocks a merge. To fail a pull request when a test breaks, [run your tests in CI](/ci-cd).
50
+
51
+ </Step>
52
+ <Step title="Ask for more with @testdriverai">
53
+
54
+ Mention the agent on any issue or pull request to ask a follow-up question or request a new test:
27
55
 
28
56
  ```text
29
- @testdriverai Write a test that verifies the homepage loads and the signup button works.
57
+ @testdriverai Write a test that logs in, adds the first product to the cart, and confirms the cart badge shows 1.
30
58
  ```
31
59
 
32
- TestDriver replies in the thread, starts a sandbox, writes the test, runs it, and posts the result with a link to the recording. It then opens a pull request that adds the test file to your repository.
60
+ The agent replies in the thread and posts screenshots as it works. When it's done, it opens a pull request with the test.
33
61
 
34
62
  <Tip>
35
- Describe what a user does and what they should see, not implementation details. "Log in, add the first product to the cart, and confirm the cart badge shows 1" gives better results than "click `#add-btn`".
63
+ Describe what a user does and what they should see, not how the page is built. "Confirm the cart badge shows 1" works better than "check `#cart-count`".
36
64
  </Tip>
37
- </Step>
38
65
 
39
- <Step title="Catch regressions automatically">
40
- Once tests are committed, TestDriver runs them on every pull request that changes something a user would see and posts a review with what it observed, including a recording. Mention `@testdriverai` on any PR to ask follow-up questions or request more tests.
41
66
  </Step>
42
67
  </Steps>
43
68
 
44
- Want to use TestDriver from GitHub Copilot or the GitHub Mobile app? Read the full GitHub guide:
45
-
46
- <Card
47
- title="GitHub Integration Guide"
48
- icon="arrow-right"
49
- href="/copilot/auto-healing#use-testdriver-in-github"
50
- arrow
51
- horizontal
52
- >
53
- Use TestDriver from GitHub web, Copilot chat, PR reviews, and mobile.
54
- </Card>
69
+ ## Next steps
70
+
71
+ <CardGroup cols={2}>
72
+ <Card title="How the agent works" icon="hand-horns" href="/agent">
73
+ What the agent does on pull requests, issues, and mentions.
74
+ </Card>
75
+ <Card title="Prevent regressions" icon="shield-check" href="/copilot/auto-healing">
76
+ Run tests in CI and have the agent fix them when your app changes.
77
+ </Card>
78
+ <Card title="Run tests in CI/CD" icon="code-branch" href="/ci-cd">
79
+ Run your TestDriver tests in GitHub Actions.
80
+ </Card>
81
+ <Card title="Set up a project" icon="wrench" href="/quickstart-manual">
82
+ Write and run tests yourself in your own repository.
83
+ </Card>
84
+ </CardGroup>