@testdriverai/mcp 7.10.0-canary.0 → 7.10.1-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 (196) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/agent/index.js +116 -71
  3. package/agent/interface.js +13 -1
  4. package/agent/lib/commands.js +35 -15
  5. package/agent/lib/provision-commands.js +92 -11
  6. package/agent/lib/sandbox.js +263 -30
  7. package/agent/lib/sdk.js +16 -12
  8. package/agent/lib/system.js +107 -31
  9. package/ai/.claude-plugin/plugin.json +89 -4
  10. package/ai/agents/testdriver.md +4 -8
  11. package/ai/skills/testdriver-assert/SKILL.md +0 -1
  12. package/ai/skills/testdriver-aws-setup/SKILL.md +1 -1
  13. package/ai/skills/testdriver-caching/SKILL.md +13 -6
  14. package/ai/skills/testdriver-ci-cd/SKILL.md +57 -14
  15. package/ai/skills/testdriver-client/SKILL.md +10 -6
  16. package/ai/skills/testdriver-customizing-devices/SKILL.md +7 -5
  17. package/ai/skills/testdriver-dashcam/SKILL.md +36 -3
  18. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +28 -4
  19. package/ai/skills/testdriver-device-config/SKILL.md +5 -5
  20. package/ai/skills/testdriver-find/SKILL.md +50 -11
  21. package/ai/skills/testdriver-generating-tests/SKILL.md +163 -8
  22. package/ai/skills/testdriver-hosted/SKILL.md +1 -1
  23. package/ai/skills/testdriver-machine-setup/SKILL.md +331 -0
  24. package/ai/skills/testdriver-making-assertions/SKILL.md +78 -2
  25. package/ai/skills/testdriver-mcp-workflow/SKILL.md +2 -2
  26. package/ai/skills/testdriver-parse/SKILL.md +1 -1
  27. package/ai/skills/testdriver-performing-actions/SKILL.md +97 -3
  28. package/ai/skills/testdriver-provision/SKILL.md +0 -20
  29. package/ai/skills/testdriver-quickstart/SKILL.md +299 -21
  30. package/ai/skills/testdriver-reusable-code/SKILL.md +3 -3
  31. package/ai/skills/testdriver-running-tests/SKILL.md +1 -1
  32. package/ai/skills/testdriver-screenshot/SKILL.md +5 -5
  33. package/ai/skills/testdriver-scroll/SKILL.md +30 -160
  34. package/ai/skills/testdriver-test-writer/SKILL.md +3 -5
  35. package/ai/skills/testdriver-testdriver/SKILL.md +3 -7
  36. package/ai/skills/testdriver-wait/SKILL.md +1 -1
  37. package/{docs/v7/ai.mdx → ai/skills/testdriver:ai/SKILL.md} +3 -4
  38. package/ai/skills/testdriver:assert/SKILL.md +315 -0
  39. package/ai/skills/testdriver:aws-setup/SKILL.md +448 -0
  40. package/ai/skills/testdriver:cache/SKILL.md +221 -0
  41. package/ai/skills/testdriver:caching/SKILL.md +124 -0
  42. package/ai/skills/testdriver:captcha/SKILL.md +158 -0
  43. package/ai/skills/testdriver:ci-cd/SKILL.md +659 -0
  44. package/ai/skills/testdriver:click/SKILL.md +286 -0
  45. package/ai/skills/testdriver:client/SKILL.md +477 -0
  46. package/ai/skills/testdriver:customizing-devices/SKILL.md +319 -0
  47. package/ai/skills/testdriver:dashcam/SKILL.md +451 -0
  48. package/ai/skills/testdriver:debugging-with-screenshots/SKILL.md +415 -0
  49. package/{docs/v7/device-config.mdx → ai/skills/testdriver:device-config/SKILL.md} +8 -8
  50. package/ai/skills/testdriver:double-click/SKILL.md +102 -0
  51. package/ai/skills/testdriver:elements/SKILL.md +605 -0
  52. package/ai/skills/testdriver:enterprise/SKILL.md +7 -0
  53. package/ai/skills/testdriver:errors/SKILL.md +246 -0
  54. package/ai/skills/testdriver:events/SKILL.md +356 -0
  55. package/ai/skills/testdriver:exec/SKILL.md +317 -0
  56. package/ai/skills/testdriver:find/SKILL.md +860 -0
  57. package/ai/skills/testdriver:focus-application/SKILL.md +293 -0
  58. package/ai/skills/testdriver:generating-tests/SKILL.md +25 -0
  59. package/ai/skills/testdriver:hosted/SKILL.md +156 -0
  60. package/ai/skills/testdriver:hover/SKILL.md +278 -0
  61. package/{docs/v7/locating-elements.mdx → ai/skills/testdriver:locating-elements/SKILL.md} +3 -3
  62. package/ai/skills/testdriver:making-assertions/SKILL.md +32 -0
  63. package/ai/skills/testdriver:mcp/SKILL.md +7 -0
  64. package/ai/skills/testdriver:mouse-down/SKILL.md +161 -0
  65. package/ai/skills/testdriver:mouse-up/SKILL.md +164 -0
  66. package/ai/skills/testdriver:parse/SKILL.md +236 -0
  67. package/ai/skills/testdriver:performing-actions/SKILL.md +53 -0
  68. package/ai/skills/testdriver:press-keys/SKILL.md +348 -0
  69. package/ai/skills/testdriver:provision/SKILL.md +331 -0
  70. package/ai/skills/testdriver:quickstart/SKILL.md +172 -0
  71. package/ai/skills/testdriver:redraw/SKILL.md +214 -0
  72. package/ai/skills/testdriver:reusable-code/SKILL.md +249 -0
  73. package/ai/skills/testdriver:right-click/SKILL.md +123 -0
  74. package/{docs/v7/running-tests.mdx → ai/skills/testdriver:running-tests/SKILL.md} +4 -4
  75. package/ai/skills/testdriver:screenshot/SKILL.md +248 -0
  76. package/ai/skills/testdriver:screenshots/SKILL.md +184 -0
  77. package/ai/skills/testdriver:scroll/SKILL.md +205 -0
  78. package/ai/skills/testdriver:secrets/SKILL.md +115 -0
  79. package/ai/skills/testdriver:self-hosted/SKILL.md +147 -0
  80. package/ai/skills/testdriver:test-results-json/SKILL.md +257 -0
  81. package/ai/skills/testdriver:testdriver/SKILL.md +624 -0
  82. package/ai/skills/testdriver:type/SKILL.md +357 -0
  83. package/ai/skills/testdriver:variables/SKILL.md +111 -0
  84. package/ai/skills/testdriver:wait/SKILL.md +50 -0
  85. package/{docs/v7/waiting-for-elements.mdx → ai/skills/testdriver:waiting-for-elements/SKILL.md} +3 -3
  86. package/ai/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
  87. package/debugger/index.html +12 -0
  88. package/docs/_data/examples-manifest.json +54 -46
  89. package/docs/_data/examples-manifest.schema.json +12 -2
  90. package/docs/_scripts/extract-example-urls.js +21 -3
  91. package/docs/_scripts/generate-examples.js +64 -16
  92. package/docs/changelog.mdx +29 -2
  93. package/docs/claude-mcp-plugin.mdx +65 -18
  94. package/docs/docs.json +16 -33
  95. package/docs/snippets/tests/scroll-yaml.mdx +2 -2
  96. package/docs/v6/commands/scroll-until-image.mdx +1 -1
  97. package/docs/v6/commands/scroll-until-text.mdx +2 -2
  98. package/docs/v6/commands/scroll.mdx +2 -2
  99. package/docs/v7/_drafts/agents.mdx +0 -4
  100. package/docs/v7/_drafts/best-practices.mdx +0 -12
  101. package/docs/v7/_drafts/commands/scroll-until-image.mdx +1 -1
  102. package/docs/v7/_drafts/commands/scroll-until-text.mdx +2 -2
  103. package/docs/v7/_drafts/commands/scroll.mdx +1 -1
  104. package/docs/v7/_drafts/configuration.mdx +0 -12
  105. package/docs/v7/_drafts/faq.mdx +2 -10
  106. package/docs/v7/_drafts/readme.mdx +0 -1
  107. package/docs/v7/_drafts/troubleshooting.mdx +1 -4
  108. package/docs/v7/assert.mdx +0 -1
  109. package/docs/v7/aws-setup.mdx +1 -1
  110. package/docs/v7/caching.mdx +14 -10
  111. package/docs/v7/ci-cd.mdx +98 -14
  112. package/docs/v7/client.mdx +10 -6
  113. package/docs/v7/copilot/auto-healing.mdx +167 -18
  114. package/docs/v7/copilot/running-tests.mdx +915 -54
  115. package/docs/v7/customizing-devices.mdx +7 -5
  116. package/docs/v7/dashcam.mdx +36 -3
  117. package/docs/v7/debugging-with-screenshots.mdx +31 -7
  118. package/docs/v7/examples/ai.mdx +13 -8
  119. package/docs/v7/examples/assert.mdx +1 -1
  120. package/docs/v7/examples/chrome-extension.mdx +30 -13
  121. package/docs/v7/examples/element-not-found.mdx +1 -1
  122. package/docs/v7/examples/findall-coffee-icons.mdx +3 -2
  123. package/docs/v7/examples/formatted-logging.mdx +74 -0
  124. package/docs/v7/examples/hover-image.mdx +1 -1
  125. package/docs/v7/examples/hover-text-with-description.mdx +2 -2
  126. package/docs/v7/examples/hover-text.mdx +1 -1
  127. package/docs/v7/examples/installer.mdx +1 -1
  128. package/docs/v7/examples/launch-vscode-linux.mdx +27 -27
  129. package/docs/v7/examples/match-image.mdx +1 -1
  130. package/docs/v7/examples/parse.mdx +3 -2
  131. package/docs/v7/examples/press-keys.mdx +2 -2
  132. package/docs/v7/examples/scroll-keyboard.mdx +2 -2
  133. package/docs/v7/examples/scroll-until-text.mdx +1 -1
  134. package/docs/v7/examples/scroll.mdx +1 -1
  135. package/docs/v7/examples/type.mdx +1 -1
  136. package/docs/v7/find.mdx +50 -11
  137. package/docs/v7/generating-tests.mdx +166 -10
  138. package/docs/v7/hosted.mdx +1 -1
  139. package/docs/v7/making-assertions.mdx +81 -4
  140. package/docs/v7/parse.mdx +1 -1
  141. package/docs/v7/performing-actions.mdx +100 -5
  142. package/docs/v7/provision.mdx +0 -20
  143. package/docs/v7/quickstart.mdx +299 -21
  144. package/docs/v7/reusable-code.mdx +3 -3
  145. package/docs/v7/screenshot.mdx +5 -5
  146. package/docs/v7/scroll.mdx +30 -160
  147. package/docs/v7/wait.mdx +1 -1
  148. package/examples/chrome-extension.test.mjs +29 -12
  149. package/examples/config.mjs +1 -1
  150. package/examples/launch-vscode-linux.test.mjs +25 -25
  151. package/interfaces/cli/commands/init.js +84 -2
  152. package/interfaces/vitest-plugin.mjs +51 -61
  153. package/lib/core/Dashcam.js +43 -2
  154. package/lib/core/index.d.ts +13 -1
  155. package/lib/github-comment.mjs +11 -5
  156. package/lib/init-project.js +98 -44
  157. package/lib/install-clients.js +470 -0
  158. package/lib/provision.js +749 -0
  159. package/lib/resolve-channel.js +2 -2
  160. package/lib/sentry.js +15 -2
  161. package/lib/vitest/hooks.mjs +44 -34
  162. package/mcp-server/README.md +32 -0
  163. package/mcp-server/dist/core/actions.d.ts +176 -0
  164. package/mcp-server/dist/core/actions.js +753 -0
  165. package/mcp-server/dist/env-utils.d.ts +45 -0
  166. package/mcp-server/dist/env-utils.js +63 -0
  167. package/mcp-server/dist/provision-types.d.ts +6 -2
  168. package/mcp-server/dist/provision-types.js +3 -1
  169. package/mcp-server/dist/server.mjs +449 -751
  170. package/mcp-server/package-lock.json +384 -1
  171. package/mcp-server/package.json +5 -2
  172. package/mcp-server/src/core/actions.ts +912 -0
  173. package/mcp-server/src/env-utils.test.ts +82 -0
  174. package/mcp-server/src/env-utils.ts +77 -0
  175. package/mcp-server/src/provision-types.ts +4 -1
  176. package/mcp-server/src/server.ts +533 -954
  177. package/mcp-server/tsconfig.json +1 -1
  178. package/mcp-server/vitest.config.ts +7 -0
  179. package/package.json +15 -3
  180. package/sdk.d.ts +11 -9
  181. package/sdk.js +116 -746
  182. package/setup/aws/spawn-runner.sh +24 -3
  183. package/docs/v7/_drafts/caching-ai.mdx +0 -215
  184. package/docs/v7/_drafts/caching.mdx +0 -366
  185. package/docs/v7/_drafts/prompt-cache.mdx +0 -200
  186. package/docs/v7/copilot/creating-tests.mdx +0 -156
  187. package/docs/v7/copilot/github.mdx +0 -143
  188. package/docs/v7/copilot/setup.mdx +0 -143
  189. package/docs/v7/examples/exec-output.mdx +0 -84
  190. package/docs/v7/examples/exec-pwsh.mdx +0 -82
  191. package/docs/v7/examples/focus-window.mdx +0 -61
  192. package/docs/v7/examples/scroll-until-image.mdx +0 -82
  193. package/docs/v7/examples/windows-installer.mdx +0 -95
  194. package/examples/formatted-logging.test.mjs +0 -27
  195. package/examples/match-image.test.mjs +0 -55
  196. package/manual/exec-stream-logs.test.mjs +0 -25
