testdriverai 6.2.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/.github/workflows/acceptance-linux.yml +75 -0
  2. package/.github/workflows/acceptance-sdk-tests.yml +133 -0
  3. package/.vscode/settings.json +5 -1
  4. package/MIGRATION.md +389 -0
  5. package/PLUGIN_MIGRATION.md +222 -0
  6. package/PROMPT_CACHE.md +200 -0
  7. package/SDK_LOGGING.md +222 -0
  8. package/SDK_MIGRATION.md +474 -0
  9. package/SDK_README.md +1122 -0
  10. package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
  11. package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
  12. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  13. package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
  14. package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
  15. package/_testdriver/lifecycle/prerun.yaml +15 -0
  16. package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
  17. package/agent/index.js +258 -68
  18. package/agent/interface.js +15 -0
  19. package/agent/lib/cache.js +142 -0
  20. package/agent/lib/commander.js +1 -39
  21. package/agent/lib/commands.js +143 -188
  22. package/agent/lib/redraw.js +6 -3
  23. package/agent/lib/sandbox.js +19 -5
  24. package/agent/lib/sdk.js +1 -0
  25. package/agent/lib/system.js +0 -3
  26. package/agent/lib/validation.js +1 -7
  27. package/debug-locate-response.js +82 -0
  28. package/debug-screenshot-1763401388589.png +0 -0
  29. package/debugger/index.html +16 -5
  30. package/docs/ARCHITECTURE.md +424 -0
  31. package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
  32. package/docs/QUICK_START_TEST_RECORDING.md +215 -0
  33. package/docs/SDK_AWESOME_LOGS.md +468 -0
  34. package/docs/TEST_RECORDING.md +388 -0
  35. package/docs/docs.json +232 -152
  36. package/docs/sdk-browser-rendering.md +167 -0
  37. package/docs/v6/getting-started/self-hosting.mdx +407 -0
  38. package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
  39. package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
  40. package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
  41. package/docs/v6/overview/comparison.mdx +101 -0
  42. package/docs/v7/README.md +135 -0
  43. package/docs/v7/api/ai.mdx +205 -0
  44. package/docs/v7/api/assert.mdx +285 -0
  45. package/docs/v7/api/assertions.mdx +403 -0
  46. package/docs/v7/api/click.mdx +287 -0
  47. package/docs/v7/api/client.mdx +322 -0
  48. package/docs/v7/api/elements.mdx +479 -0
  49. package/docs/v7/api/exec.mdx +346 -0
  50. package/docs/v7/api/find.mdx +316 -0
  51. package/docs/v7/api/focusApplication.mdx +294 -0
  52. package/docs/v7/api/hover.mdx +279 -0
  53. package/docs/v7/api/pressKeys.mdx +349 -0
  54. package/docs/v7/api/sandbox.mdx +404 -0
  55. package/docs/v7/api/scroll.mdx +300 -0
  56. package/docs/v7/api/type.mdx +314 -0
  57. package/docs/v7/commands/assert.mdx +45 -0
  58. package/docs/v7/commands/exec.mdx +282 -0
  59. package/docs/v7/commands/focus-application.mdx +44 -0
  60. package/docs/v7/commands/hover-image.mdx +69 -0
  61. package/docs/v7/commands/hover-text.mdx +47 -0
  62. package/docs/v7/commands/if.mdx +53 -0
  63. package/docs/v7/commands/match-image.mdx +67 -0
  64. package/docs/v7/commands/press-keys.mdx +87 -0
  65. package/docs/v7/commands/remember.mdx +49 -0
  66. package/docs/v7/commands/run.mdx +44 -0
  67. package/docs/v7/commands/scroll-until-image.mdx +66 -0
  68. package/docs/v7/commands/scroll-until-text.mdx +60 -0
  69. package/docs/v7/commands/scroll.mdx +69 -0
  70. package/docs/v7/commands/type.mdx +45 -0
  71. package/docs/v7/commands/wait-for-image.mdx +54 -0
  72. package/docs/v7/commands/wait-for-text.mdx +48 -0
  73. package/docs/v7/commands/wait.mdx +45 -0
  74. package/docs/v7/getting-started/quickstart.mdx +199 -0
  75. package/docs/v7/guides/migration.mdx +562 -0
  76. package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
  77. package/docs/v7/playwright.mdx +342 -0
  78. package/eslint.config.js +19 -1
  79. package/examples/run-tests-with-recording.sh +70 -0
  80. package/examples/screenshot-example.js +63 -0
  81. package/examples/sdk-awesome-logs-demo.js +177 -0
  82. package/examples/sdk-cache-thresholds.js +96 -0
  83. package/examples/sdk-element-properties.js +155 -0
  84. package/examples/sdk-simple-example.js +65 -0
  85. package/examples/test-recording-example.test.js +166 -0
  86. package/interfaces/cli/lib/base.js +10 -4
  87. package/interfaces/logger.js +2 -1
  88. package/interfaces/shared-test-state.mjs +69 -0
  89. package/interfaces/vitest-plugin.mjs +744 -0
  90. package/mcp-server/AI_GUIDELINES.md +57 -0
  91. package/package.json +18 -5
  92. package/schema.json +8 -29
  93. package/scripts/view-test-results.mjs +96 -0
  94. package/sdk-log-formatter.js +714 -0
  95. package/sdk.d.ts +735 -0
  96. package/sdk.js +1906 -0
  97. package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
  98. package/setup/aws/cloudformation.yaml +9 -2
  99. package/test/mcp-example-test.yaml +27 -0
  100. package/test-find-api.js +73 -0
  101. package/test-prompt-cache.js +96 -0
  102. package/test-sandbox-render.js +28 -0
  103. package/test-sdk-methods.js +15 -0
  104. package/test-sdk-refactor.js +53 -0
  105. package/test-stack-trace.mjs +57 -0
  106. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
  107. package/testdriver/acceptance-sdk/README.md +128 -0
  108. package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
  109. package/testdriver/acceptance-sdk/assert.test.mjs +44 -0
  110. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +70 -0
  111. package/testdriver/acceptance-sdk/element-not-found.test.mjs +38 -0
  112. package/testdriver/acceptance-sdk/exec-js.test.mjs +55 -0
  113. package/testdriver/acceptance-sdk/exec-output.test.mjs +71 -0
  114. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +69 -0
  115. package/testdriver/acceptance-sdk/focus-window.test.mjs +48 -0
  116. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +41 -0
  117. package/testdriver/acceptance-sdk/hover-image.test.mjs +43 -0
  118. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +50 -0
  119. package/testdriver/acceptance-sdk/hover-text.test.mjs +41 -0
  120. package/testdriver/acceptance-sdk/match-image.test.mjs +48 -0
  121. package/testdriver/acceptance-sdk/press-keys.test.mjs +64 -0
  122. package/testdriver/acceptance-sdk/prompt.test.mjs +45 -0
  123. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +52 -0
  124. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +51 -0
  125. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +42 -0
  126. package/testdriver/acceptance-sdk/scroll.test.mjs +50 -0
  127. package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
  128. package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +239 -0
  129. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +648 -0
  130. package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
  131. package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
  132. package/testdriver/acceptance-sdk/type.test.mjs +84 -0
  133. package/verify-element-api.js +89 -0
  134. package/verify-types.js +0 -0
  135. package/vitest.config.example.js +19 -0
  136. package/vitest.config.mjs +65 -0
  137. package/vitest.config.mjs.bak +44 -0
  138. package/.github/workflows/acceptance-v6.yml +0 -169
  139. package/docs/overview/comparison.mdx +0 -82
  140. package/testdriver/lifecycle/prerun.yaml +0 -17
  141. /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
  142. /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
  143. /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
  144. /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
  145. /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
  146. /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
  147. /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
  148. /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
  149. /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
  150. /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
  151. /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
  152. /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
  153. /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
  154. /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
  155. /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
  156. /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
  157. /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
  158. /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
  159. /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
  160. /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
  161. /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
  162. /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
  163. /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
  164. /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
  165. /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
  166. /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
  167. /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
  168. /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
  169. /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
  170. /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
  171. /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
  172. /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
  173. /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
  174. /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
  175. /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
  176. /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
  177. /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
  178. /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
  179. /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
  180. /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
  181. /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
  182. /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
  183. /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
  184. /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
  185. /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
  186. /package/docs/{account → v6/account}/dashboard.mdx +0 -0
  187. /package/docs/{account → v6/account}/enterprise.mdx +0 -0
  188. /package/docs/{account → v6/account}/pricing.mdx +0 -0
  189. /package/docs/{account → v6/account}/projects.mdx +0 -0
  190. /package/docs/{account → v6/account}/team.mdx +0 -0
  191. /package/docs/{action → v6/action}/ami.mdx +0 -0
  192. /package/docs/{action → v6/action}/performance.mdx +0 -0
  193. /package/docs/{action → v6/action}/secrets.mdx +0 -0
  194. /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
  195. /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
  196. /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
  197. /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
  198. /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
  199. /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
  200. /package/docs/{cli → v6/cli}/overview.mdx +0 -0
  201. /package/docs/{commands → v6/commands}/assert.mdx +0 -0
  202. /package/docs/{commands → v6/commands}/exec.mdx +0 -0
  203. /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
  204. /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
  205. /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
  206. /package/docs/{commands → v6/commands}/if.mdx +0 -0
  207. /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
  208. /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
  209. /package/docs/{commands → v6/commands}/remember.mdx +0 -0
  210. /package/docs/{commands → v6/commands}/run.mdx +0 -0
  211. /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
  212. /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
  213. /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
  214. /package/docs/{commands → v6/commands}/type.mdx +0 -0
  215. /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
  216. /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
  217. /package/docs/{commands → v6/commands}/wait.mdx +0 -0
  218. /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
  219. /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
  220. /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
  221. /package/docs/{features → v6/features}/generation.mdx +0 -0
  222. /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
  223. /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
  224. /package/docs/{features → v6/features}/selectorless.mdx +0 -0
  225. /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
  226. /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
  227. /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
  228. /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
  229. /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
  230. /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
  231. /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
  232. /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
  233. /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
  234. /package/docs/{guide → v6/guide}/code.mdx +0 -0
  235. /package/docs/{guide → v6/guide}/locating.mdx +0 -0
  236. /package/docs/{guide → v6/guide}/protips.mdx +0 -0
  237. /package/docs/{guide → v6/guide}/variables.mdx +0 -0
  238. /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
  239. /package/docs/{importing → v6/importing}/csv.mdx +0 -0
  240. /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
  241. /package/docs/{importing → v6/importing}/jira.mdx +0 -0
  242. /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
  243. /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
  244. /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
  245. /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
  246. /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
  247. /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
  248. /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
  249. /package/docs/{overview → v6/overview}/faq.mdx +0 -0
  250. /package/docs/{overview → v6/overview}/performance.mdx +0 -0
  251. /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
  252. /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
  253. /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
  254. /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
  255. /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
  256. /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
  257. /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
  258. /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
  259. /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
  260. /package/docs/{security → v6/security}/action.mdx +0 -0
  261. /package/docs/{security → v6/security}/agent.mdx +0 -0
  262. /package/docs/{security → v6/security}/platform.mdx +0 -0
  263. /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
  264. /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
