@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
package/docs/docs.json CHANGED
@@ -20,7 +20,6 @@
20
20
  "group": "Overview",
21
21
  "pages": [
22
22
  "/v7/quickstart",
23
- "/v7/what-is-testdriver",
24
23
  {
25
24
  "group": "Examples",
26
25
  "icon": "code",
@@ -29,27 +28,20 @@
29
28
  "/v7/examples/assert",
30
29
  "/v7/examples/chrome-extension",
31
30
  "/v7/examples/element-not-found",
32
- "/v7/examples/exec-output",
33
- "/v7/examples/exec-pwsh",
34
31
  "/v7/examples/findall-coffee-icons",
35
- "/v7/examples/focus-window",
36
- "/v7/examples/formatted-logging",
37
32
  "/v7/examples/hover-image",
38
33
  "/v7/examples/hover-text-with-description",
39
34
  "/v7/examples/hover-text",
40
35
  "/v7/examples/installer",
41
36
  "/v7/examples/launch-vscode-linux",
42
- "/v7/examples/match-image",
43
37
  "/v7/examples/parse",
44
38
  "/v7/examples/press-keys",
45
- "/v7/examples/prompt",
46
39
  "/v7/examples/scroll-keyboard",
47
- "/v7/examples/scroll-until-image",
48
40
  "/v7/examples/scroll",
49
- "/v7/examples/type",
50
- "/v7/examples/windows-installer"
41
+ "/v7/examples/type"
51
42
  ]
52
43
  },
44
+ "/v7/what-is-testdriver",
53
45
  {
54
46
  "group": "Deployment",
55
47
  "icon": "server",
@@ -61,32 +53,16 @@
61
53
  "/changelog"
62
54
  ]
63
55
  },