@@ -1,12 +1,82 @@
1
1
  ---
2
2
  name: testdriver:making-assertions
3
- description: Verify application state with AI-powered assertions
3
+ description: Locate elements and verify app state with AI-powered assertions
4
4
  ---
5
5
  <!-- Generated from making-assertions.mdx. DO NOT EDIT. -->
6
6
 
7
+ Once a test runs, validate that the app did what it should. Validation has two parts: locating the elements you want to check, and making assertions about the state of your app. TestDriver uses AI as a judge, returning a boolean plus reasoning about whether your app is in the expected state.
8
+
9
+ ## Locating Elements
10
+
11
+ ### Locating Single Elements
12
+
13
+ Use natural language to describe elements. Descriptions should be specific enough to locate the element, but not too-specific that they break with minor UI changes. For example:
14
+
15
+ ```javascript
16
+ await testdriver.find('email input field');
17
+ await testdriver.find('first product card in the grid');
18
+ await testdriver.find('dropdown menu labeled "Country"');
19
+ ```
20
+
21
+ <Info>TestDriver will cache found elements for improved performance on subsequent calls. Learn more about [element caching here](/v7/caching).</Info>
22
+
23
+ ### Debugging Found Elements
24
+
25
+ After finding an element, you can inspect its properties for debugging:
26
+
27
+ ```javascript
28
+ const button = await testdriver.find('submit button');
29
+ console.log(button);
30
+ ```
31
+
32
+ This outputs all element properties:
33
+
34
+ ```javascript
35
+ {
36
+ description: 'submit button',
37
+ found: true,
38
+ x: 150,
39
+ y: 300,
40
+ coordinates: { x: 150, y: 300, centerX: 200, centerY: 320 },
41
+ threshold: 0.8,
42
+ confidence: 0.95,
43
+ similarity: 0.92,
44
+ selector: 'button[type="submit"]',
45
+ cache: {
46
+ hit: true,
47
+ strategy: 'pixel-diff',
48
+ createdAt: '2025-01-15T10:30:00Z',
49
+ diffPercent: 0.02,
50
+ imageUrl: 'https://...'
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### Working with Multiple Elements
56
+
57
+ Find and interact with multiple elements:
58
+
59
+ ```javascript
60
+ // Find all matching elements
61
+ const products = await testdriver.findAll('product card');
62
+ console.log(`Found ${products.length} products`);
63
+
64
+ // Interact with each
65
+ for (const product of products) {
66
+ const title = await product.find('title text');
67
+ console.log('Product:', title.text);
68
+
69
+ await product.find('add to cart button').click();
70
+ }
71
+
72
+ // Or find specific element
73
+ const firstProduct = products[0];
74
+ await firstProduct.click();
75
+ ```
76
+
7
77
  ## Making Assertions
8
78
 
9
- Use AI-powered assertions to verify application state:
79
+ Use AI-powered assertions to verify application state. TestDriver acts as a judge: it evaluates your natural-language statement against the current state of the app and returns a boolean plus reasoning explaining the verdict.
10
80
 
11
81
  ```javascript