@@ -0,0 +1,562 @@
1
+ ---
2
+ title: "Migration Guide"
3
+ sidebarTitle: "YAML to SDK"
4
+ description: "Migrate from YAML tests to the JavaScript SDK"
5
+ icon: "right-left"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ TestDriver v7 introduces a JavaScript SDK that provides programmatic access to all TestDriver capabilities. This guide helps you migrate from YAML-based tests to the SDK.
11
+
12
+ ## Why Migrate?
13
+
14
+ The SDK offers several advantages over YAML:
15
+
16
+ - **Type Safety**: Full TypeScript support with autocomplete
17
+ - **Programmatic Control**: Use variables, loops, functions, and conditional logic
18
+ - **Better Debugging**: Stack traces point to your actual code
19
+ - **IDE Integration**: Better editor support and refactoring
20
+ - **Test Framework Integration**: Works with Vitest, Jest, Mocha, and more
21
+ - **Flexibility**: Combine with other testing libraries and tools
22
+
23
+ ## Basic Structure Comparison
24
+
25
+ ### YAML Test
26
+
27
+ ```yaml
28
+ version: 6.0.0
29
+ steps:
30
+ - prompt: focus chrome
31
+ commands:
32
+ - command: focus-application
33
+ name: Google Chrome
34
+
35
+ - prompt: enter username
36
+ commands:
37
+ - command: hover-text
38
+ text: Username
39
+ description: username input field
40
+ action: click
41
+ - command: type
42
+ text: standard_user
43
+
44
+ - prompt: verify login page
45
+ commands:
46
+ - command: assert
47
+ assertion: the login page is displayed
48
+ ```
49
+
50
+ ### SDK Equivalent
51
+
52
+ ```javascript
53
+ import { beforeAll, afterAll, describe, it } from 'vitest';
54
+ import TestDriver from 'testdriverai';
55
+
56
+ describe('Login Test', () => {
57
+ let testdriver;
58
+
59
+ beforeAll(async () => {
60
+ client = new TestDriver(process.env.TD_API_KEY, {
61
+ os: 'windows'
62
+ });
63
+ await testdriver.auth();
64
+ await testdriver.connect({ newSandbox: true });
65
+ });
66
+
67
+ afterAll(async () => {
68
+ await testdriver.disconnect();
69
+ });
70
+
71
+ it('should display login page and accept credentials', async () => {
72
+ // Focus chrome
73
+ await testdriver.focusApplication('Google Chrome');
74
+
75
+ // Enter username
76
+ const usernameField = await testdriver.find('username input field');
77
+ await usernameField.click();
78
+ await testdriver.type('standard_user');
79
+
80
+ // Verify login page
81
+ await testdriver.assert('the login page is displayed');
82
+ });
83
+ });
84
+ ```
85
+
86
+ ## Command Mapping
87
+
88
+ ### Element Location
89
+
90
+ <CodeGroup>
91
+ ```yaml YAML
92
+ - command: hover-text
93
+ text: Submit
94
+ description: submit button
95
+ action: click
96
+ ```
97
+
98
+ ```javascript SDK
99
+ const button = await testdriver.find('submit button');
100
+ await button.click();
101
+ ```
102
+ </CodeGroup>
103
+
104
+ ### Typing
105
+
106
+ <CodeGroup>
107
+ ```yaml YAML
108
+ - command: type
109
+ text: hello world
110
+ delay: 250
111
+ ```
112
+
113
+ ```javascript SDK
114
+ await testdriver.type('hello world', 250);
115
+ ```
116
+ </CodeGroup>
117
+
118
+ ### Keyboard Keys
119
+
120
+ <CodeGroup>
121
+ ```yaml YAML
122
+ - command: press-keys
123
+ keys:
124
+ - ctrl
125
+ - a
126
+ ```
127
+
128
+ ```javascript SDK
129
+ await testdriver.pressKeys(['ctrl', 'a']);
130
+ ```
131
+ </CodeGroup>
132
+
133
+ ### Scrolling
134
+
135
+ <CodeGroup>
136
+ ```yaml YAML
137
+ - command: scroll
138
+ direction: down
139
+ amount: 300
140
+ method: mouse
141
+ ```
142
+
143
+ ```javascript SDK
144
+ await testdriver.scroll('down', 300, 'mouse');
145
+ ```
146
+ </CodeGroup>
147
+
148
+ ### Assertions
149
+
150
+ <CodeGroup>
151
+ ```yaml YAML
152
+ - command: assert
153
+ assertion: the form is valid
154
+ ```
155
+
156
+ ```javascript SDK
157
+ await testdriver.assert('the form is valid');
158
+ ```
159
+ </CodeGroup>
160
+
161
+ ### Wait for Element
162
+
163
+ <CodeGroup>
164
+ ```yaml YAML
165
+ - command: wait-for-text
166
+ text: Success
167
+ timeout: 10000
168
+ ```
169
+
170
+ ```javascript SDK
171
+ // Use polling pattern
172
+ let element;
173
+ for (let i = 0; i < 10; i++) {
174
+ element = await testdriver.find('Success');
175
+ if (element.found()) break;
176
+ await new Promise(r => setTimeout(r, 1000));
177
+ }
178
+ ```
179
+ </CodeGroup>
180
+
181
+ ### Code Execution
182
+
183
+ <CodeGroup>
184
+ ```yaml YAML
185
+ - command: exec
186
+ language: pwsh
187
+ code: |
188
+ npm install -g package
189
+ timeout: 30000
190
+ ```
191
+
192
+ ```javascript SDK
193
+ await testdriver.exec('pwsh', 'npm install -g package', 30000);
194
+ ```
195
+ </CodeGroup>
196
+
197
+ ### Focus Application
198
+
199
+ <CodeGroup>
200
+ ```yaml YAML
201
+ - command: focus-application
202
+ name: Google Chrome
203
+ ```
204
+
205
+ ```javascript SDK
206
+ await testdriver.focusApplication('Google Chrome');
207
+ ```
208
+ </CodeGroup>
209
+
210
+ ### Remember
211
+
212
+ <CodeGroup>
213
+ ```yaml YAML
214
+ - command: remember
215
+ description: the order number
216
+ ```
217
+
218
+ ```javascript SDK
219
+ const orderNumber = await testdriver.remember('the order number');
220
+ ```
221
+ </CodeGroup>
222
+
223
+ ## Advanced Patterns
224
+
225
+ ### Variables & Data Reuse
226
+
227
+ **YAML** uses template variables:
228
+ ```yaml
229
+ variables:
230
+ username: john.doe
231
+ password: secret123
232
+
233
+ steps:
234
+ - command: type
235
+ text: ${username}
236
+ ```
237
+
238
+ **SDK** uses JavaScript variables:
239
+ ```javascript
240
+ const username = 'john.doe';
241
+ const password = 'secret123';
242
+
243
+ await testdriver.type(username);
244
+ ```
245
+
246
+ ### Conditional Logic
247
+
248
+ **YAML** uses if command:
249
+ ```yaml
250
+ - command: if
251
+ condition: error message is visible
252
+ then:
253
+ - command: assert
254
+ assertion: error message is correct
255
+ else:
256
+ - command: assert
257
+ assertion: form submitted successfully
258
+ ```
259
+
260
+ **SDK** uses native JavaScript:
261
+ ```javascript
262
+ const errorElement = await testdriver.find('error message');
263
+
264
+ if (errorElement.found()) {
265
+ await testdriver.assert('error message is correct');
266
+ } else {
267
+ await testdriver.assert('form submitted successfully');
268
+ }
269
+ ```
270
+
271
+ ### Loops
272
+
273
+ **YAML** requires workarounds or snippets for repetition.
274
+
275
+ **SDK** uses native JavaScript loops:
276
+ ```javascript
277
+ // Fill multiple similar fields
278
+ const fields = ['First Name', 'Last Name', 'Email'];
279
+ const values = ['John', 'Doe', 'john@example.com'];
280
+
281
+ for (let i = 0; i < fields.length; i++) {
282
+ const field = await testdriver.find(`${fields[i]} input field`);
283
+ await field.click();
284
+ await testdriver.type(values[i]);
285
+ }
286
+ ```
287
+
288
+ ### Data-Driven Tests
289
+
290
+ **YAML** requires external tools or CSV imports.
291
+
292
+ **SDK** uses test framework features:
293
+ ```javascript
294
+ const testCases = [
295
+ { username: 'user1', password: 'pass1', expected: true },
296
+ { username: 'user2', password: 'wrong', expected: false },
297
+ { username: '', password: '', expected: false },
298
+ ];
299
+
300
+ testCases.forEach(({ username, password, expected }) => {
301
+ it(`should handle login for ${username}`, async () => {
302
+ const usernameField = await testdriver.find('username field');
303
+ await usernameField.click();
304
+ await testdriver.type(username);
305
+
306
+ const passwordField = await testdriver.find('password field');
307
+ await passwordField.click();
308
+ await testdriver.type(password);
309
+
310
+ const submitButton = await testdriver.find('submit button');
311
+ await submitButton.click();
312
+
313
+ if (expected) {
314
+ await testdriver.assert('login successful');
315
+ } else {
316
+ await testdriver.assert('error message is shown');
317
+ }
318
+ });
319
+ });
320
+ ```
321
+
322
+ ## Lifecycle Hooks
323
+
324
+ ### YAML Lifecycle
325
+
326
+ ```yaml
327
+ prerun: lifecycle/prerun.yaml
328
+ postrun: lifecycle/postrun.yaml
329
+
330
+ steps:
331
+ # test steps
332
+ ```
333
+
334
+ ### SDK Lifecycle
335
+
336
+ ```javascript
337
+ describe('My Tests', () => {
338
+ let testdriver;
339
+
340
+ beforeAll(async () => {
341
+ client = new TestDriver(process.env.TD_API_KEY);
342
+ await testdriver.auth();
343
+ await testdriver.connect();
344
+
345
+ // Prerun logic
346
+ await testdriver.exec('pwsh', 'npm ls dashcam -g', 30000);
347
+ await testdriver.exec('pwsh', 'dashcam start', 5000);
348
+ });
349
+
350
+ afterAll(async () => {
351
+ // Postrun logic
352
+ const dashcamUrl = await testdriver.exec('pwsh', 'dashcam -p', 10000);
353
+ console.log('Recording:', dashcamUrl);
354
+
355
+ await testdriver.disconnect();
356
+ });
357
+
358
+ // Tests here
359
+ });
360
+ ```
361
+
362
+ ## Migration Checklist
363
+
364
+ <Steps>
365
+ <Step title="Set up project">
366
+ ```bash
367
+ npm install testdriverai vitest
368
+ ```
369
+ </Step>
370
+
371
+ <Step title="Create test file">
372
+ Create a new `.test.mjs` or `.test.js` file for each YAML test file.
373
+ </Step>
374
+
375
+ <Step title="Initialize client">
376
+ Add `beforeAll` and `afterAll` hooks to set up the TestDriver testdriver.
377
+ </Step>
378
+
379
+ <Step title="Convert commands">
380
+ Use the command mapping above to convert each YAML command to SDK calls.
381
+ </Step>
382
+
383
+ <Step title="Add assertions">
384
+ Use your test framework's assertions (`expect()`) along with TestDriver's AI assertions.
385
+ </Step>
386
+
387
+ <Step title="Test incrementally">
388
+ Run tests frequently during migration to catch issues early.
389
+ </Step>
390
+ </Steps>
391
+
392
+ ## Common Pitfalls
393
+
394
+ <Warning>
395
+ **Element must be found before interaction**
396
+
397
+ The `find()` method automatically locates elements, but you should check if it was found:
398
+
399
+ ```javascript
400
+ const element = await testdriver.find('button');
401
+ if (!element.found()) {
402
+ throw new Error('Element not found');
403
+ }
404
+ await element.click();
405
+ ```
406
+ </Warning>
407
+
408
+ <Warning>
409
+ **Always call disconnect()**
410
+
411
+ Use `afterAll` to ensure sandboxes are cleaned up:
412
+
413
+ ```javascript
414
+ afterAll(async () => {
415
+ await testdriver.disconnect();
416
+ });
417
+ ```
418
+ </Warning>
419
+
420
+ <Warning>
421
+ **Async/await is required**
422
+
423
+ All SDK methods return Promises and must be awaited:
424
+
425
+ ```javascript
426
+ // ❌ Wrong
427
+ testdriver.type('hello');
428
+
429
+ // ✅ Correct
430
+ await testdriver.type('hello');
431
+ ```
432
+ </Warning>
433
+
434
+ ## Example: Complete Migration
435
+
436
+ ### Before (YAML)
437
+
438
+ ```yaml
439
+ version: 6.0.0
440
+
441
+ variables:
442
+ username: standard_user
443
+
444
+ prerun: lifecycle/prerun.yaml
445
+ postrun: lifecycle/postrun.yaml
446
+
447
+ steps:
448
+ - prompt: focus chrome
449
+ commands:
450
+ - command: focus-application
451
+ name: Google Chrome
452
+
453
+ - prompt: fill login form
454
+ commands:
455
+ - command: hover-text
456
+ text: Username
457
+ action: click
458
+ - command: type
459
+ text: ${username}
460
+ - command: press-keys
461
+ keys: [tab]
462
+ - command: type
463
+ text: secret_sauce
464
+
465
+ - prompt: submit form
466
+ commands:
467
+ - command: press-keys
468
+ keys: [enter]
469
+
470
+ - prompt: verify success
471
+ commands:
472
+ - command: assert
473
+ assertion: products page is displayed
474
+ ```
475
+
476
+ ### After (SDK)
477
+
478
+ ```javascript
479
+ import { beforeAll, afterAll, describe, it, expect } from 'vitest';
480
+ import TestDriver from 'testdriverai';
481
+
482
+ describe('Login Flow', () => {
483
+ let testdriver;
484
+ const username = 'standard_user';
485
+
486
+ beforeAll(async () => {
487
+ client = new TestDriver(process.env.TD_API_KEY, {
488
+ os: 'windows'
489
+ });
490
+
491
+ await testdriver.auth();
492
+ await testdriver.connect({ newSandbox: true });
493
+
494
+ // Prerun
495
+ await testdriver.exec('pwsh', 'dashcam start', 5000, true);
496
+ });
497
+
498
+ afterAll(async () => {
499
+ // Postrun
500
+ const url = await testdriver.exec('pwsh', 'dashcam -p', 10000);
501
+ console.log('Recording:', url);
502
+
503
+ await testdriver.disconnect();
504
+ });
505
+
506
+ it('should login successfully', async () => {
507
+ // Focus chrome
508
+ await testdriver.focusApplication('Google Chrome');
509
+
510
+ // Fill login form
511
+ const usernameField = await testdriver.find('Username input field');
512
+ await usernameField.click();
513
+ await testdriver.type(username);
514
+
515
+ await testdriver.pressKeys(['tab']);
516
+ await testdriver.type('secret_sauce');
517
+
518
+ // Submit form
519
+ await testdriver.pressKeys(['enter']);
520
+
521
+ // Verify success
522
+ const result = await testdriver.assert('products page is displayed');
523
+ expect(result).toBeTruthy();
524
+ });
525
+ });
526
+ ```
527
+
528
+ ## Next Steps
529
+
530
+ <CardGroup cols={2}>
531
+ <Card
532
+ title="API Reference"
533
+ icon="book"
534
+ href="/v7/api/client"
535
+ >
536
+ Explore all available SDK methods
537
+ </Card>
538
+
539
+ <Card
540
+ title="Examples"
541
+ icon="code"
542
+ href="/v7/guides/examples"
543
+ >
544
+ See complete test examples
545
+ </Card>
546
+
547
+ <Card
548
+ title="Best Practices"
549
+ icon="star"
550
+ href="/v7/guides/best-practices"
551
+ >
552
+ Learn SDK best practices
553
+ </Card>
554
+
555
+ <Card
556
+ title="Quickstart"
557
+ icon="rocket"
558
+ href="/v7/getting-started/quickstart"
559
+ >
560
+ Get started with the SDK
561
+ </Card>
562
+ </CardGroup>
@@ -43,9 +43,10 @@ The setup process involves three main steps:
43
43
  - AWS account with permissions to run CloudFormation.
