testdriverai 6.2.2 → 7.1.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 (300) 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/AGENTS.md +550 -0
  5. package/CODEOWNERS +0 -1
  6. package/README.md +126 -0
  7. package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
  8. package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
  9. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  10. package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
  11. package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
  12. package/_testdriver/lifecycle/prerun.yaml +15 -0
  13. package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
  14. package/agent/index.js +300 -85
  15. package/agent/interface.js +15 -0
  16. package/agent/lib/cache.js +142 -0
  17. package/agent/lib/commander.js +1 -39
  18. package/agent/lib/commands.js +910 -296
  19. package/agent/lib/redraw.js +129 -41
  20. package/agent/lib/sandbox.js +29 -6
  21. package/agent/lib/sdk.js +22 -0
  22. package/agent/lib/system.js +0 -3
  23. package/agent/lib/validation.js +1 -7
  24. package/debug-locate-response.js +82 -0
  25. package/debugger/index.html +15 -4
  26. package/docs/ARCHITECTURE.md +424 -0
  27. package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
  28. package/docs/MIGRATION.md +425 -0
  29. package/docs/PRESETS.md +210 -0
  30. package/docs/QUICK_START_TEST_RECORDING.md +215 -0
  31. package/docs/SDK_AWESOME_LOGS.md +468 -0
  32. package/docs/TEST_RECORDING.md +388 -0
  33. package/docs/docs.json +286 -152
  34. package/docs/guide/best-practices-polling.mdx +154 -0
  35. package/docs/sdk-browser-rendering.md +167 -0
  36. package/docs/v6/getting-started/self-hosting.mdx +407 -0
  37. package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
  38. package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
  39. package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
  40. package/docs/v6/overview/comparison.mdx +101 -0
  41. package/docs/v7/README.md +135 -0
  42. package/docs/v7/api/ai.mdx +205 -0
  43. package/docs/v7/api/assert.mdx +285 -0
  44. package/docs/v7/api/assertions.mdx +403 -0
  45. package/docs/v7/api/click.mdx +287 -0
  46. package/docs/v7/api/client.mdx +322 -0
  47. package/docs/v7/api/dashcam.mdx +497 -0
  48. package/docs/v7/api/doubleClick.mdx +102 -0
  49. package/docs/v7/api/elements.mdx +479 -0
  50. package/docs/v7/api/exec.mdx +346 -0
  51. package/docs/v7/api/find.mdx +316 -0
  52. package/docs/v7/api/focusApplication.mdx +294 -0
  53. package/docs/v7/api/hover.mdx +279 -0
  54. package/docs/v7/api/mouseDown.mdx +161 -0
  55. package/docs/v7/api/mouseUp.mdx +164 -0
  56. package/docs/v7/api/pressKeys.mdx +349 -0
  57. package/docs/v7/api/rightClick.mdx +123 -0
  58. package/docs/v7/api/sandbox.mdx +404 -0
  59. package/docs/v7/api/scroll.mdx +300 -0
  60. package/docs/v7/api/type.mdx +314 -0
  61. package/docs/v7/commands/assert.mdx +45 -0
  62. package/docs/v7/commands/exec.mdx +282 -0
  63. package/docs/v7/commands/focus-application.mdx +44 -0
  64. package/docs/v7/commands/hover-image.mdx +69 -0
  65. package/docs/v7/commands/hover-text.mdx +47 -0
  66. package/docs/v7/commands/if.mdx +53 -0
  67. package/docs/v7/commands/match-image.mdx +67 -0
  68. package/docs/v7/commands/press-keys.mdx +87 -0
  69. package/docs/v7/commands/remember.mdx +49 -0
  70. package/docs/v7/commands/run.mdx +44 -0
  71. package/docs/v7/commands/scroll-until-image.mdx +66 -0
  72. package/docs/v7/commands/scroll-until-text.mdx +60 -0
  73. package/docs/v7/commands/scroll.mdx +69 -0
  74. package/docs/v7/commands/type.mdx +45 -0
  75. package/docs/v7/commands/wait-for-image.mdx +54 -0
  76. package/docs/v7/commands/wait-for-text.mdx +48 -0
  77. package/docs/v7/commands/wait.mdx +45 -0
  78. package/docs/v7/getting-started/configuration.mdx +380 -0
  79. package/docs/v7/getting-started/quickstart.mdx +332 -0
  80. package/docs/v7/guides/best-practices.mdx +486 -0
  81. package/docs/v7/guides/caching-ai.mdx +215 -0
  82. package/docs/v7/guides/caching-selectors.mdx +292 -0
  83. package/docs/v7/guides/caching.mdx +366 -0
  84. package/docs/v7/guides/ci-cd/azure.mdx +587 -0
  85. package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
  86. package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
  87. package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
  88. package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
  89. package/docs/v7/guides/ci-cd/travis.mdx +438 -0
  90. package/docs/v7/guides/debugging.mdx +349 -0
  91. package/docs/v7/guides/faq.mdx +393 -0
  92. package/docs/v7/guides/migration.mdx +562 -0
  93. package/docs/v7/guides/performance.mdx +517 -0
  94. package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
  95. package/docs/v7/guides/troubleshooting.mdx +526 -0
  96. package/docs/v7/guides/vitest-plugin.mdx +477 -0
  97. package/docs/v7/guides/vitest.mdx +535 -0
  98. package/docs/v7/platforms/linux.mdx +308 -0
  99. package/docs/v7/platforms/macos.mdx +433 -0
  100. package/docs/v7/platforms/windows.mdx +430 -0
  101. package/docs/v7/playwright.mdx +342 -0
  102. package/docs/v7/presets/chrome-extension.mdx +223 -0
  103. package/docs/v7/presets/chrome.mdx +287 -0
  104. package/docs/v7/presets/electron.mdx +435 -0
  105. package/docs/v7/presets/vscode.mdx +398 -0
  106. package/docs/v7/presets/webapp.mdx +396 -0
  107. package/docs/v7/progressive-apis/CORE.md +459 -0
  108. package/docs/v7/progressive-apis/HOOKS.md +360 -0
  109. package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
  110. package/docs/v7/progressive-apis/PROVISION.md +266 -0
  111. package/eslint.config.js +19 -1
  112. package/interfaces/cli/lib/base.js +10 -4
  113. package/interfaces/logger.js +2 -1
  114. package/interfaces/shared-test-state.mjs +69 -0
  115. package/interfaces/vitest-plugin.mjs +830 -0
  116. package/package.json +29 -5
  117. package/schema.json +8 -29
  118. package/scripts/view-test-results.mjs +96 -0
  119. package/sdk-log-formatter.js +714 -0
  120. package/sdk.d.ts +1028 -0
  121. package/sdk.js +2567 -0
  122. package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
  123. package/setup/aws/cloudformation.yaml +9 -2
  124. package/src/core/Dashcam.js +469 -0
  125. package/src/core/index.d.ts +150 -0
  126. package/src/core/index.js +12 -0
  127. package/src/presets/index.mjs +331 -0
  128. package/src/vitest/extended.mjs +108 -0
  129. package/src/vitest/hooks.d.ts +119 -0
  130. package/src/vitest/hooks.mjs +298 -0
  131. package/src/vitest/index.mjs +64 -0
  132. package/src/vitest/lifecycle.mjs +277 -0
  133. package/src/vitest/utils.mjs +150 -0
  134. package/test/dashcam.test.js +137 -0
  135. package/test/mcp-example-test.yaml +27 -0
  136. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
  137. package/testdriver/acceptance-sdk/README.md +128 -0
  138. package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
  139. package/testdriver/acceptance-sdk/assert.test.mjs +26 -0
  140. package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
  141. package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
  142. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +58 -0
  143. package/testdriver/acceptance-sdk/element-not-found.test.mjs +25 -0
  144. package/testdriver/acceptance-sdk/exec-js.test.mjs +43 -0
  145. package/testdriver/acceptance-sdk/exec-output.test.mjs +59 -0
  146. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +57 -0
  147. package/testdriver/acceptance-sdk/focus-window.test.mjs +36 -0
  148. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +26 -0
  149. package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
  150. package/testdriver/acceptance-sdk/hover-image.test.mjs +34 -0
  151. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +38 -0
  152. package/testdriver/acceptance-sdk/hover-text.test.mjs +27 -0
  153. package/testdriver/acceptance-sdk/match-image.test.mjs +36 -0
  154. package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
  155. package/testdriver/acceptance-sdk/press-keys.test.mjs +50 -0
  156. package/testdriver/acceptance-sdk/prompt.test.mjs +33 -0
  157. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +38 -0
  158. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +39 -0
  159. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +28 -0
  160. package/testdriver/acceptance-sdk/scroll.test.mjs +41 -0
  161. package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
  162. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +420 -0
  163. package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
  164. package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
  165. package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
  166. package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
  167. package/testdriver/acceptance-sdk/type.test.mjs +45 -0
  168. package/verify-element-api.js +89 -0
  169. package/verify-types.js +0 -0
  170. package/vitest.config.example.js +19 -0
  171. package/vitest.config.mjs +66 -0
  172. package/vitest.config.mjs.bak +44 -0
  173. package/.github/workflows/acceptance-v6.yml +0 -169
  174. package/.vscode/mcp.json +0 -9
  175. package/docs/overview/comparison.mdx +0 -82
  176. package/testdriver/lifecycle/prerun.yaml +0 -17
  177. /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
  178. /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
  179. /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
  180. /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
  181. /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
  182. /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
  183. /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
  184. /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
  185. /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
  186. /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
  187. /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
  188. /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
  189. /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
  190. /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
  191. /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
  192. /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
  193. /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
  194. /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
  195. /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
  196. /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
  197. /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
  198. /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
  199. /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
  200. /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
  201. /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
  202. /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
  203. /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
  204. /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
  205. /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
  206. /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
  207. /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
  208. /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
  209. /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
  210. /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
  211. /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
  212. /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
  213. /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
  214. /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
  215. /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
  216. /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
  217. /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
  218. /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
  219. /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
  220. /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
  221. /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
  222. /package/docs/{account → v6/account}/dashboard.mdx +0 -0
  223. /package/docs/{account → v6/account}/enterprise.mdx +0 -0
  224. /package/docs/{account → v6/account}/pricing.mdx +0 -0
  225. /package/docs/{account → v6/account}/projects.mdx +0 -0
  226. /package/docs/{account → v6/account}/team.mdx +0 -0
  227. /package/docs/{action → v6/action}/ami.mdx +0 -0
  228. /package/docs/{action → v6/action}/performance.mdx +0 -0
  229. /package/docs/{action → v6/action}/secrets.mdx +0 -0
  230. /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
  231. /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
  232. /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
  233. /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
  234. /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
  235. /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
  236. /package/docs/{cli → v6/cli}/overview.mdx +0 -0
  237. /package/docs/{commands → v6/commands}/assert.mdx +0 -0
  238. /package/docs/{commands → v6/commands}/exec.mdx +0 -0
  239. /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
  240. /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
  241. /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
  242. /package/docs/{commands → v6/commands}/if.mdx +0 -0
  243. /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
  244. /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
  245. /package/docs/{commands → v6/commands}/remember.mdx +0 -0
  246. /package/docs/{commands → v6/commands}/run.mdx +0 -0
  247. /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
  248. /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
  249. /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
  250. /package/docs/{commands → v6/commands}/type.mdx +0 -0
  251. /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
  252. /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
  253. /package/docs/{commands → v6/commands}/wait.mdx +0 -0
  254. /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
  255. /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
  256. /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
  257. /package/docs/{features → v6/features}/generation.mdx +0 -0
  258. /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
  259. /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
  260. /package/docs/{features → v6/features}/selectorless.mdx +0 -0
  261. /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
  262. /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
  263. /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
  264. /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
  265. /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
  266. /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
  267. /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
  268. /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
  269. /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
  270. /package/docs/{guide → v6/guide}/code.mdx +0 -0
  271. /package/docs/{guide → v6/guide}/locating.mdx +0 -0
  272. /package/docs/{guide → v6/guide}/protips.mdx +0 -0
  273. /package/docs/{guide → v6/guide}/variables.mdx +0 -0
  274. /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
  275. /package/docs/{importing → v6/importing}/csv.mdx +0 -0
  276. /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
  277. /package/docs/{importing → v6/importing}/jira.mdx +0 -0
  278. /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
  279. /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
  280. /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
  281. /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
  282. /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
  283. /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
  284. /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
  285. /package/docs/{overview → v6/overview}/faq.mdx +0 -0
  286. /package/docs/{overview → v6/overview}/performance.mdx +0 -0
  287. /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
  288. /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
  289. /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
  290. /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
  291. /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
  292. /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
  293. /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
  294. /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
  295. /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
  296. /package/docs/{security → v6/security}/action.mdx +0 -0
  297. /package/docs/{security → v6/security}/agent.mdx +0 -0
  298. /package/docs/{security → v6/security}/platform.mdx +0 -0
  299. /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
  300. /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