12
82
  // Verify visibility
@@ -30,3 +100,9 @@ await testdriver.assert('form has red border');
30
100
  ```
31
101
 
32
102
  <Info>Assertions are not cached and always re-evaluated to ensure accuracy.</Info>
103
+
104
+ ## Next
105
+
106
+ <Card title="Adapt" icon="arrows-rotate" href="/v7/performing-actions">
107
+ Drive your app forward by performing actions on the elements you've located and validated.
108
+ </Card>
@@ -294,7 +294,7 @@ When creating a new test project, use these exact dependencies:
294
294
  {
295
295
  "type": "module",
296
296
  "devDependencies": {
297
- "testdriverai": "beta",
297
+ "testdriverai": "canary",
298
298
  "vitest": "^4.0.0"
299
299
  },
300
300
  "scripts": {
@@ -303,7 +303,7 @@ When creating a new test project, use these exact dependencies:
303
303
  }
304
304
  ```
305
305
 
306
- **Important:** The package is `testdriverai` (NOT `@testdriverai/sdk`). Always install from the `beta` tag.
306
+ **Important:** The package is `testdriverai` (NOT `@testdriverai/sdk`). Always install from the `canary` tag.
307
307
 
308
308
  ## Test File Format
309
309
 
@@ -120,7 +120,7 @@ console.log(`Found ${buttons.length} buttons`);
120
120
 