44
44
  - [AWS CLI](https://aws.amazon.com/cli/) installed locally.
45
45
 
46
- <Tip>Be sure to run `aws configure` with your credentials</Tip>
47
-
48
- - Access to the TestDriver AMI (Golden Image)\
46
+ <Tip>
47
+ Be sure to run `aws configure` with your credentials
48
+ </Tip>
49
+ - Access to the TestDriver AMI (Golden Image is `ami-055cd47506a2f39bb`)\
49
50
  [Contact us with your preferred AWS Region for access](https://form.typeform.com/to/UECf9rDx?typeform-source=testdriver.ai).
50
51
  - A GitHub repository for committing your tests & workflow.
51
52
 
@@ -76,8 +77,7 @@ aws cloudformation deploy \
76
77
  ```
77
78
 
78
79
  <Danger>
79
- **Security**: Replace `AllowedIngressCidr=0.0.0.0/0` with your specific IP
80
- ranges to lock down access to your VPC.
80
+ **Security**: Replace `AllowedIngressCidr=0.0.0.0/0` with your specific IP ranges to lock down access to your VPC.
81
81
  </Danger>
82
82
 
83
83
  ### Get Launch Template ID
@@ -91,7 +91,9 @@ aws cloudformation describe-stacks \
91
91
  --output text
92
92
  ```
93
93
 
94
- <Tip>**Save this ID** – you'll need it for the next step.</Tip>
94
+ <Tip>
95
+ **Save this ID** – you'll need it for the next step.
96
+ </Tip>
95
97
 
96
98
  ## Step 2: Spawn a New TestDriver Runner
97
99
 
@@ -127,15 +129,12 @@ AWS_REGION=us-east-2
127
129
  ```
128
130
 
129
131
  <Note>
130
- **Instance Lifecycle**: Instances spawned by this script will continue running
131
- until you manually terminate them. They are automatically tagged with
132
- `Name=TestDriverRunner` and `Project=[your ProjectTag value]` for easy
133
- identification in the AWS console.
132
+ **Instance Lifecycle**: Instances spawned by this script will continue running until you manually terminate them. They are automatically tagged with `Name=TestDriverRunner` and `Project=[your ProjectTag value]` for easy identification in the AWS console.
134
133
  </Note>
135
134
 
136
135
  #### Changing Resolution in Lifecycle Files
137
136
 
138
- You can also change the resolution before running tests by adding an `exec` command in your `lifecycle/provision.yaml` file:
137
+ You can also change the resolution before running tests by adding an [`exec`](/commands/exec) command in your `lifecycle/provision.yaml` file:
139
138
 
140
139
  ```yaml lifecycle/provision.yaml
141
140
  version: 6.0.0
@@ -367,4 +366,4 @@ For enterprise customers:
367
366
 
368
367
  - Contact your account manager for AMI access issues
369
368
  - Use support channels for infrastructure questions
370
- - Check the TestDriver documentation for CLI usage
369
+ - Check the TestDriver documentation for CLI usage