64
- {
65
- "group": "GitHub Copilot",
66
- "pages": [
67
- "/v7/copilot/setup",
68
- "/v7/copilot/creating-tests",
69
- "/v7/copilot/running-tests",
70
- "/v7/copilot/github",
71
- "/v7/copilot/auto-healing"
72
- ]
73
- },
74
56
  {
75
57
  "group": "Guide",
76
58
  "pages": [
77
59
  "/v7/generating-tests",
78
- "/v7/device-config",
79
- "/v7/locating-elements",
80
- "/v7/waiting-for-elements",
81
- "/v7/performing-actions",
82
- "/v7/making-assertions"
83
- ]
84
- },
85
- {
86
- "group": "Running Tests",
87
- "pages": [
88
- "/v7/running-tests",
89
60
  "/v7/caching",
61
+ "/v7/copilot/running-tests",
62
+ "/v7/making-assertions",
63
+ "/v7/performing-actions",
64
+ "/v7/debugging-with-screenshots",
65
+ "/v7/copilot/auto-healing",
90
66
  "/v7/ci-cd",
91
67
  "/v7/test-results-json"
92
68
  ]
@@ -98,7 +74,7 @@
98
74
  "/v7/secrets",
99
75
  "/v7/reusable-code",
100
76
  {
101
- "group": "Self-Hosting Setup",
77
+ "group": "Self-Hosting",
102
78
  "icon": "server",
103
79
  "pages": [
104
80
  "/v7/aws-setup"
@@ -109,7 +85,6 @@
109
85
  {
110
86
  "group": "Actions",
111
87
  "pages": [
112
- "/v7/ai",
113
88
  "/v7/assert",
114
89
  "/v7/captcha",
115
90
  "/v7/click",
@@ -358,6 +333,14 @@
358
333
  }
359
334
  },
360
335
  "redirects": [
336
+ {
337
+ "source": "/v7/ai",
338
+ "destination": "/v7/quickstart"
339
+ },
340
+ {
341
+ "source": "/v7/ai/:slug*",
342
+ "destination": "/v7/quickstart"
343
+ },
361
344
  {
362
345
  "source": "/guides/github-actions",
363
346
  "destination": "/v6/action/setup"
@@ -14,7 +14,7 @@ steps:
14
14
  - command: press-keys
15
15
  keys:
16
16
  - enter
17
- - prompt: scroll down with the mouse 1000 pixels
17
+ - prompt: scroll down with the mouse 10 clicks
18
18
  commands:
19
19
  - command: hover-text
20
20
  text: "HTML: HyperText Markup Language"
@@ -22,7 +22,7 @@ steps:
22
22
  action: click
23
23
  - command: scroll
24
24
  direction: down
25
- amount: 1000
25
+ amount: 10
26
26
  - prompt: assert the page is scrolled
27
27
  commands:
28
28
  - command: assert
@@ -22,7 +22,7 @@ The `scroll-until-image` command is used to scroll the screen in a specified dir
22
22
  | :-----------: | :-------: | :---------------------------------------------------------------------------------------------------------------------- |
23
23
  | `description` | `string` | A description of the image and what it represents. |
24
24
  | `direction` | `string` | (Optional) The direction to scroll. Available directions are: `up`, `down`, `left`, `right`. Defaults to `down`. |
25
- | `distance` | `number` | (Optional) The maximum number of pixels to scroll before giving up. Default is `10000`. |
25
+ | `distance` | `number` | (Optional) The maximum number of scroll clicks before giving up. Default is `100`. |
26
26
  | `method` | `string` | (Optional) The method to use to scroll the page. Available methods are: `mouse` and `keyboard`. Defaults to `keyboard`. |
27
27
  | `path` | `string` | (Optional) The relative path to the image file that needs to be matched on the screen. |
28
28
  | `invert` | `boolean` | (Optional) If set to `true`, the command will scroll until the specified image is NOT detected. Default is `false`. |
@@ -23,7 +23,7 @@ The `scroll-until-text` command is used to scroll the screen in a specified dire
23
23
  | `text` | `string` | The text to find on the screen. Longer and unique are better. Note this is **case sensitive** |
24
24
  | `direction` | `string` | (Optional) The direction to scroll. Available directions are: `up`, `down`, `left`, `right`. Defaults to `down`. |
25
25
  | `method` | `string` | (Optional) The method to use to scroll the page. Available methods are: `mouse` and `keyboard`. Defaults to `keyboard`. |
26
- | `distance` | `number` | (Optional) The maximum number of pixels to scroll before giving up. Default is `10000`. |
26
+ | `distance` | `number` | (Optional) The maximum number of scroll clicks before giving up. Default is `100`. |
27
27
  | `invert` | `boolean` | (Optional) If set to `true`, the command will scroll until the specified text is NOT detected. Default is `false`. |
28
28
 
29
29
  <Note>
@@ -47,7 +47,7 @@ distance: 1000
47
47
 
48
48
  - Use unique and specific text to improve detection accuracy.
49
49
  - Adjust the `distance` value to control how far the command scrolls before giving up.
50
- - If you don't specify a `distance`, the command will scroll 300 pixels at a time, giving up after 5 attempts.
50
+ - If you don't specify a `distance`, the command will scroll 5 clicks at a time, giving up after reaching 100 clicks.
51
51
 
52
52
  ## Gotchas
53
53
 
@@ -22,7 +22,7 @@ The `scroll` command is used to scroll the screen in a specified direction using
22
22
  | :---------: | :------: | :------------------------------------------------------------------------------------ |
23
23
  | `direction` | `string` | The direction to scroll. Available directions are: `up`, `down`, `left`, `right`. |
24
24
  | `method` | `string` | The method to scroll. Available methods are: `mouse`, `keyboard`. Defaults to `mouse` |
25
- | `amount` | `number` | (Optional) Pixels to scroll. If not specified, a default amount of 300 is used. |
25
+ | `amount` | `number` | (Optional) Clicks (scroll wheel units) to scroll. If not specified, a default of 3 is used. |
26
26
 
27
27
  <Warning>
28
28
  The `amount` should only be used when the `method` is mouse. If the `method`
@@ -36,7 +36,7 @@ The `scroll` command is used to scroll the screen in a specified direction using
36
36
  - command: scroll
37
37
  direction: down
38
38
  method: mouse
39
- amount: 100
39
+ amount: 3
40
40
  ```
41
41
 
42
42
  ## Protips
@@ -364,10 +364,6 @@ await testdriver.scroll('left', 300);
364
364
  // Scroll methods
365
365
  await testdriver.scroll('down', 300, 'mouse'); // Mouse wheel (smooth)
366
366
  await testdriver.scroll('down', 300, 'keyboard'); // Page Down key
367
-
368
- // Scroll until text appears
369
- await testdriver.scrollUntilText('Contact Us');
370
- await testdriver.scrollUntilText('Footer', 'down', 5000);
371
367
  ```
372
368
 
373
369
  ### exec(language, code, timeout, silent) - Execute Code
@@ -117,18 +117,6 @@ await button.click();
117
117
 
118
118
  ## Actions
119
119
 
120
- ### Use Descriptive Prompts
121
-
122
- ```javascript
123
- // ❌ Generic
124
- await testdriver.ai('login');
125
-
126
- // ✅ Specific steps
127
- await testdriver.ai('click the username field and type user@example.com');
128
- await testdriver.ai('click the password field and type password123');
129
- await testdriver.ai('click the blue submit button');
130
- ```
131
-
132
120
  ### Chain Actions
133
121
 
134
122
  ```javascript
@@ -22,7 +22,7 @@ The `scroll-until-image` command is used to scroll the screen in a specified dir
22
22
  | :-----------: | :-------: | :---------------------------------------------------------------------------------------------------------------------- |
23
23
  | `description` | `string` | A description of the image and what it represents. |
24
24
  | `direction` | `string` | (Optional) The direction to scroll. Available directions are: `up`, `down`, `left`, `right`. Defaults to `down`. |
25
- | `distance` | `number` | (Optional) The maximum number of pixels to scroll before giving up. Default is `10000`. |
25
+ | `distance` | `number` | (Optional) The maximum number of scroll clicks before giving up. Default is `100`. |
26
26
  | `method` | `string` | (Optional) The method to use to scroll the page. Available methods are: `mouse` and `keyboard`. Defaults to `keyboard`. |
27
27
  | `path` | `string` | (Optional) The relative path to the image file that needs to be matched on the screen. |
28
28
  | `invert` | `boolean` | (Optional) If set to `true`, the command will scroll until the specified image is NOT detected. Default is `false`. |
@@ -23,7 +23,7 @@ The `scroll-until-text` command is used to scroll the screen in a specified dire
23
23
  | `text` | `string` | The text to find on the screen. Longer and unique are better. Note this is **case sensitive** |
24
24
  | `direction` | `string` | (Optional) The direction to scroll. Available directions are: `up`, `down`, `left`, `right`. Defaults to `down`. |
25
25
  | `method` | `string` | (Optional) The method to use to scroll the page. Available methods are: `mouse` and `keyboard`. Defaults to `keyboard`. |
26
- | `distance` | `number` | (Optional) The maximum number of pixels to scroll before giving up. Default is `10000`. |
26
+ | `distance` | `number` | (Optional) The maximum number of scroll clicks before giving up. Default is `100`. |
27
27
  | `invert` | `boolean` | (Optional) If set to `true`, the command will scroll until the specified text is NOT detected. Default is `false`. |
28
28
 
29
29
  <Note>
@@ -47,7 +47,7 @@ distance: 1000
47
47
 
48
48
  - Use unique and specific text to improve detection accuracy.
49
49
  - Adjust the `distance` value to control how far the command scrolls before giving up.
50
- - If you don't specify a `distance`, the command will scroll 300 pixels at a time, giving up after 5 attempts.
50
+ - If you don't specify a `distance`, the command will scroll 5 clicks at a time, giving up after reaching 100 clicks.
51
51
 
52
52
  ## Gotchas
53
53
 
@@ -22,7 +22,7 @@ The `scroll` command is used to scroll the screen in a specified direction using
22
22
  | :---------: | :------: | :------------------------------------------------------------------------------------ |
23
23
  | `direction` | `string` | The direction to scroll. Available directions are: `up`, `down`, `left`, `right`. |
24
24
  | `method` | `string` | The method to scroll. Available methods are: `mouse`, `keyboard`. Defaults to `mouse` |
25
- | `amount` | `number` | (Optional) Pixels to scroll. If not specified, a default amount of 300 is used. |
25
+ | `amount` | `number` | (Optional) Scroll clicks (wheel units). If not specified, a default amount of 3 is used. |
26
26
 
27
27
  <Warning>
28
28
  The `amount` should only be used when the `method` is mouse. If the `method`
@@ -205,18 +205,6 @@ const { testdriver, dashcam } = await electron(context, {
205
205
 
206
206
  ## Cache Configuration
207
207
 
208
- ### Prompt Cache
209
-
210
- Configure AI prompt caching:
211
-
212
- ```javascript
213
- // Disable prompt cache globally
214
- process.env.TD_NO_PROMPT_CACHE = 'true';
215
-
216
- // Per call
217
- await testdriver.ai('click button', false); // bypass cache
218
- ```
219
-
220
208
  ### Selector Cache
221
209
 
222
210
  Configure element location caching:
@@ -116,21 +116,13 @@ Features:
116
116
 
117
117
  ### How does caching work?
118
118
 
119
- Two types of caching:
120
-
121
- **1. Prompt Cache** - Caches AI-generated commands locally
122
- ```javascript
123
- await testdriver.ai('click button'); // AI call
124
- await testdriver.ai('click button'); // Uses cache
125
- ```
126
-
127
- **2. Selector Cache** - Caches element locations on server
119
+ **Selector Cache** - Caches element locations on server
128
120
  ```javascript
129
121
  await testdriver.find('button'); // AI vision
130
122
  await testdriver.find('button'); // Cache hit (95%+ similar UI)
131
123
  ```
132
124
 
133
- See [caching guide](/v7/guides/caching-ai) for details.
125
+ See [caching guide](/v7/caching) for details.
134
126
 
135
127
  ### Can I test responsive designs?
136
128
 
@@ -67,7 +67,6 @@ v7/
67
67
  - `pressKeys()` - Keyboard shortcuts and special keys
68
68
  - `click()` / `hover()` - Coordinate-based mouse actions
69
69
  - `scroll()` - Page scrolling
70
- - `scrollUntilText()` / `scrollUntilImage()` - Scroll until found
71
70
  - Keyboard key reference
72
71
 
73
72
  #### Assertions (`/v7/api/assertions.mdx`)
@@ -331,11 +331,8 @@ test('slow test', async () => {
331
331
 
332
332
  **2. Optimize test:**
333
333
  ```javascript
334
- // Use faster actions
334
+ // Use explicit actions
335
335
  await testdriver.find('button').then(el => el.click());
336
-
337
- // Instead of
338
- await testdriver.ai('click the button');
339
336
  ```
340
337
 
341
338
  ### Tests Fail in CI
@@ -313,4 +313,3 @@ describe('Assertions', () => {
313
313
 
314
314
  - [`extract()`](/v7/extract) - Extract information for detailed assertions
315
315
  - [`find()`](/v7/find) - Locate elements to verify
316
- - [`ai()`](/v7/ai) - Complex AI-driven tasks
@@ -193,7 +193,7 @@ Tests should use `context.ip || process.env.TD_IP` for the IP configuration:
193
193
 
194
194
  ```javascript
195
195
  import { describe, it } from "vitest";
196
- import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
196
+ import { TestDriver } from "testdriverai/vitest/hooks";
197
197
 
198
198
  describe("My Test", () => {
199
199
  it("should run on self-hosted instance", async (context) => {
@@ -1,11 +1,13 @@
1
1
  ---
2
- title: "Caching Prompts"
3
- description: "1.7x faster test execution with intelligent caching and optimization"
4
- icon: "bolt"
2
+ title: "Learn"
3
+ sidebarTitle: "Learn"
4
+ description: "How TestDriver learns your app and caches what it discovers for instant, deterministic replays"
5
+ icon: "brain"
5
6
  ---
6
7
 
7
- TestDriver is engineered for performance with intelligent caching that delivers up to **1.7x faster** test execution by skipping redundant AI vision analysis.
8
+ Once the agent has [explored your app](/v7/generating-tests), TestDriver remembers what it found. Every element the AI vision agent discovers is cached with a vision fingerprint—a perceptual hash of the screen state where it was located. On the next run, TestDriver matches against that cache instead of calling the AI again. Passing tests replay instantly, deterministically, and cheaply.
8
9
 
10
+ This learning is what makes TestDriver fast. Intelligent caching delivers up to **1.7x faster** test execution by skipping redundant AI vision analysis—the agent only thinks when it sees something new.
9
11
 
10
12
  ```javascript
11
13
  // First run: builds cache
@@ -17,7 +19,7 @@ await testdriver.find('submit button');
17
19
 
18
20
  ## Automatic Caching
19
21
 
20
- Caching is enabled automatically with zero configuration. The cache key is computed from:
22
+ Learning is enabled automatically with zero configuration. The cache key—the fingerprint TestDriver uses to recognize what it already knows—is computed from:
21
23
 
22
24
  - **File hash**: SHA-256 hash of the test file contents
23
25
  - **Selector prompt**: The exact text description passed to `find()`
@@ -53,7 +55,7 @@ You can clear the cache within the TestDriver console. There, you'll also find p
53
55
 
54
56
  ## Debugging Cache Hits and Misses
55
57
 
56
- You can track cache performance in your tests:
58
+ You can track what TestDriver has learned by inspecting cache performance in your tests:
57
59
 
58
60
  ```javascript
59
61
  test('monitor cache performance', async (context) => {
@@ -75,7 +77,7 @@ test('monitor cache performance', async (context) => {
75
77
 
76
78
  ## Configuring the Cache
77
79
 
78
- You can configure cache behavior globally when initializing TestDriver:
80
+ You can configure how TestDriver learns globally when initializing TestDriver:
79
81
 
80
82
  ```javascript
81
83
  import { TestDriver } from 'testdriverai';
@@ -103,7 +105,7 @@ await testdriver.find('submit button', {
103
105
 
104
106
  ## Caching with Variables
105
107
 
106
- Custom cache keys prevent cache pollution when using variables in prompts, dramatically improving cache hit rates.
108
+ Custom cache keys prevent cache pollution when using variables in prompts, dramatically improving cache hit rates—so TestDriver reuses what it learned even when your data changes.
107
109
 
108
110
  ```javascript
109
111
  // ❌ Without cache key - creates new cache for each variable value
@@ -123,6 +125,8 @@ await testdriver.find(`order ${orderId} status`, {
123
125
  });
124
126
  ```
125
127
 
128
+ ## Next
126
129
 
127
-
128
-
130
+ <Card href="/v7/copilot/running-tests" title="Run" icon="play">
131
+ Now that TestDriver has learned your app, run your tests in CI and locally—replaying the cache for fast, deterministic results.
132
+ </Card>
package/docs/v7/ci-cd.mdx CHANGED
@@ -7,29 +7,72 @@ icon: "code-branch"
7
7
 
8
8
  TestDriver integrates seamlessly with popular CI providers, enabling automated end-to-end testing on every push and pull request.
9
9
 
10
- ## Adding Your API Key
10
+ ## Authentication
11
11
 
12
- TestDriver requires an API key to authenticate with the TestDriver cloud. Store this securely as a secret in your CI provider.
12
+ On **GitHub Actions, prefer OIDC** via the published `testdriverai/action`
13
+ there's no `TD_API_KEY` secret to store, copy, or rotate. The action proves the
14
+ workflow is running inside your org and TestDriver exchanges that proof for your
15
+ team's key at run time. See the GitHub Actions tab below.
13
16
 
14
- <Steps>
15
- <Step title="Get Your API Key">
16
- Go to [console.testdriver.ai/team](https://console.testdriver.ai/team) and copy your team's API key
17
- </Step>
18
- <Step title="Add Secret to Your CI Provider">
19
- Add `TD_API_KEY` as a secret environment variable in your CI provider's settings.
20
- </Step>
21
- </Steps>
17
+ For other CI providers (or self-hosted runners without OIDC), fall back to a
18
+ stored API key from [console.testdriver.ai/team](https://console.testdriver.ai/team),
19
+ added as a `TD_API_KEY` secret in your CI provider's settings.
22
20
 
23
21
  <Note>
24
- Never commit your API key directly in code. Always use your CI provider's secrets management.
22
+ Never commit your API key directly in code. Always use OIDC or your CI provider's secrets management.
25
23
  </Note>
26
24
 
27
25
  ## CI Provider Examples
28
26
 
29
27
  <Tabs>
30
28
  <Tab title="GitHub Actions">
31
- ### Adding Secrets
32
-
29
+ ### Authenticate with OIDC via `testdriverai/action` (recommended)
30
+
31
+ Use the published [`testdriverai/action`](https://github.com/testdriverai/action) — it mints the OIDC token, exchanges it for your team's API key, and exports `TD_API_KEY` for the steps that follow. **No `TD_API_KEY` secret to store or rotate.**
32
+
33
+ <Note>
34
+ One-time setup: authorize the [TestDriver GitHub App](https://console.testdriver.ai) for your org so the org → team binding exists. If your org authorized the App before OIDC support shipped, re-authorize once. If the App isn't authorized, the action fails with a console link (or falls back to the `api-key` secret if you provide one).
35
+ </Note>
36
+
37
+ ```yaml .github/workflows/testdriver.yml
38
+ name: TestDriver Tests
39
+
40
+ on:
41
+ push:
42
+ branches: [main]
43
+ pull_request:
44
+ branches: [main]
45
+
46
+ jobs:
47
+ test:
48
+ runs-on: ubuntu-latest
49
+ permissions:
50
+ id-token: write # REQUIRED to mint an OIDC token
51
+ contents: read
52
+
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+
56
+ - uses: actions/setup-node@v4
57
+ with:
58
+ node-version: '20'
59
+ cache: 'npm'
60
+
61
+ - run: npm ci
62
+
63
+ - name: Authenticate to TestDriver
64
+ uses: testdriverai/action@stable # pin @stable / @canary / @test to your SDK channel
65
+ with:
66
+ api-key: ${{ secrets.TD_API_KEY }} # optional fallback if OIDC isn't set up
67
+
68
+ - name: Run TestDriver tests
69
+ run: npx vitest run
70
+ ```
71
+
72
+ ### Stored-key fallback
73
+
74
+ Only if you can't use OIDC (e.g. self-hosted runners without an OIDC provider). Add the key as a secret and pass it via `env`:
75
+
33
76
  1. Navigate to your GitHub repository
34
77
  2. Go to **Settings** → **Secrets and variables** → **Actions**
35
78
  3. Click **New repository secret**
@@ -572,7 +615,7 @@ When using multi-platform testing, read the `TD_OS` environment variable in your
572
615
 
573
616
  ```javascript tests/cross-platform.test.mjs
574
617
  import { describe, expect, it } from "vitest";
575
- import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
618
+ import { TestDriver } from "testdriverai/vitest/hooks";
576
619
 
577
620
  describe("Cross-platform tests", () => {
578
621
  it("should work on both Linux and Windows", async (context) => {
@@ -592,6 +635,47 @@ describe("Cross-platform tests", () => {
592
635
  });
593
636
  ```
594
637
 
638
+ ## Concurrency limits
639
+
640
+ Your plan allows a fixed number of sandboxes running at once. When a test asks for
641
+ a sandbox and you're already at that limit, the request is **queued** rather than
642
+ failed immediately: the SDK waits for a slot to free up, retrying every 10 seconds,
643
+ then proceeds automatically once one opens. This is what lets a parallel CI matrix
644
+ (many jobs starting at once) work on a plan with fewer slots than jobs — the extra
645
+ jobs simply wait their turn instead of erroring.
646
+
647
+ By default the SDK waits up to **60 seconds** for a slot before giving up with a
648
+ concurrency-limit error. Control that ceiling with `TD_CONCURRENCY_MAX_WAIT`:
649
+
650
+ | Value | Behavior |
651
+ | ----- | -------- |
652
+ | _unset_ | Wait up to **60 seconds** (the default). |
653
+ | `TD_CONCURRENCY_MAX_WAIT=300` | Wait up to **300 seconds** (5 minutes) before giving up. |
654
+ | `TD_CONCURRENCY_MAX_WAIT=0` | **Don't queue** — fail on the first denial. |
655
+
656
+ The value is **in seconds** (fractional values are allowed and rounded to the
657
+ nearest millisecond). Any invalid or negative value falls back to the 60-second
658
+ default. The wait applies per sandbox request, across both the initial allocation
659
+ and the realtime slot-approval handshake.
660
+
661
+ ```yaml
662
+ # Example: a large parallel matrix that may queue for a while.
663
+ # Give each job up to 5 minutes to acquire a slot before failing.
664
+ - name: Run TestDriver tests
665
+ env:
666
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
667
+ TD_CONCURRENCY_MAX_WAIT: "300"
668
+ run: npx vitest run
669
+ ```
670
+
671
+ <Tip>
672
+ Raise `TD_CONCURRENCY_MAX_WAIT` when you run more parallel jobs than your plan has
673
+ slots and would rather they queue than fail. Set it to `0` when you'd prefer a job
674
+ to **fail fast** on a busy account (e.g. a quick smoke test that shouldn't sit
675
+ waiting). When jobs routinely give up waiting, that's the signal to
676
+ [add more slots](https://console.testdriver.ai/checkout/pro).
677
+ </Tip>
678
+
595
679
  ## Viewing Results
596
680
 
597
681
  All test runs are automatically recorded and visible in your TestDriver dashboard at [console.testdriver.ai](https://console.testdriver.ai):
@@ -30,7 +30,7 @@ const testdriver = new TestDriver(apiKey, options)
30
30
  </ParamField>
31
31
 
32
32
  <ParamField path="resolution" type="string" default="1366x768">
33
- Screen resolution for the sandbox (e.g., `'1920x1080'`, `'1366x768'`)
33
+ Screen resolution for the sandbox (e.g., `'1920x1080'`, `'1366x768'`). Custom resolutions are only available on Enterprise plans.
34
34
  </ParamField>
35
35
 
36
36
  <ParamField path="apiRoot" type="string">
@@ -45,7 +45,7 @@ const testdriver = new TestDriver(apiKey, options)
45
45
  Enable or disable console logging
46
46
  </ParamField>
47
47
 
48
- <ParamField path="autoScreenshots" type="boolean" default="true">
48
+ <ParamField path="autoScreenshots" type="boolean" default="false">
49
49
  Automatically capture screenshots before and after each command. Screenshots are saved to `.testdriver/screenshots/<test>/` with descriptive filenames that include the line number and action name. Format: `<seq>-<action>-<phase>-L<line>-<description>.png`
50
50
  </ParamField>
51
51
 
@@ -54,11 +54,11 @@ const testdriver = new TestDriver(apiKey, options)
54
54
  </ParamField>
55
55
 
56
56
  <ParamField path="reconnect" type="boolean" default="false">
57
- Reconnect to the last used sandbox instead of creating a new one. When `true`, provision methods (`chrome`, `vscode`, `installer`, etc.) will be skipped since the application is already running. Throws error if no previous sandbox exists.
57
+ Reattach to the last used sandbox instead of creating a new one. When `true`, the SDK reads the sandbox id from `.testdriver/last-sandbox` (written automatically on every successful connect) and rejoins that VM. Provision methods (`chrome`, `vscode`, `installer`, etc.) are skipped because the application is already running. The previous sandbox must still be alive — see [`keepAlive`](#keepalive) and the [Run guide](/v7/copilot/running-tests#keeping-machines-alive-between-runs).
58
58
  </ParamField>
59
-
60
- <ParamField path="keepAlive" type="number" default="60000">
61
- Keep sandbox alive for the specified number of milliseconds after disconnect. Set to `0` to terminate immediately on disconnect. Useful for debugging or reconnecting to the same sandbox.
59
+
60
+ <ParamField path="sandboxId" type="string">
61
+ Reattach to a specific sandbox id instead of the one recorded in `.testdriver/last-sandbox`. Use this for CI matrices or to pin a chain of tests to a known VM. Implies `reconnect: true` behavior (provision calls are skipped).
62
62
  </ParamField>
63
63
 
64
64
  <ParamField path="preview" type="string" default="browser">
@@ -275,6 +275,10 @@ await testdriver.connect(options)
275
275
  <ParamField path="headless" type="boolean" default="false">
276
276
  **Deprecated**: Use `preview: "none"` instead. Run in headless mode without opening the debugger.
277
277
  </ParamField>
278
+
279
+ <ParamField path="keepAlive" type="number" default="60000">
280
+ Keep sandbox alive for the specified number of milliseconds after disconnect. Set to `0` to terminate immediately on disconnect. Useful for debugging or reconnecting to the same sandbox.
281
+ </ParamField>
278
282
  </Expandable>
279
283
  </ParamField>
280
284