121
121
  ```javascript
122
122
  import { describe, expect, it } from "vitest";
123
- import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
123
+ import { TestDriver } from "testdriverai/vitest/hooks";
124
124
 
125
125
  describe("Login Page", () => {
126
126
  it("should have expected form elements", async (context) => {
@@ -1,9 +1,13 @@
1
1
  ---
2
2
  name: testdriver:performing-actions
3
- description: Click, type, hover, scroll and more with TestDriver
3
+ description: Perform actions and handle dynamic, async UI so tests adapt to change
4
4
  ---
5
5
  <!-- Generated from performing-actions.mdx. DO NOT EDIT. -->
6
6
 
7
+ Real apps move, load, and change. Adapt your tests to handle it.
8
+
9
+ Once you've [generated](/v7/generating-tests) and [learned](/v7/caching) your tests and gotten them [running](/v7/copilot/running-tests), the next challenge is the real world: buttons appear after a spinner, pages navigate, animations play, and content streams in over the network. To keep tests reliable, you need to perform the right actions and handle timing so your tests adapt to how the UI actually behaves instead of breaking.
10
+
7
11
  ## Performing Actions
8
12
 
9
13
  TestDriver provides a variety of actions you can perform, like [clicking](/v7/click), [typing](/v7/type), [hovering](/v7/hover), and [scrolling](/v7/scroll). For a full list, see the [API Reference](/v7/click).
@@ -27,7 +31,6 @@ await testdriver.find('dropdown menu').hover();
27
31
 
28
32
  // Scrolling
29
33
  await testdriver.scroll('down', 500);
30
- await testdriver.scrollUntilText('Footer content');
31
34
 
32
35
  // Waiting
33
36
  await testdriver.wait(2000); // Wait 2 seconds for animation/state change
@@ -37,7 +40,7 @@ const price = await testdriver.extract('the total price');
37
40
  const orderNumber = await testdriver.extract('the order confirmation number');
38
41
  ```
39
42
 
40
- ## Chaining Actions
43
+ ### Chaining Actions
41
44
 
42
45
  TestDriver supports method chaining for cleaner code:
43
46
 
@@ -52,3 +55,94 @@ Or save element reference for later use:
52
55
  const button = await testdriver.find('submit button');
53
56
  await button.click();