package/docs/docs.json CHANGED
@@ -12,175 +12,309 @@
12
12
  },
13
13
  "favicon": "/images/template/icon.png",
14
14
  "navigation": {
15
- "groups": [
15
+ "tabs": [
16
16
  {
17
- "group": "Overview",
18
- "pages": [
19
- "/overview/what-is-testdriver",
17
+ "tab": "Computer-Use SDK",
18
+ "versions": [
20
19
  {
21
- "group": "Concepts",
22
- "icon": "book",
23
- "pages": [
24
- "/features/selectorless",
25
- "/overview/comparison",
26
- "/overview/performance",
27
- "/overview/faq"
20
+ "version": "7.0.0 (SDK)",
21
+ "groups": [
22
+ {
23
+ "group": "Getting Started",
24
+ "pages": [
25
+ "/v7/getting-started/quickstart",
26
+ {
27
+ "group": "Configuration",
28
+ "icon": "gear",
29
+ "pages": [
30
+ "/v7/getting-started/configuration",
31
+ {
32
+ "group": "Platforms",
33
+ "icon": "server",
34
+ "pages": [
35
+ "/v7/platforms/linux",
36
+ "/v7/platforms/windows",
37
+ "/v7/platforms/macos"
38
+ ]
39
+ }
40
+ ]
41
+ }
42
+ ]
43
+ },
44
+ {
45
+ "group": "Examples",
46
+ "icon": "code",
47
+ "pages": [
48
+ "/v7/presets/chrome",
49
+ "/v7/presets/chrome-extension",
50
+ "/v7/presets/vscode",
51
+ "/v7/presets/electron"
52
+ ]
53
+ },
54
+ {
55
+ "group": "Interactions",
56
+ "icon": "bolt",
57
+ "pages": [
58
+ "/v7/api/find",
59
+ "/v7/api/ai",
60
+ "/v7/api/click",
61
+ "/v7/api/doubleClick",
62
+ "/v7/api/rightClick",
63
+ "/v7/api/hover",
64
+ "/v7/api/mouseDown",
65
+ "/v7/api/mouseUp",
66
+ "/v7/api/type",
67
+ "/v7/api/pressKeys",
68
+ "/v7/api/scroll",
69
+ "/v7/api/focusApplication",
70
+ "/v7/api/assert",
71
+ "/v7/api/exec"
72
+ ]
73
+ },
74
+ {
75
+ "group": "Core Concepts",
76
+ "icon": "book",
77
+ "pages": [
78
+ "/v7/api/client",
79
+ "/v7/api/sandbox",
80
+ "/v7/api/elements",
81
+ "/v7/api/dashcam",
82
+ "/v7/api/assertions"
83
+ ]
84
+ },
85
+ {
86
+ "group": "Progressive APIs",
87
+ "icon": "layer-group",
88
+ "pages": [
89
+ "/v7/progressive-apis/PROGRESSIVE_DISCLOSURE",
90
+ "/v7/progressive-apis/PROVISION",
91
+ "/v7/progressive-apis/HOOKS"
92
+ ]
93
+ },
94
+
95
+ {
96
+ "group": "Guides",
97
+ "icon": "book-open",
98
+ "pages": [
99
+ "/v7/guides/vitest",
100
+ "/v7/guides/vitest-plugin",
101
+ "/v7/guides/debugging",
102
+ "/v7/guides/best-practices",
103
+ "/v7/guides/troubleshooting",
104
+ "/v7/guides/faq",
105
+ {
106
+ "group": "Caching",
107
+ "icon": "bolt",
108
+ "pages": [
109
+ "/v7/guides/caching-ai",
110
+ "/v7/guides/caching-selectors"
111
+ ]
112
+ },
113
+ {
114
+ "group": "CI/CD Integration",
115
+ "icon": "arrows-spin",
116
+ "pages": [
117
+ "/v7/guides/ci-cd/overview",
118
+ "/v7/guides/ci-cd/github-actions",
119
+ "/v7/guides/ci-cd/gitlab",
120
+ "/v7/guides/ci-cd/circleci",
121
+ "/v7/guides/ci-cd/jenkins",
122
+ "/v7/guides/ci-cd/azure",
123
+ "/v7/guides/ci-cd/travis"
124
+ ]
125
+ },
126
+ "/v7/guides/performance",
127
+ "/v7/guides/self-hosting",
128
+ "/v7/guides/migration"
129
+ ]
130
+ }
28
131
  ]
29
132
  },
30
- "/account/enterprise"
31
- ]
32
- },
33
- {
34
- "group": "Get Started",
35
- "pages": [
36
- "/overview/quickstart",
37
133
  {
38
- "group": "CLI",
39
- "icon": "terminal",
40
- "pages": [
41
- "/cli/overview",
134
+ "version": "6.X.X (YAML)",
135
+ "groups": [
136
+ {
137
+ "group": "Overview",
138
+ "pages": [
139
+ "/v6/overview/what-is-testdriver",
140
+ {
141
+ "group": "Concepts",
142
+ "icon": "book",
143
+ "pages": [
144
+ "/v6/features/selectorless",
145
+ "/v6/overview/comparison",
146
+ "/v6/overview/performance",
147
+ "/v6/overview/faq"
148
+ ]
149
+ },
150
+ "/v6/account/enterprise"
151
+ ]
152
+ },
153
+ {
154
+ "group": "Get Started",
155
+ "pages": [
156
+ "/v6/overview/quickstart",
157
+ {
158
+ "group": "CLI",
159
+ "icon": "terminal",
160
+ "pages": [
161
+ "/v6/cli/overview",
162
+ {
163
+ "group": "Commands",
164
+ "icon": "command",
165
+ "pages": [
166
+ "/v6/interactive/explore",
167
+ "/v6/interactive/run",
168
+ "/v6/interactive/save"
169
+ ]
170
+ }
171
+ ]
172
+ },
173
+ "/v6/getting-started/self-hosting",
174
+ "/v6/getting-started/playwright",
175
+ "/v6/getting-started/vscode"
176
+ ]
177
+ },
178
+ {
179
+ "group": "Examples",
180
+ "pages": [
181
+ {
182
+ "group": "Apps",
183
+ "icon": "laptop",
184
+ "pages": [
185
+ "apps/static-websites",
186
+ "apps/desktop-apps",
187
+ "apps/chrome-extensions",
188
+ "apps/mobile-apps",
189
+ "apps/tauri-apps"
190
+ ]
191
+ },
192
+ {
193
+ "group": "Scenarios",
194
+ "icon": "computer-mouse",
195
+ "pages": [
196
+ "scenarios/ai-chatbot",
197
+ "scenarios/cookie-banner",
198
+ "scenarios/file-upload",
199
+ "scenarios/form-filling",
200
+ "scenarios/log-in",
201
+ "scenarios/pdf-generation",
202
+ "scenarios/spell-check"
203
+ ]
204
+ },
205
+ {
206
+ "group": "Build Systems",
207
+ "icon": "helmet-safety",
208
+ "pages": [
209
+ "/v6/integrations/electron",
210
+ "/v6/integrations/netlify",
211
+ "/v6/integrations/vercel"
212
+ ]
213
+ }
214
+ ]
215
+ },
216
+ {
217
+ "group": "Guide",
218
+ "pages": [
219
+ {
220
+ "group": "Configuration",
221
+ "icon": "desktop",
222
+ "pages": [
223
+ "/v6/guide/authentication",
224
+ "/v6/guide/variables",
225
+ "/v6/guide/lifecycle",
226
+ "/v6/guide/dashcam",
227
+ "/v6/guide/environment-variables",
228
+ "/v6/action/ami"
229
+ ]
230
+ },
231
+ {
232
+ "group": "Writing",
233
+ "icon": "pencil",
234
+ "pages": [
235
+ "/v6/features/generation",
236
+ "/v6/guide/locating",
237
+ "/v6/guide/waiting",
238
+ "/v6/guide/assertions",
239
+ "/v6/guide/code",
240
+ "/v6/features/reusable-snippets",
241
+ "/v6/guide/protips"
242
+ ]
243
+ },
244
+ {
245
+ "group": "Importing",
246
+ "icon": "file-import",
247
+ "pages": [
248
+ "/v6/importing/csv",
249
+ "/v6/importing/gherkin",
250
+ "/v6/importing/jira",
251
+ "/v6/importing/testrail"
252
+ ]
253
+ },
254
+ {
255
+ "group": "Running",
256
+ "icon": "play",
257
+ "pages": [
258
+ "/v6/getting-started/running",
259
+ "/v6/getting-started/ci",
260
+ "/v6/features/parallel-testing",
261
+ "/v6/action/performance",
262
+ "/v6/action/secrets"
263
+ ]
264
+ },
265
+ {
266
+ "group": "Maintaining",
267
+ "icon": "wrench",
268
+ "pages": ["/v6/getting-started/editing", "/v6/features/auto-healing"]
269
+ },
270
+ {
271
+ "group": "Reporting",
272
+ "icon": "chart-simple",
273
+ "pages": ["exporting/junit", "/v6/bugs/jira"]
274
+ }
275
+ ]
276
+ },
42
277
  {
43
- "group": "Commands",
44
- "icon": "command",
278
+ "group": "Reference",
45
279
  "pages": [
46
- "/interactive/explore",
47
- "/interactive/run",
48
- "/interactive/save"
280
+ {
281
+ "group": "YAML",
282
+ "icon": "file-code",
283
+ "pages": [
284
+ "/v6/commands/assert",
285
+ "/v6/commands/exec",
286
+ "/v6/commands/focus-application",
287
+ "/v6/commands/hover-image",
288
+ "/v6/commands/hover-text",
289
+ "/v6/commands/if",
290
+ "/v6/commands/match-image",
291
+ "/v6/commands/press-keys",
292
+ "/v6/commands/remember",
293
+ "/v6/commands/run",
294
+ "/v6/commands/scroll",
295
+ "/v6/commands/scroll-until-image",
296
+ "/v6/commands/scroll-until-text",
297
+ "/v6/commands/type",
298
+ "/v6/commands/wait",
299
+ "/v6/commands/wait-for-image",
300
+ "/v6/commands/wait-for-text"
301
+ ]
302
+ }
49
303
  ]
50
304
  }
51
305
  ]
52
- },
53
- "/getting-started/self-hosting",
54
- "/getting-started/playwright",
55
- "/getting-started/vscode"
306
+ }
56
307
  ]
57
308
  },
58
309
  {
59
- "group": "Examples",
60
- "pages": [
61
- {
62
- "group": "Apps",
63
- "icon": "laptop",
64
- "pages": [
65
- "apps/static-websites",
66
- "apps/desktop-apps",
67
- "apps/chrome-extensions",
68
- "apps/mobile-apps",
69
- "apps/tauri-apps"
70
- ]
71
- },
72
- {
73
- "group": "Scenarios",
74
- "icon": "computer-mouse",
75
- "pages": [
76
- "scenarios/ai-chatbot",
77
- "scenarios/cookie-banner",
78
- "scenarios/file-upload",
79
- "scenarios/form-filling",
80
- "scenarios/log-in",
81
- "scenarios/pdf-generation",
82
- "scenarios/spell-check"
83
- ]
84
- },
85
- {
86
- "group": "Build Systems",
87
- "icon": "helmet-safety",
88
- "pages": [
89
- "/integrations/electron",
90
- "/integrations/netlify",
91
- "/integrations/vercel"
92
- ]
93
- }
94
- ]
310
+ "tab": "Playwright SDK",
311
+ "pages": ["v7/playwright"]
95
312
  },
96
313
  {
97
- "group": "Guide",
98
- "pages": [
99
- {
100
- "group": "Configuration",
101
- "icon": "desktop",
102
- "pages": [
103
- "/guide/authentication",
104
- "/guide/variables",
105
- "/guide/lifecycle",
106
- "/guide/dashcam",
107
- "/guide/environment-variables",
108
- "/action/ami"
109
- ]
110
- },
111
- {
112
- "group": "Writing",
113
- "icon": "pencil",
114
- "pages": [
115
- "/features/generation",
116
- "/guide/locating",
117
- "/guide/waiting",
118
- "/guide/assertions",
119
- "/guide/code",
120
- "/features/reusable-snippets",
121
- "/guide/protips"
122
- ]
123
- },
124
- {
125
- "group": "Importing",
126
- "icon": "file-import",
127
- "pages": [
128
- "/importing/csv",
129
- "/importing/gherkin",
130
- "/importing/jira",
131
- "/importing/testrail"
132
- ]
133
- },
134
- {
135
- "group": "Running",
136
- "icon": "play",
137
- "pages": [
138
- "/getting-started/running",
139
- "/getting-started/ci",
140
- "/features/parallel-testing",
141
- "/action/performance",
142
- "/action/secrets"
143
- ]
144
- },
145
- {
146
- "group": "Maintaining",
147
- "icon": "wrench",
148
- "pages": ["/getting-started/editing", "/features/auto-healing"]
149
- },
150
- {
151
- "group": "Reporting",
152
- "icon": "chart-simple",
153
- "pages": ["exporting/junit", "/bugs/jira"]
154
- }
155
- ]
314
+ "tab": "Playwright Studio"
156
315
  },
157
316
  {
158
- "group": "Reference",
159
- "pages": [
160
- {
161
- "group": "YAML",
162
- "icon": "file-code",
163
- "pages": [
164
- "/commands/assert",
165
- "/commands/exec",
166
- "/commands/focus-application",
167
- "/commands/hover-image",
168
- "/commands/hover-text",
169
- "/commands/if",
170
- "/commands/match-image",
171
- "/commands/press-keys",
172
- "/commands/remember",
173
- "/commands/run",
174
- "/commands/scroll",
175
- "/commands/scroll-until-image",
176
- "/commands/scroll-until-text",
177
- "/commands/type",
178
- "/commands/wait",
179
- "/commands/wait-for-image",
180
- "/commands/wait-for-text"
181
- ]
182
- }
183
- ]
317
+ "tab": "Dashcam CLI"
184
318
  }
185
319
  ]
186
320
  },
@@ -0,0 +1,154 @@
1
+ # Best Practices: Element Polling
2
+
3
+ **⚠️ CRITICAL: Never use `wait()` for waiting for elements to appear.**
4
+
5
+ ## Why Avoid `wait()`?
6
+
7
+ Arbitrary waits with `wait()` have several problems:
8
+
9
+ 1. **Brittle**: Fixed timeouts may be too short (causing flaky tests) or too long (wasting time)
10
+ 2. **Slow**: You always wait the full duration, even if the element appears sooner
11
+ 3. **Unreliable**: Network conditions, system load, and other factors affect timing
12
+ 4. **Hard to debug**: When tests fail, you don't know if it was a timing issue or actual failure
13
+
14
+ ## The Right Way: Element Polling with `find()`
15
+
16
+ TestDriver's `find()` method is designed for element detection. Use it in a polling loop to wait for elements:
17
+
18
+ ### Basic Polling Pattern
19
+
20
+ ```javascript
21
+ // ❌ WRONG: Using wait()
22
+ await testdriver.wait(2000);
23
+ const button = await testdriver.find("Submit button");
24
+
25
+ // ✅ CORRECT: Polling with find()
26
+ let button;
27
+ for (let i = 0; i < 10; i++) {
28
+ try {
29
+ button = await testdriver.find("Submit button");
30
+ if (button.found()) break;
31
+ } catch (e) {
32
+ if (i === 9) throw e; // Re-throw on last attempt
33
+ }
34
+ await new Promise(resolve => setTimeout(resolve, 1000));
35
+ }
36
+ ```
37
+
38
+ ### Helper Function for Polling
39
+
40
+ Create a reusable helper function:
41
+
42
+ ```javascript
43
+ async function waitForElement(testdriver, description, maxAttempts = 10, delayMs = 1000) {
44
+ for (let i = 0; i < maxAttempts; i++) {
45
+ try {
46
+ const element = await testdriver.find(description);
47
+ if (element.found()) {
48
+ return element;
49
+ }
50
+ } catch (e) {
51
+ if (i === maxAttempts - 1) throw e;
52
+ }
53
+ await new Promise(resolve => setTimeout(resolve, delayMs));
54
+ }
55
+ throw new Error(`Element not found after ${maxAttempts} attempts: ${description}`);
56
+ }
57
+
58
+ // Usage
59
+ const emailField = await waitForElement(testdriver, "Email input field");
60
+ await emailField.click();
61
+ ```
62
+
63
+ ## When to Use Polling
64
+
65
+ Use element polling in these scenarios:
66
+
67
+ - **After navigation**: Waiting for a new page to load
68
+ - **After user action**: Waiting for UI updates (form submission, modal opening, etc.)
69
+ - **Dynamic content**: Waiting for AJAX-loaded elements
70
+ - **State transitions**: Waiting for loading spinners to disappear or success messages to appear
71
+
72
+ ## Example: Complete Login Flow
73
+
74
+ ```javascript
75
+ import { chrome } from "testdriverai/presets";
76
+
77
+ // Helper function
78
+ async function waitForElement(testdriver, description, maxAttempts = 10, delayMs = 1000) {
79
+ for (let i = 0; i < maxAttempts; i++) {
80
+ try {
81
+ const element = await testdriver.find(description);
82
+ if (element.found()) return element;
83
+ } catch (e) {
84
+ if (i === maxAttempts - 1) throw e;
85
+ }
86
+ await new Promise(resolve => setTimeout(resolve, delayMs));
87
+ }
88
+ throw new Error(`Element not found after ${maxAttempts} attempts: ${description}`);
89
+ }
90
+
91
+ it("should log in successfully", async (context) => {
92
+ const { testdriver } = await chrome(context, {
93
+ url: 'https://example.com/login',
94
+ });
95
+
96
+ // Wait for login page to load
97
+ const emailField = await waitForElement(testdriver, "Email input field");
98
+ await emailField.click();
99
+ await testdriver.type("user@example.com");
100
+
101
+ const passwordField = await testdriver.find("Password input field");
102
+ await passwordField.click();
103
+ await testdriver.type("password123");
104
+
105
+ const loginButton = await testdriver.find("Login button");
106
+ await loginButton.click();
107
+
108
+ // Wait for dashboard to load after login
109
+ await waitForElement(testdriver, "Dashboard welcome message");
110
+
111
+ // Verify login successful
112
+ const isLoggedIn = await testdriver.assert("user is logged in to dashboard");
113
+ expect(isLoggedIn).toBeTruthy();
114
+ });
115
+ ```
116
+
117
+ ## Advanced: Conditional Polling
118
+
119
+ For elements that may or may not appear (like dialogs or notifications):
120
+
121
+ ```javascript
122
+ // Try to find and dismiss optional dialog
123
+ try {
124
+ const dialog = await waitForElement(testdriver, "Cookie consent dialog", 3, 500);
125
+ const acceptButton = await testdriver.find("Accept button");
126
+ await acceptButton.click();
127
+ console.log("Dismissed cookie dialog");
128
+ } catch {
129
+ console.log("No cookie dialog found, continuing...");
130
+ }
131
+ ```
132
+
133
+ ## Configuration
134
+
135
+ Adjust polling parameters based on your needs:
136
+
137
+ ```javascript
138
+ // Quick polling for fast UI updates (check every 300ms, up to 3 seconds)
139
+ await waitForElement(testdriver, "Success message", 10, 300);
140
+
141
+ // Patient polling for slow operations (check every 2s, up to 20 seconds)
142
+ await waitForElement(testdriver, "Processing complete indicator", 10, 2000);
143
+ ```
144
+
145
+ ## Summary
146
+
147
+ | Pattern | Use Case |
148
+ |---------|----------|
149
+ | **Polling with `find()`** | ✅ Waiting for UI elements to appear or disappear |
150
+ | **`wait()`** | ❌ NEVER use for element waiting |
151
+ | **Helper function** | ✅ Recommended for cleaner, reusable code |
152
+ | **Conditional polling** | ✅ For optional elements (dialogs, notifications) |
153
+
154
+ Remember: **If you're waiting for something to appear on screen, use `find()` in a polling loop, not `wait()`.**