54
57
  ```
58
+
59
+ ## Waiting for Dynamic Content
60
+
61
+ By default, `find()` automatically polls for up to 10 seconds, retrying every 5 seconds until the element is found. This means most elements that appear after short async operations will be found without any extra configuration.
62
+
63
+ For longer operations, increase the `timeout`:
64
+
65
+ ```javascript
66
+ // Default behavior - polls for up to 10 seconds automatically
67
+ const element = await testdriver.find('Loading complete indicator');
68
+ await element.click();
69
+
70
+ // Wait up to 30 seconds for slower operations
71
+ const element = await testdriver.find('Loading complete indicator', { timeout: 30000 });
72
+ await element.click();
73
+
74
+ // Useful after actions that trigger loading states
75
+ await testdriver.find('submit button').click();
76
+ await testdriver.find('success message', { timeout: 15000 });
77
+
78
+ // Disable polling for instant checks
79
+ const toast = await testdriver.find('notification toast', { timeout: 0 });
80
+ ```
81
+
82
+ ### Flake Prevention
83
+
84
+ TestDriver automatically waits for the screen and network to stabilize after each action using **redraw detection**. This prevents flaky tests caused by animations, loading states, or dynamic content updates.
85
+
86
+ <Note>
87
+ Redraw detection adds a small delay after each action but significantly reduces test flakiness.
88
+ </Note>
89
+
90
+ For example, when clicking a submit button that navigates to a new page:
91
+
92
+ ```javascript
93
+ // Click submit - TestDriver automatically waits for the new page to load
94
+ await testdriver.find('submit button').click();
95
+
96
+ // By the time this runs, the page has fully loaded and stabilized
97
+ await testdriver.assert('dashboard is displayed');
98
+ await testdriver.find('welcome message');
99
+ ```
100
+
101
+ Without redraw detection, you'd need manual waits or retries to handle the page transition. TestDriver handles this automatically by detecting when the screen stops changing and network requests complete.
102
+
103
+ You can disable redraw detection or customize its behavior:
104
+
105
+ ```javascript
106
+ // Disable redraw detection for faster tests (less reliable)
107
+ const testdriver = TestDriver(context, {
108
+ redraw: false
109
+ });
110
+ ```
111
+
112
+ Here is an example of customizing redraw detection:
113
+
114
+ ```javascript
115
+ // Fine-tune redraw detection
116
+ const testdriver = TestDriver(context, {
117
+ redraw: {
118
+ enabled: true,
119
+ diffThreshold: 0.1, // Pixel difference threshold (0-1)
120
+ screenRedraw: true, // Monitor screen changes
121
+ networkMonitor: true, // Wait for network idle
122
+ }
123
+ });
124
+ ```
125
+
126
+ ### Simple Delays with `wait()`
127
+
128
+ For simple pauses — waiting for animations, transitions, or state changes after an action — use `wait()`:
129
+
130
+ ```javascript
131
+ // Wait for an animation to complete
132
+ await testdriver.find('menu toggle').click();
133
+ await testdriver.wait(2000);
134
+
135
+ // Wait for a page transition to settle
136
+ await testdriver.find('next page button').click();
137
+ await testdriver.wait(1000);
138
+ ```
139
+
140
+ <Note>
141
+ For waiting for specific **elements** to appear, prefer `find()` with a `timeout` option. Use `wait()` only for simple time-based pauses.
142
+ </Note>
143
+
144
+ Once your tests can reliably act on a changing UI and [assert](/v7/making-assertions) the results, the next step is figuring out what happened when something does go wrong.
145
+
146
+ <Card title="Next: Debug" icon="bug" href="/v7/debugging-with-screenshots">
147
+ Use screenshots and run output to see exactly what your test saw and pinpoint failures.
148
+ </Card>
@@ -14,10 +14,6 @@ Access provision methods via `testdriver.provision.*`:
14
14
  await testdriver.provision.chrome({ url: 'https://example.com' });
15
15
  ```
16
16
 
17
- <Note>
18
- When `reconnect: true` is set on the client, **all provision methods are skipped** since the application is assumed to already be running.
19
- </Note>
20
-
21
17
  ## Methods
22
18
 
23
19
  ### chrome()
@@ -234,22 +230,6 @@ await testdriver.provision.dashcam({
234
230
  });
235
231
  ```
236
232
 
237
- ## Reconnect Behavior
238
-
239
- When `reconnect: true` is set on the client, all provision methods are wrapped in a Proxy that intercepts calls and skips them silently. This is because when reconnecting to an existing sandbox, the applications are already running.
240
-
241
- ```javascript
242
- const testdriver = new TestDriver({
243
- reconnect: true,
244
- });
245
-
246
- await testdriver.ready();
247
-
248
- // These calls are silently skipped:
249
- await testdriver.provision.chrome({ url: 'https://example.com' });
250
- await testdriver.provision.dashcam();
251
- ```
252
-
253
233
  ## Types
254
234
 
255
235
  ```typescript
@@ -9,6 +9,53 @@ TestDriver makes it easy to write automated computer-use tests for web browsers,
9
9
  <Tip><a href="https://discord.com/invite/cWDFW8DzPm" target="_blank" rel="noreferrer">Join our Discord</a> if you have any questions or need help getting started!</Tip>
10
10
 
11
11
  <Tabs>
12
+ <Tab title="Add to GitHub" icon="github">
13
+
14
+ Drop-in UI testing for any GitHub repository. Mention `@testdriverai` anywhere in your repo and it writes UI tests and catches regressions before they merge.
15
+
16
+ <Card
17
+ title="Add to GitHub"
18
+ icon="github"
19
+ href="https://go.testdriver.ai/github"
20
+ arrow
21
+ horizontal
22
+ >
23
+ Install the TestDriver GitHub app and start testing in minutes — no setup required.
24
+ </Card>
25
+
26
+ <Steps>
27
+ <Step title="Install the GitHub App">
28
+ Click **Add to GitHub** above and install TestDriver on the repositories you want to test.
29
+ </Step>
30
+
31
+ <Step title="Mention @testdriverai">
32
+ Open a pull request or issue and mention `@testdriverai` to have it write and run UI tests:
33
+
34
+ ```
35
+ @testdriverai Write a test that verifies the homepage loads and the signup button works.
36
+ ```
37
+
38
+ TestDriver spawns a sandbox, writes the test, and posts results right in the conversation.
39
+ </Step>
40
+
41
+ <Step title="Catch Regressions Automatically">
42
+ Once your tests are committed, TestDriver runs them on every pull request and flags regressions before they merge.
43
+ </Step>
44
+ </Steps>
45
+
46
+ Want to use TestDriver from GitHub Copilot or the GitHub Mobile app instead? See the full GitHub guide:
47
+
48
+ <Card
49
+ title="GitHub Integration Guide"
50
+ icon="arrow-right"
51
+ href="/v7/copilot/auto-healing#use-testdriver-in-github"
52
+ arrow
53
+ horizontal
54
+ >
55
+ Use TestDriver from GitHub web, Copilot chat, PR reviews, and mobile.
56
+ </Card>
57
+
58
+ </Tab>
12
59
  <Tab title="CLI" icon="terminal">
13
60
 
14
61
  Get started quickly with the TestDriver CLI.
@@ -39,32 +86,263 @@ TestDriver makes it easy to write automated computer-use tests for web browsers,
39
86
  </Step>
40
87
  </Steps>
41
88
  </Tab>
42
- <Tab title="GitHub Copilot" icon="github">
89
+ <Tab title="AI Setup" icon="robot">
43
90
 
44
- Use the TestDriver VS Code extension with GitHub Copilot for an AI-powered testing workflow.
91
+ Plug TestDriver into your AI client so you can write, run, and debug real end-to-end tests right from chat. There are three pieces, and `testdriverai init` installs all of them for you:
45
92
 
46
- <Card
47
- title="Install TestDriver for VS Code"
48
- icon="/images/content/extension/vscode.svg"
49
- href="vscode:extension/testdriver.testdriver"
50
- arrow
51
- horizontal
52
- >
53
- </Card>
93
+ - **The agent** — an expert test-creator that drives a live sandbox, writes code after each step, and reruns the test until it passes.
94
+ - **Skills** — small instruction files that teach the agent the exact syntax for each TestDriver capability (`find`, `click`, `type`, `assert`, …).
95
+ - **The MCP server** — exposes TestDriver's computer-use tools over the [Model Context Protocol](https://modelcontextprotocol.io) so any MCP-capable client can use them.
54
96
 
55
- The extension provides one-click sign-in, project initialization, a live preview panel for watching tests execute, and MCP server configuration for GitHub Copilot.
97
+ ### Quick install (recommended)
56
98
 
57
- Once installed, follow the full setup guide to configure MCP and start building tests with AI assistance:
99
+ `testdriverai init` wires up the agent, skills, and MCP server for you, writing each client's config in the exact format and location it expects:
58
100
 
59
- <Card
60
- title="VS Code + Copilot Setup Guide"
61
- icon="arrow-right"
62
- href="/v7/copilot/setup"
63
- arrow
64
- horizontal
65
- >
66
- Sign in, initialize your project, and configure MCP for GitHub Copilot.
67
- </Card>
101
+ ```bash
102
+ # interactive pick your client(s)
103
+ npx testdriverai init
104
+
105
+ # one client
106
+ npx testdriverai init --client claude-code
107
+
108
+ # several
109
+ npx testdriverai init --client claude-code,cursor,vscode
110
+
111
+ # everything
112
+ npx testdriverai init --client all
113
+ ```
114
+
115
+ <Info>
116
+ `init` detects clients already present in your project and pre-selects them in the picker. Re-running `init` is safe — it merges the TestDriver entry into existing config without overwriting your other servers.
117
+ </Info>
118
+
119
+ You'll need a TestDriver API key. Create one at [console.testdriver.ai/team](https://console.testdriver.ai/team) and `init` will save it to `.env` as `TD_API_KEY`.
120
+
121
+ ### The agent
122
+
123
+ The **TestDriver agent** is an expert test-creator that runs inside your AI client (Claude Code, Cursor, VS Code, and others). It writes, runs, and debugs real end-to-end tests by driving your app the same way a person would — using AI vision to find elements, click, type, and assert — through the TestDriver MCP server.
124
+
125
+ Unlike a chat assistant that only suggests code, the agent works **iteratively against a live sandbox**: it starts a session, performs each action, writes the generated code to your test file, verifies the result with a screenshot, and reruns the test until it passes.
126
+
127
+ During init you'll be asked which AI client(s) to install into. The agent is written to the location each client expects:
128
+
129
+ | Client | Agent location |
130
+ | --- | --- |
131
+ | Claude Code | `.claude/agents/testdriver.md` |
132
+ | VS Code (Copilot) | `.github/agents/testdriver.agent.md` |
133
+ | Cursor | `.cursor/rules/testdriver.mdc` |
134
+ | Windsurf | `.windsurf/rules/testdriver.md` |
135
+ | Codex | `AGENTS.md` |
136
+ | Zed | `.rules` |
137
+
138
+ Once installed, invoke it from your client's chat:
139
+
140
+ ```text
141
+ @testdriver write a test that logs in and verifies the dashboard loads
142
+ ```
143
+
144
+ The agent will spin up a sandbox, perform the steps live, write them into a test file under `tests/`, and run it for you.
145
+
146
+ ### Skills
147
+
148
+ **Skills** are small, focused instruction files — one per TestDriver capability — that teach your AI client exactly how to use each part of the TestDriver SDK and MCP tools. They follow the [Anthropic `SKILL.md` format](https://code.claude.com/docs/en/skills): a folder per skill, each containing a `SKILL.md` with YAML frontmatter and a markdown body.
149
+
150
+ There are **106 skills**, generated directly from the TestDriver documentation, covering every action and concept: `find`, `click`, `type`, `assert`, `check`, `scroll`, `press-keys`, `provision`, caching, secrets, CI/CD, and more. They're written to the directory each client expects:
151
+
152
+ | Client | Skills location |
153
+ | --- | --- |
154
+ | Claude Code | `.claude/skills/<name>/SKILL.md` |
155
+ | Zed | `.agents/skills/<name>/SKILL.md` |
156
+ | Codex | referenced from `AGENTS.md` |
157
+ | VS Code · Cursor · Windsurf | folded into the agent rules/instructions |
158
+
159
+ <Note>
160
+ Skills are **generated, not hand-edited** — each is built from a `.mdx` docs page and carries a `DO NOT EDIT` marker. To change a skill, edit the corresponding documentation page and run `node docs/_scripts/generate-skills.js`.
161
+ </Note>
162
+
163
+ ### MCP server
164
+
165
+ The **TestDriver MCP server** exposes TestDriver's computer-use tools — `session_start`, `find`, `click`, `type`, `assert`, `check`, `screenshot`, and more — over the [Model Context Protocol](https://modelcontextprotocol.io). It runs as a local stdio process:
166
+
167
+ ```bash
168
+ npx -p testdriverai testdriverai-mcp
169
+ ```
170
+
171
+ and authenticates with your `TD_API_KEY`. `testdriverai init` configures it for you, but you can also wire it up by hand:
172
+
173
+ | Client | Auto-install | MCP config file | Config key |
174
+ | --- | --- | --- | --- |
175
+ | Claude Code | ✅ | `.mcp.json` | `mcpServers` |
176
+ | Claude Desktop | ✅ | OS-specific | `mcpServers` |
177
+ | Cursor | ✅ | `.cursor/mcp.json` | `mcpServers` |
178
+ | VS Code (Copilot) | ✅ | `.vscode/mcp.json` | `servers` |
179
+ | Windsurf | ✅ | `~/.codeium/windsurf/mcp_config.json` | `mcpServers` |
180
+ | Codex | ✅ | `~/.codex/config.toml` | `[mcp_servers]` |
181
+ | Zed | ✅ | `.zed/settings.json` | `context_servers` |
182
+ | Lovable | ⚙️ partial | GitHub `AGENTS.md` + UI | — |
183
+ | Replit | ⚙️ partial | `replit.md` + UI | — |
184
+ | v0 (Vercel) | 📝 manual | web UI only | — |
185
+
186
+ <Note>
187
+ Each client uses a **different top-level key** for MCP servers. The most common mistake when configuring by hand is using `mcpServers` for VS Code (it wants `servers`), Codex (TOML `[mcp_servers]`), or Zed (`context_servers`).
188
+ </Note>
189
+
190
+ <Tabs>
191
+ <Tab title="Claude Code">
192
+ Add to `.mcp.json` at your project root (or `~/.claude.json` for all projects):
193
+
194
+ ```json
195
+ {
196
+ "mcpServers": {
197
+ "testdriver": {
198
+ "type": "stdio",
199
+ "command": "npx",
200
+ "args": ["-p", "testdriverai", "testdriverai-mcp"],
201
+ "env": { "TD_API_KEY": "${TD_API_KEY}" }
202
+ }
203
+ }
204
+ }
205
+ ```
206
+ </Tab>
207
+
208
+ <Tab title="Claude Desktop">
209
+ Edit the Claude Desktop config file:
210
+
211
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
212
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
213
+ - **Linux:** `~/.config/Claude/claude_desktop_config.json`
214
+
215
+ ```json
216
+ {
217
+ "mcpServers": {
218
+ "testdriver": {
219
+ "command": "npx",
220
+ "args": ["-p", "testdriverai", "testdriverai-mcp"],
221
+ "env": { "TD_API_KEY": "your_api_key" }
222
+ }
223
+ }
224
+ }
225
+ ```
226
+
227
+ Restart Claude Desktop after saving.
228
+ </Tab>
229
+
230
+ <Tab title="Cursor">
231
+ Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
232
+
233
+ ```json
234
+ {
235
+ "mcpServers": {
236
+ "testdriver": {
237
+ "type": "stdio",
238
+ "command": "npx",
239
+ "args": ["-p", "testdriverai", "testdriverai-mcp"],
240
+ "env": { "TD_API_KEY": "${TD_API_KEY}" }
241
+ }
242
+ }
243
+ }
244
+ ```
245
+ </Tab>
246
+
247
+ <Tab title="VS Code">
248
+ Add to `.vscode/mcp.json`. VS Code uses the `servers` key and an `inputs` prompt for secrets:
249
+
250
+ ```json
251
+ {
252
+ "servers": {
253
+ "testdriver": {
254
+ "type": "stdio",
255
+ "command": "npx",
256
+ "args": ["-p", "testdriverai", "testdriverai-mcp"],
257
+ "env": { "TD_API_KEY": "${input:testdriver-api-key}" }
258
+ }
259
+ },
260
+ "inputs": [
261
+ {
262
+ "type": "promptString",
263
+ "id": "testdriver-api-key",
264
+ "description": "TestDriver API Key From https://console.testdriver.ai/team",
265
+ "password": true
266
+ }
267
+ ]
268
+ }
269
+ ```
270
+ </Tab>
271
+
272
+ <Tab title="Windsurf">
273
+ Windsurf reads MCP config globally. Add to `~/.codeium/windsurf/mcp_config.json`:
274
+
275
+ ```json
276
+ {
277
+ "mcpServers": {
278
+ "testdriver": {
279
+ "command": "npx",
280
+ "args": ["-p", "testdriverai", "testdriverai-mcp"],
281
+ "env": { "TD_API_KEY": "${TD_API_KEY}" }
282
+ }
283
+ }
284
+ }
285
+ ```
286
+ </Tab>
287
+
288
+ <Tab title="Codex">
289
+ Codex uses TOML. Add to `~/.codex/config.toml`:
290
+
291
+ ```toml
292
+ [mcp_servers.testdriver]
293
+ command = "npx"
294
+ args = ["-p", "testdriverai", "testdriverai-mcp"]
295
+ env = { TD_API_KEY = "${TD_API_KEY}" }
296
+ ```
297
+ </Tab>
298
+
299
+ <Tab title="Zed">
300
+ Zed calls them "context servers". Add to `.zed/settings.json` (project) or `~/.config/zed/settings.json` (global):
301
+
302
+ ```json
303
+ {
304
+ "context_servers": {
305
+ "testdriver": {
306
+ "command": "npx",
307
+ "args": ["-p", "testdriverai", "testdriverai-mcp"],
308
+ "env": { "TD_API_KEY": "${TD_API_KEY}" }
309
+ }
310
+ }
311
+ }
312
+ ```
313
+ </Tab>
314
+ </Tabs>
315
+
316
+ **Web-based clients** — Lovable, Replit, and v0 run in the browser, so the MCP server can't be launched as a local process. Configure them through each product's UI:
317
+
318
+ <AccordionGroup>
319
+ <Accordion title="Lovable">
320
+ 1. Connect your GitHub repo and run `npx testdriverai init --client lovable` — this writes `AGENTS.md` and the skills into the repo so Lovable's agent picks them up.
321
+ 2. In Lovable, open **Settings → MCP** and add the TestDriver server.
322
+ </Accordion>
323
+
324
+ <Accordion title="Replit">
325
+ 1. Run `npx testdriverai init --client replit` to write `replit.md` with the TestDriver agent guidance.
326
+ 2. In Replit, open **Tools → Integrations → MCP** and add a custom MCP server.
327
+ </Accordion>
328
+
329
+ <Accordion title="v0 (Vercel)">
330
+ v0 is fully UI-driven and does not read repo files.
331
+
332
+ 1. Open **[v0.app/chat/settings/mcp-connections](https://v0.app/chat/settings/mcp-connections)** and add the TestDriver MCP connection.
333
+ 2. Paste the agent guidance into **Instructions** (the **+** in the prompt bar).
334
+ </Accordion>
335
+ </AccordionGroup>
336
+
337
+ ### Verifying the install
338
+
339
+ Open your client's chat and ask the agent to write a test:
340
+
341
+ ```text
342
+ @testdriver write a test that opens the homepage and asserts the title
343
+ ```
344
+
345
+ If the MCP server is wired up correctly, the agent will start a session and you'll see screenshots come back as it works. If tools don't appear, check that `TD_API_KEY` is set and restart the client.
68
346
 
69
347
  </Tab>
70
348
  <Tab title="Manual" icon="wrench">
@@ -49,7 +49,7 @@ Now import and use these helpers in any test:
49
49
 
50
50
  ```javascript test/checkout.test.mjs
51
51
  import { describe, expect, it } from "vitest";
52
- import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
52
+ import { TestDriver } from "testdriverai/vitest/hooks";
53
53
  import { login } from './helpers/auth.js';
54
54
 
55
55
  describe("Checkout", () => {
@@ -120,7 +120,7 @@ Use the page object in your tests:
120
120
 
121
121
  ```javascript test/auth.test.mjs
122
122
  import { describe, expect, it } from "vitest";
123
- import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
123
+ import { TestDriver } from "testdriverai/vitest/hooks";
124
124
  import { LoginPage } from './pages/LoginPage.js';
125
125
 
126
126
  describe("Authentication", () => {
@@ -190,7 +190,7 @@ export async function setupAuthenticatedSession(testdriver, user = testUsers.reg
190
190
 
191
191
  ```javascript test/admin.test.mjs
192
192
  import { describe, expect, it } from "vitest";
193
- import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
193
+ import { TestDriver } from "testdriverai/vitest/hooks";
194
194
  import { testUsers, testUrls, setupAuthenticatedSession } from './fixtures/index.js';
195
195
 
196
196
  describe("Admin Panel", () => {
@@ -101,7 +101,7 @@ Set `maxConcurrency` in your Vitest config to match your license slot limit:
101
101
 
102
102
  ```javascript vitest.config.mjs
103
103
  import { defineConfig } from 'vitest/config';
104
- import { TestDriver } from 'testdriverai/vitest';
104
+ import TestDriver from 'testdriverai/vitest';
105
105
 
106
106
  export default defineConfig({
107
107
  test: {