@testdriverai/agent 7.8.0-test.38

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 (528) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +4 -0
  3. package/.prettierignore +4 -0
  4. package/.prettierrc +1 -0
  5. package/CHANGELOG.md +953 -0
  6. package/README.md +81 -0
  7. package/agent/events.js +135 -0
  8. package/agent/index.js +2450 -0
  9. package/agent/interface.js +35 -0
  10. package/agent/lib/analytics.js +22 -0
  11. package/agent/lib/censorship.js +75 -0
  12. package/agent/lib/commander.js +246 -0
  13. package/agent/lib/commands.js +1684 -0
  14. package/agent/lib/config.js +60 -0
  15. package/agent/lib/generator.js +91 -0
  16. package/agent/lib/http.js +144 -0
  17. package/agent/lib/logger.js +56 -0
  18. package/agent/lib/outputs.js +29 -0
  19. package/agent/lib/parser.js +209 -0
  20. package/agent/lib/redraw.js +386 -0
  21. package/agent/lib/resources/cursor-2.png +0 -0
  22. package/agent/lib/sandbox.js +1104 -0
  23. package/agent/lib/sdk.js +633 -0
  24. package/agent/lib/session.js +25 -0
  25. package/agent/lib/source-mapper.js +342 -0
  26. package/agent/lib/subimage/index.js +77 -0
  27. package/agent/lib/subimage/opencv.js +69 -0
  28. package/agent/lib/system.js +204 -0
  29. package/agent/lib/theme.js +14 -0
  30. package/agent/lib/valid-version.js +21 -0
  31. package/agent/lib/validation.js +169 -0
  32. package/ai/.claude-plugin/plugin.json +9 -0
  33. package/ai/agents/testdriver.md +638 -0
  34. package/ai/skills/testdriver-ai/SKILL.md +204 -0
  35. package/ai/skills/testdriver-assert/SKILL.md +315 -0
  36. package/ai/skills/testdriver-aws-setup/SKILL.md +448 -0
  37. package/ai/skills/testdriver-cache/SKILL.md +221 -0
  38. package/ai/skills/testdriver-caching/SKILL.md +124 -0
  39. package/ai/skills/testdriver-captcha/SKILL.md +158 -0
  40. package/ai/skills/testdriver-ci-cd/SKILL.md +602 -0
  41. package/ai/skills/testdriver-click/SKILL.md +286 -0
  42. package/ai/skills/testdriver-client/SKILL.md +477 -0
  43. package/ai/skills/testdriver-cloud/SKILL.md +119 -0
  44. package/ai/skills/testdriver-customizing-devices/SKILL.md +319 -0
  45. package/ai/skills/testdriver-dashcam/SKILL.md +418 -0
  46. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +401 -0
  47. package/ai/skills/testdriver-device-config/SKILL.md +317 -0
  48. package/ai/skills/testdriver-double-click/SKILL.md +102 -0
  49. package/ai/skills/testdriver-elements/SKILL.md +605 -0
  50. package/ai/skills/testdriver-enterprise/SKILL.md +114 -0
  51. package/ai/skills/testdriver-errors/SKILL.md +246 -0
  52. package/ai/skills/testdriver-events/SKILL.md +356 -0
  53. package/ai/skills/testdriver-examples/SKILL.md +7 -0
  54. package/ai/skills/testdriver-exec/SKILL.md +317 -0
  55. package/ai/skills/testdriver-find/SKILL.md +829 -0
  56. package/ai/skills/testdriver-focus-application/SKILL.md +293 -0
  57. package/ai/skills/testdriver-generating-tests/SKILL.md +36 -0
  58. package/ai/skills/testdriver-hover/SKILL.md +278 -0
  59. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -0
  60. package/ai/skills/testdriver-making-assertions/SKILL.md +32 -0
  61. package/ai/skills/testdriver-mcp/SKILL.md +7 -0
  62. package/ai/skills/testdriver-mcp-workflow/SKILL.md +410 -0
  63. package/ai/skills/testdriver-mouse-down/SKILL.md +161 -0
  64. package/ai/skills/testdriver-mouse-up/SKILL.md +164 -0
  65. package/ai/skills/testdriver-parse/SKILL.md +236 -0
  66. package/ai/skills/testdriver-performing-actions/SKILL.md +54 -0
  67. package/ai/skills/testdriver-press-keys/SKILL.md +348 -0
  68. package/ai/skills/testdriver-provision/SKILL.md +331 -0
  69. package/ai/skills/testdriver-quickstart/SKILL.md +144 -0
  70. package/ai/skills/testdriver-redraw/SKILL.md +214 -0
  71. package/ai/skills/testdriver-reusable-code/SKILL.md +249 -0
  72. package/ai/skills/testdriver-right-click/SKILL.md +123 -0
  73. package/ai/skills/testdriver-running-tests/SKILL.md +185 -0
  74. package/ai/skills/testdriver-screenshot/SKILL.md +248 -0
  75. package/ai/skills/testdriver-screenshots/SKILL.md +184 -0
  76. package/ai/skills/testdriver-scroll/SKILL.md +335 -0
  77. package/ai/skills/testdriver-secrets/SKILL.md +115 -0
  78. package/ai/skills/testdriver-self-hosted/SKILL.md +65 -0
  79. package/ai/skills/testdriver-test-writer/SKILL.md +448 -0
  80. package/ai/skills/testdriver-testdriver/SKILL.md +628 -0
  81. package/ai/skills/testdriver-testdriver-mechanic/SKILL.md +165 -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/ai/skills/testdriver-waiting-for-elements/SKILL.md +90 -0
  86. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +54 -0
  87. package/bin/testdriverai.js +22 -0
  88. package/debugger/bg.png +0 -0
  89. package/debugger/icon.png +0 -0
  90. package/debugger/index.html +469 -0
  91. package/debugger/td.png +0 -0
  92. package/debugger/tray-buffered.png +0 -0
  93. package/debugger/tray.png +0 -0
  94. package/docs/GITHUB_COMMENTS.md +330 -0
  95. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
  96. package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
  97. package/docs/TEST-GITHUB-COMMENTS.md +129 -0
  98. package/docs/_data/examples-manifest.json +177 -0
  99. package/docs/_data/examples-manifest.schema.json +41 -0
  100. package/docs/_scripts/extract-example-urls.js +165 -0
  101. package/docs/_scripts/generate-examples.js +560 -0
  102. package/docs/_scripts/generate-skills.js +154 -0
  103. package/docs/_scripts/link-replacer.js +164 -0
  104. package/docs/_scripts/upload-docs-to-openai.js +284 -0
  105. package/docs/changelog.mdx +161 -0
  106. package/docs/claude-mcp-plugin.mdx +160 -0
  107. package/docs/docs.json +442 -0
  108. package/docs/github-integration-setup.md +266 -0
  109. package/docs/guide/best-practices-polling.mdx +174 -0
  110. package/docs/images/content/account/newprojectsettings.png +0 -0
  111. package/docs/images/content/account/projectpage.png +0 -0
  112. package/docs/images/content/account/projectreplays.png +0 -0
  113. package/docs/images/content/account/team-manage.png +0 -0
  114. package/docs/images/content/account/teampage.png +0 -0
  115. package/docs/images/content/extension/cursor.svg +1 -0
  116. package/docs/images/content/extension/vscode.svg +57 -0
  117. package/docs/images/content/extension/windsurf.svg +3 -0
  118. package/docs/images/content/parse/output.png +0 -0
  119. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  120. package/docs/images/content/side-by-side.png +0 -0
  121. package/docs/images/content/vscode/ide-full.png +0 -0
  122. package/docs/images/content/vscode/running.png +0 -0
  123. package/docs/images/content/vscode/v7-chat.png +0 -0
  124. package/docs/images/content/vscode/v7-choose-agent.png +0 -0
  125. package/docs/images/content/vscode/v7-full.png +0 -0
  126. package/docs/images/content/vscode/v7-onboarding.png +0 -0
  127. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  128. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  129. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  130. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  131. package/docs/images/content/vscode/vscode-install.png +0 -0
  132. package/docs/images/content/vscode/vscode-overview.png +0 -0
  133. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  134. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  135. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  136. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  137. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  138. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  139. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  140. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  141. package/docs/images/template/dark.png +0 -0
  142. package/docs/images/template/icon.png +0 -0
  143. package/docs/images/template/light.png +0 -0
  144. package/docs/snippets/calendar-link.mdx +4 -0
  145. package/docs/snippets/gitignore-warning.mdx +7 -0
  146. package/docs/snippets/lifecycle-warning.mdx +6 -0
  147. package/docs/snippets/test-prereqs.mdx +12 -0
  148. package/docs/snippets/tests/assert-replay.mdx +7 -0
  149. package/docs/snippets/tests/assert-yaml.mdx +8 -0
  150. package/docs/snippets/tests/exec-js-replay.mdx +7 -0
  151. package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
  152. package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
  153. package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
  154. package/docs/snippets/tests/hover-image-replay.mdx +7 -0
  155. package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
  156. package/docs/snippets/tests/hover-text-replay.mdx +7 -0
  157. package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
  158. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
  159. package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
  160. package/docs/snippets/tests/match-image-replay.mdx +7 -0
  161. package/docs/snippets/tests/match-image-yaml.mdx +17 -0
  162. package/docs/snippets/tests/press-keys-replay.mdx +7 -0
  163. package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
  164. package/docs/snippets/tests/remember-replay.mdx +7 -0
  165. package/docs/snippets/tests/remember-yaml.mdx +28 -0
  166. package/docs/snippets/tests/scroll-replay.mdx +7 -0
  167. package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
  168. package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
  169. package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
  170. package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
  171. package/docs/snippets/tests/scroll-yaml.mdx +30 -0
  172. package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
  173. package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
  174. package/docs/snippets/tests/type-replay.mdx +7 -0
  175. package/docs/snippets/tests/type-yaml.mdx +28 -0
  176. package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
  177. package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
  178. package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
  179. package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
  180. package/docs/snippets/tests/wait-replay.mdx +7 -0
  181. package/docs/snippets/tests/wait-yaml.mdx +13 -0
  182. package/docs/styles.css +65 -0
  183. package/docs/v6/account/dashboard.mdx +16 -0
  184. package/docs/v6/account/enterprise.mdx +110 -0
  185. package/docs/v6/account/pricing.mdx +33 -0
  186. package/docs/v6/account/projects.mdx +33 -0
  187. package/docs/v6/account/team.mdx +35 -0
  188. package/docs/v6/action/ami.mdx +109 -0
  189. package/docs/v6/action/performance.mdx +105 -0
  190. package/docs/v6/action/secrets.mdx +93 -0
  191. package/docs/v6/apps/chrome-extensions.mdx +48 -0
  192. package/docs/v6/apps/desktop-apps.mdx +93 -0
  193. package/docs/v6/apps/mobile-apps.mdx +26 -0
  194. package/docs/v6/apps/static-websites.mdx +54 -0
  195. package/docs/v6/apps/tauri-apps.mdx +361 -0
  196. package/docs/v6/bugs/jira.mdx +232 -0
  197. package/docs/v6/cli/overview.mdx +66 -0
  198. package/docs/v6/commands/assert.mdx +45 -0
  199. package/docs/v6/commands/exec.mdx +276 -0
  200. package/docs/v6/commands/focus-application.mdx +44 -0
  201. package/docs/v6/commands/hover-image.mdx +69 -0
  202. package/docs/v6/commands/hover-text.mdx +47 -0
  203. package/docs/v6/commands/if.mdx +53 -0
  204. package/docs/v6/commands/match-image.mdx +67 -0
  205. package/docs/v6/commands/press-keys.mdx +87 -0
  206. package/docs/v6/commands/remember.mdx +49 -0
  207. package/docs/v6/commands/run.mdx +44 -0
  208. package/docs/v6/commands/scroll-until-image.mdx +66 -0
  209. package/docs/v6/commands/scroll-until-text.mdx +60 -0
  210. package/docs/v6/commands/scroll.mdx +69 -0
  211. package/docs/v6/commands/type.mdx +45 -0
  212. package/docs/v6/commands/wait-for-image.mdx +54 -0
  213. package/docs/v6/commands/wait-for-text.mdx +48 -0
  214. package/docs/v6/commands/wait.mdx +45 -0
  215. package/docs/v6/exporting/junit.mdx +218 -0
  216. package/docs/v6/exporting/playwright.mdx +197 -0
  217. package/docs/v6/features/auto-healing.mdx +144 -0
  218. package/docs/v6/features/generation.mdx +116 -0
  219. package/docs/v6/features/parallel-testing.mdx +151 -0
  220. package/docs/v6/features/reusable-snippets.mdx +131 -0
  221. package/docs/v6/features/selectorless.mdx +80 -0
  222. package/docs/v6/features/visual-assertions.mdx +139 -0
  223. package/docs/v6/getting-started/ci.mdx +146 -0
  224. package/docs/v6/getting-started/cli.mdx +91 -0
  225. package/docs/v6/getting-started/editing.mdx +100 -0
  226. package/docs/v6/getting-started/playwright.mdx +342 -0
  227. package/docs/v6/getting-started/running.mdx +48 -0
  228. package/docs/v6/getting-started/self-hosting.mdx +408 -0
  229. package/docs/v6/getting-started/vscode.mdx +88 -0
  230. package/docs/v6/guide/assertions.mdx +189 -0
  231. package/docs/v6/guide/authentication.mdx +136 -0
  232. package/docs/v6/guide/code.mdx +65 -0
  233. package/docs/v6/guide/dashcam.mdx +118 -0
  234. package/docs/v6/guide/environment-variables.mdx +26 -0
  235. package/docs/v6/guide/lifecycle.mdx +242 -0
  236. package/docs/v6/guide/locating.mdx +141 -0
  237. package/docs/v6/guide/protips.mdx +43 -0
  238. package/docs/v6/guide/variables.mdx +143 -0
  239. package/docs/v6/guide/waiting.mdx +130 -0
  240. package/docs/v6/importing/csv.mdx +196 -0
  241. package/docs/v6/importing/gherkin.mdx +143 -0
  242. package/docs/v6/importing/jira.mdx +164 -0
  243. package/docs/v6/importing/testrail.mdx +162 -0
  244. package/docs/v6/integrations/electron.mdx +146 -0
  245. package/docs/v6/integrations/netlify.mdx +100 -0
  246. package/docs/v6/integrations/vercel.mdx +125 -0
  247. package/docs/v6/interactive/explore.mdx +99 -0
  248. package/docs/v6/interactive/run.mdx +52 -0
  249. package/docs/v6/interactive/save.mdx +63 -0
  250. package/docs/v6/overview/comparison.mdx +101 -0
  251. package/docs/v6/overview/faq.mdx +162 -0
  252. package/docs/v6/overview/performance.mdx +52 -0
  253. package/docs/v6/overview/quickstart.mdx +137 -0
  254. package/docs/v6/overview/what-is-testdriver.mdx +85 -0
  255. package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
  256. package/docs/v6/scenarios/cookie-banner.mdx +32 -0
  257. package/docs/v6/scenarios/file-upload.mdx +33 -0
  258. package/docs/v6/scenarios/form-filling.mdx +32 -0
  259. package/docs/v6/scenarios/log-in.mdx +75 -0
  260. package/docs/v6/scenarios/pdf-generation.mdx +25 -0
  261. package/docs/v6/scenarios/spell-check.mdx +22 -0
  262. package/docs/v6/security/action.mdx +84 -0
  263. package/docs/v6/security/agent.mdx +73 -0
  264. package/docs/v6/security/platform.mdx +77 -0
  265. package/docs/v6/tutorials/advanced-test.mdx +81 -0
  266. package/docs/v6/tutorials/basic-test.mdx +45 -0
  267. package/docs/v7/_drafts/agents.mdx +843 -0
  268. package/docs/v7/_drafts/architecture.mdx +399 -0
  269. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  270. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
  271. package/docs/v7/_drafts/best-practices.mdx +486 -0
  272. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  273. package/docs/v7/_drafts/caching-selectors.mdx +424 -0
  274. package/docs/v7/_drafts/caching.mdx +366 -0
  275. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  276. package/docs/v7/_drafts/commands/assert.mdx +45 -0
  277. package/docs/v7/_drafts/commands/exec.mdx +276 -0
  278. package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
  279. package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
  280. package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
  281. package/docs/v7/_drafts/commands/if.mdx +53 -0
  282. package/docs/v7/_drafts/commands/match-image.mdx +67 -0
  283. package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
  284. package/docs/v7/_drafts/commands/remember.mdx +49 -0
  285. package/docs/v7/_drafts/commands/run.mdx +44 -0
  286. package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
  287. package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
  288. package/docs/v7/_drafts/commands/scroll.mdx +69 -0
  289. package/docs/v7/_drafts/commands/type.mdx +45 -0
  290. package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
  291. package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
  292. package/docs/v7/_drafts/commands/wait.mdx +45 -0
  293. package/docs/v7/_drafts/configuration.mdx +378 -0
  294. package/docs/v7/_drafts/contributing.mdx +174 -0
  295. package/docs/v7/_drafts/core.mdx +458 -0
  296. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  297. package/docs/v7/_drafts/debugging.mdx +349 -0
  298. package/docs/v7/_drafts/error-handling.mdx +501 -0
  299. package/docs/v7/_drafts/faq.mdx +393 -0
  300. package/docs/v7/_drafts/hooks.mdx +360 -0
  301. package/docs/v7/_drafts/init-command.mdx +95 -0
  302. package/docs/v7/_drafts/installation.mdx +420 -0
  303. package/docs/v7/_drafts/migration.mdx +562 -0
  304. package/docs/v7/_drafts/observable.mdx +604 -0
  305. package/docs/v7/_drafts/playwright.mdx +342 -0
  306. package/docs/v7/_drafts/plugin-migration.mdx +220 -0
  307. package/docs/v7/_drafts/powerful.mdx +419 -0
  308. package/docs/v7/_drafts/presets.mdx +210 -0
  309. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  310. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  311. package/docs/v7/_drafts/provision.mdx +390 -0
  312. package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
  313. package/docs/v7/_drafts/readme.mdx +135 -0
  314. package/docs/v7/_drafts/reports.mdx +414 -0
  315. package/docs/v7/_drafts/scalable.mdx +763 -0
  316. package/docs/v7/_drafts/screenshot.mdx +155 -0
  317. package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
  318. package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
  319. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  320. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  321. package/docs/v7/_drafts/self-hosting.mdx +369 -0
  322. package/docs/v7/_drafts/test-recording.mdx +382 -0
  323. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  324. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  325. package/docs/v7/_drafts/vitest.mdx +535 -0
  326. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  327. package/docs/v7/ai.mdx +205 -0
  328. package/docs/v7/assert.mdx +316 -0
  329. package/docs/v7/aws-setup.mdx +449 -0
  330. package/docs/v7/cache.mdx +223 -0
  331. package/docs/v7/caching.mdx +128 -0
  332. package/docs/v7/captcha.mdx +159 -0
  333. package/docs/v7/ci-cd.mdx +603 -0
  334. package/docs/v7/click.mdx +287 -0
  335. package/docs/v7/client.mdx +478 -0
  336. package/docs/v7/copilot/auto-healing.mdx +265 -0
  337. package/docs/v7/copilot/creating-tests.mdx +156 -0
  338. package/docs/v7/copilot/github.mdx +143 -0
  339. package/docs/v7/copilot/running-tests.mdx +149 -0
  340. package/docs/v7/copilot/setup.mdx +143 -0
  341. package/docs/v7/customizing-devices.mdx +319 -0
  342. package/docs/v7/dashcam.mdx +419 -0
  343. package/docs/v7/debugging-with-screenshots.mdx +402 -0
  344. package/docs/v7/device-config.mdx +317 -0
  345. package/docs/v7/double-click.mdx +102 -0
  346. package/docs/v7/elements.mdx +606 -0
  347. package/docs/v7/enterprise.mdx +9 -0
  348. package/docs/v7/errors.mdx +248 -0
  349. package/docs/v7/events.mdx +358 -0
  350. package/docs/v7/examples/ai.mdx +72 -0
  351. package/docs/v7/examples/assert.mdx +72 -0
  352. package/docs/v7/examples/captcha-api.mdx +92 -0
  353. package/docs/v7/examples/chrome-extension.mdx +132 -0
  354. package/docs/v7/examples/drag-and-drop.mdx +100 -0
  355. package/docs/v7/examples/element-not-found.mdx +67 -0
  356. package/docs/v7/examples/exec-output.mdx +85 -0
  357. package/docs/v7/examples/exec-pwsh.mdx +83 -0
  358. package/docs/v7/examples/focus-window.mdx +62 -0
  359. package/docs/v7/examples/hover-image.mdx +94 -0
  360. package/docs/v7/examples/hover-text.mdx +69 -0
  361. package/docs/v7/examples/installer.mdx +91 -0
  362. package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
  363. package/docs/v7/examples/match-image.mdx +96 -0
  364. package/docs/v7/examples/press-keys.mdx +92 -0
  365. package/docs/v7/examples/scroll-keyboard.mdx +79 -0
  366. package/docs/v7/examples/scroll-until-image.mdx +81 -0
  367. package/docs/v7/examples/scroll-until-text.mdx +109 -0
  368. package/docs/v7/examples/scroll.mdx +81 -0
  369. package/docs/v7/examples/type.mdx +92 -0
  370. package/docs/v7/examples/windows-installer.mdx +89 -0
  371. package/docs/v7/exec.mdx +318 -0
  372. package/docs/v7/find.mdx +830 -0
  373. package/docs/v7/focus-application.mdx +294 -0
  374. package/docs/v7/generating-tests.mdx +36 -0
  375. package/docs/v7/hosted.mdx +158 -0
  376. package/docs/v7/hover.mdx +279 -0
  377. package/docs/v7/locating-elements.mdx +71 -0
  378. package/docs/v7/making-assertions.mdx +32 -0
  379. package/docs/v7/mcp.mdx +9 -0
  380. package/docs/v7/mouse-down.mdx +161 -0
  381. package/docs/v7/mouse-up.mdx +164 -0
  382. package/docs/v7/parse.mdx +237 -0
  383. package/docs/v7/performing-actions.mdx +54 -0
  384. package/docs/v7/press-keys.mdx +349 -0
  385. package/docs/v7/provision.mdx +333 -0
  386. package/docs/v7/quickstart.mdx +173 -0
  387. package/docs/v7/redraw.mdx +216 -0
  388. package/docs/v7/reusable-code.mdx +249 -0
  389. package/docs/v7/right-click.mdx +123 -0
  390. package/docs/v7/running-tests.mdx +185 -0
  391. package/docs/v7/screenshot.mdx +249 -0
  392. package/docs/v7/screenshots.mdx +186 -0
  393. package/docs/v7/scroll.mdx +336 -0
  394. package/docs/v7/secrets.mdx +115 -0
  395. package/docs/v7/self-hosted.mdx +149 -0
  396. package/docs/v7/type.mdx +358 -0
  397. package/docs/v7/variables.mdx +111 -0
  398. package/docs/v7/wait.mdx +52 -0
  399. package/docs/v7/waiting-for-elements.mdx +90 -0
  400. package/docs/v7/what-is-testdriver.mdx +54 -0
  401. package/eslint.config.js +67 -0
  402. package/examples/ai.test.mjs +31 -0
  403. package/examples/assert.test.mjs +47 -0
  404. package/examples/chrome-extension.test.mjs +97 -0
  405. package/examples/config.mjs +5 -0
  406. package/examples/element-not-found.test.mjs +27 -0
  407. package/examples/exec-output.test.mjs +60 -0
  408. package/examples/exec-pwsh.test.mjs +58 -0
  409. package/examples/findall-coffee-icons.test.mjs +42 -0
  410. package/examples/focus-window.test.mjs +37 -0
  411. package/examples/formatted-logging.test.mjs +27 -0
  412. package/examples/hover-image.test.mjs +53 -0
  413. package/examples/hover-text-with-description.test.mjs +57 -0
  414. package/examples/hover-text.test.mjs +28 -0
  415. package/examples/installer.test.mjs +50 -0
  416. package/examples/launch-vscode-linux.test.mjs +55 -0
  417. package/examples/match-image.test.mjs +55 -0
  418. package/examples/parse.test.mjs +19 -0
  419. package/examples/press-keys.test.mjs +44 -0
  420. package/examples/prompt.test.mjs +34 -0
  421. package/examples/scroll-keyboard.test.mjs +38 -0
  422. package/examples/scroll-until-image.test.mjs +40 -0
  423. package/examples/scroll.test.mjs +42 -0
  424. package/examples/type.test.mjs +46 -0
  425. package/examples/windows-installer.test.mjs +54 -0
  426. package/index.js +2 -0
  427. package/interfaces/cli/commands/init.js +438 -0
  428. package/interfaces/cli/commands/setup.js +382 -0
  429. package/interfaces/cli/lib/base.js +285 -0
  430. package/interfaces/cli.js +20 -0
  431. package/interfaces/junit-reporter.js +290 -0
  432. package/interfaces/logger.js +388 -0
  433. package/interfaces/readline.js +234 -0
  434. package/interfaces/shared-test-state.mjs +64 -0
  435. package/interfaces/vitest-plugin.d.ts +115 -0
  436. package/interfaces/vitest-plugin.mjs +1698 -0
  437. package/lib/captcha/solver.js +358 -0
  438. package/lib/core/Dashcam.js +533 -0
  439. package/lib/core/index.d.ts +172 -0
  440. package/lib/core/index.js +12 -0
  441. package/lib/environments.json +18 -0
  442. package/lib/github-comment-formatter.js +263 -0
  443. package/lib/github-comment.mjs +452 -0
  444. package/lib/init-project.js +575 -0
  445. package/lib/presets/index.mjs +331 -0
  446. package/lib/resolve-channel.js +46 -0
  447. package/lib/sentry.js +417 -0
  448. package/lib/vitest/hooks.d.ts +57 -0
  449. package/lib/vitest/hooks.mjs +674 -0
  450. package/lib/vitest/setup-aws.mjs +247 -0
  451. package/lib/vitest/setup-self-hosted.mjs +151 -0
  452. package/lib/vitest/setup.mjs +46 -0
  453. package/manual/captcha-api.test.mjs +51 -0
  454. package/manual/drag-and-drop.test.mjs +59 -0
  455. package/manual/flake-diffthreshold-001.test.mjs +9 -0
  456. package/manual/flake-diffthreshold-01.test.mjs +9 -0
  457. package/manual/flake-diffthreshold-05.test.mjs +9 -0
  458. package/manual/flake-noredraw-cache.test.mjs +9 -0
  459. package/manual/flake-noredraw-nocache.test.mjs +9 -0
  460. package/manual/flake-redraw-cache.test.mjs +9 -0
  461. package/manual/flake-redraw-nocache.test.mjs +9 -0
  462. package/manual/flake-rocket-match.test.mjs +30 -0
  463. package/manual/flake-shared.mjs +51 -0
  464. package/manual/no-provision.test.mjs +31 -0
  465. package/manual/packer-hover-image.test.mjs +176 -0
  466. package/manual/scroll-until-text.test.mjs +68 -0
  467. package/manual/test-init-command.js +223 -0
  468. package/mcp-server/README.md +322 -0
  469. package/mcp-server/dist/codegen.d.ts +9 -0
  470. package/mcp-server/dist/codegen.js +165 -0
  471. package/mcp-server/dist/mcp-app.html +114 -0
  472. package/mcp-server/dist/package.json +1 -0
  473. package/mcp-server/dist/provision-types.d.ts +290 -0
  474. package/mcp-server/dist/provision-types.js +174 -0
  475. package/mcp-server/dist/server.d.ts +6 -0
  476. package/mcp-server/dist/server.mjs +1925 -0
  477. package/mcp-server/dist/session.d.ts +85 -0
  478. package/mcp-server/dist/session.js +152 -0
  479. package/mcp-server/mcp-app.html +28 -0
  480. package/mcp-server/mcp-config.example.json +19 -0
  481. package/mcp-server/package-lock.json +4027 -0
  482. package/mcp-server/package.json +31 -0
  483. package/mcp-server/src/codegen.ts +189 -0
  484. package/mcp-server/src/mcp-app.css +360 -0
  485. package/mcp-server/src/mcp-app.ts +547 -0
  486. package/mcp-server/src/provision-types.ts +209 -0
  487. package/mcp-server/src/server.ts +2391 -0
  488. package/mcp-server/src/session.ts +194 -0
  489. package/mcp-server/tsconfig.json +16 -0
  490. package/mcp-server/vite.config.ts +23 -0
  491. package/package.json +158 -0
  492. package/schema.json +1046 -0
  493. package/scripts/generate-skills.js +94 -0
  494. package/sdk-log-formatter.js +1157 -0
  495. package/sdk.d.ts +1486 -0
  496. package/sdk.js +4336 -0
  497. package/setup/aws/cloudformation.yaml +463 -0
  498. package/setup/aws/disable-defender.sh +42 -0
  499. package/setup/aws/install-dev-runner.sh +79 -0
  500. package/setup/aws/spawn-runner.sh +289 -0
  501. package/test/captcha-solver.test.mjs +152 -0
  502. package/test/chrome-remote-debugging.test.mjs +66 -0
  503. package/test/duckduckgo/experiment.test.mjs +28 -0
  504. package/test/duckduckgo/setup.test.mjs +29 -0
  505. package/test/manual/debug-locate-response.js +82 -0
  506. package/test/manual/reconnect-provision.test.mjs +49 -0
  507. package/test/manual/test-console-logs.test.mjs +42 -0
  508. package/test/manual/test-find-api.js +73 -0
  509. package/test/manual/test-init.sh +54 -0
  510. package/test/manual/test-prompt-cache.js +97 -0
  511. package/test/manual/test-provision-auth.mjs +22 -0
  512. package/test/manual/test-sandbox-render.js +29 -0
  513. package/test/manual/test-sdk-methods.js +15 -0
  514. package/test/manual/test-sdk-refactor.js +53 -0
  515. package/test/manual/test-stack-trace.mjs +57 -0
  516. package/test/manual/verify-element-api.js +89 -0
  517. package/test/manual/verify-types.js +0 -0
  518. package/test/manual-unawaited-promise.test.mjs +31 -0
  519. package/vitest.config.mjs +58 -0
  520. package/vitest.runner.config.mjs +33 -0
  521. package/vscode-extension/.vscodeignore +12 -0
  522. package/vscode-extension/README.md +94 -0
  523. package/vscode-extension/media/icon.png +0 -0
  524. package/vscode-extension/package-lock.json +4126 -0
  525. package/vscode-extension/package.json +86 -0
  526. package/vscode-extension/src/extension.ts +829 -0
  527. package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
  528. package/vscode-extension/tsconfig.json +16 -0
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # --- Config (reads from env) ---
5
+ : "${AWS_REGION:?Set AWS_REGION}"
6
+ : "${AMI_ID:?Set AMI_ID (TestDriver Ami)}"
7
+ : "${AWS_LAUNCH_TEMPLATE_ID:?Set AWS_LAUNCH_TEMPLATE_ID}"
8
+ : "${AWS_LAUNCH_TEMPLATE_VERSION:=\$Latest}"
9
+ : "${AWS_TAG_PREFIX:=td}"
10
+ : "${RUNNER_CLASS_ID:=default}"
11
+ : "${RESOLUTION:=1440x900}"
12
+
13
+ TAG_NAME="${AWS_TAG_PREFIX}-"$(date +%s)
14
+
15
+ echo "Launching AWS Instance..."
16
+
17
+ # --- 1) Launch instance ---
18
+ RUN_JSON=$(aws ec2 run-instances \
19
+ --region "$AWS_REGION" \
20
+ --image-id "$AMI_ID" \
21
+ --launch-template "LaunchTemplateId=$AWS_LAUNCH_TEMPLATE_ID,Version=$AWS_LAUNCH_TEMPLATE_VERSION" \
22
+ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=${TAG_NAME}},{Key=Class,Value=${RUNNER_CLASS_ID}},{Key=TD_RESOLUTION,Value=${RESOLUTION}}]" \
23
+ --output json)
24
+
25
+ INSTANCE_ID=$(jq -r '.Instances[0].InstanceId' <<<"$RUN_JSON")
26
+
27
+ echo "Launched: $INSTANCE_ID"
28
+ echo "Instance details:"
29
+ echo " Region: $AWS_REGION"
30
+ echo " AMI ID: $AMI_ID"
31
+ echo " Launch Template ID: $AWS_LAUNCH_TEMPLATE_ID"
32
+ echo " Launch Template Version: $AWS_LAUNCH_TEMPLATE_VERSION"
33
+
34
+ echo "Waiting for instance to be running..."
35
+
36
+ # --- 2) Wait for running + status checks ---
37
+ aws ec2 wait instance-running --region "$AWS_REGION" --instance-ids "$INSTANCE_ID"
38
+ echo "✓ Instance is now running"
39
+
40
+ echo "Waiting for instance to pass status checks..."
41
+
42
+ aws ec2 wait instance-status-ok --region "$AWS_REGION" --instance-ids "$INSTANCE_ID"
43
+ echo "✓ Instance passed all status checks"
44
+
45
+ # Additional validation - check instance state details
46
+ echo "Validating instance readiness..."
47
+ INSTANCE_STATE=$(aws ec2 describe-instances --region "$AWS_REGION" --instance-ids "$INSTANCE_ID" \
48
+ --query 'Reservations[0].Instances[0].{State:State.Name,StatusChecks:StateTransitionReason}' \
49
+ --output json)
50
+ echo "Instance state details: $INSTANCE_STATE"
51
+
52
+ # --- 3) Ensure SSM connectivity ---
53
+ echo "Waiting for SSM connectivity..."
54
+ echo "This can take several minutes for the SSM agent to be fully ready..."
55
+
56
+ # First, check if the instance is registered with SSM
57
+ echo "Checking SSM instance registration..."
58
+ TRIES=0; MAX_TRIES=60
59
+ while :; do
60
+ echo "Attempt $((TRIES+1))/$MAX_TRIES: Checking if instance is registered with SSM..."
61
+
62
+ # Check if instance appears in SSM managed instances
63
+ if aws ssm describe-instance-information \
64
+ --region "$AWS_REGION" \
65
+ --filters "Key=InstanceIds,Values=$INSTANCE_ID" \
66
+ --query 'InstanceInformationList[0].InstanceId' \
67
+ --output text 2>/dev/null | grep -q "$INSTANCE_ID"; then
68
+ echo "✓ Instance is registered with SSM"
69
+ break
70
+ fi
71
+
72
+ TRIES=$((TRIES+1))
73
+ if [ $TRIES -ge $MAX_TRIES ]; then
74
+ echo "❌ SSM registration timeout - instance may not have proper IAM role or SSM agent"
75
+ echo "Checking instance details for debugging..."
76
+ aws ec2 describe-instances --region "$AWS_REGION" --instance-ids "$INSTANCE_ID" \
77
+ --query 'Reservations[0].Instances[0].{State:State.Name,IAMProfile:IamInstanceProfile.Arn,SecurityGroups:SecurityGroups[].GroupId}' \
78
+ --output table
79
+ exit 2
80
+ fi
81
+ echo "Instance not yet registered with SSM, waiting..."
82
+ sleep 10
83
+ done
84
+
85
+ # Now test SSM command execution
86
+ echo "Testing SSM command execution..."
87
+ TRIES=0; MAX_TRIES=30
88
+ while :; do
89
+ echo "Attempt $((TRIES+1))/$MAX_TRIES: Sending test SSM command..."
90
+
91
+ if CMD_JSON=$(aws ssm send-command \
92
+ --region "$AWS_REGION" \
93
+ --targets "Key=instanceIds,Values=$INSTANCE_ID" \
94
+ --document-name "AWS-RunPowerShellScript" \
95
+ --parameters 'commands=["echo SSM connectivity test successful"]' \
96
+ --output json 2>/dev/null); then
97
+
98
+ COMMAND_ID=$(jq -r '.Command.CommandId' <<<"$CMD_JSON")
99
+ echo "✓ SSM command sent successfully (Command ID: $COMMAND_ID)"
100
+
101
+ # Wait for command to complete and check status
102
+ echo "Waiting for command execution..."
103
+ if aws ssm wait command-executed --region "$AWS_REGION" --command-id "$COMMAND_ID" --instance-id "$INSTANCE_ID" 2>/dev/null; then
104
+ echo "✓ SSM connectivity confirmed"
105
+ break
106
+ else
107
+ echo "⚠ Command execution may have failed, checking status..."
108
+ CMD_STATUS=$(aws ssm get-command-invocation \
109
+ --region "$AWS_REGION" \
110
+ --command-id "$COMMAND_ID" \
111
+ --instance-id "$INSTANCE_ID" \
112
+ --query 'Status' \
113
+ --output text 2>/dev/null || echo "Unknown")
114
+ echo "Command status: $CMD_STATUS"
115
+
116
+ if [ "$CMD_STATUS" = "Success" ]; then
117
+ echo "✓ Command actually succeeded"
118
+ break
119
+ fi
120
+ fi
121
+ else
122
+ echo "⚠ Failed to send SSM command"
123
+ fi
124
+
125
+ TRIES=$((TRIES+1))
126
+ if [ $TRIES -ge $MAX_TRIES ]; then
127
+ echo "❌ SSM command execution timeout"
128
+ echo "Final debugging information:"
129
+
130
+ # Get SSM agent status
131
+ echo "SSM Agent status on instance:"
132
+ aws ssm describe-instance-information \
133
+ --region "$AWS_REGION" \
134
+ --filters "Key=InstanceIds,Values=$INSTANCE_ID" \
135
+ --query 'InstanceInformationList[0].{PingStatus:PingStatus,LastPingDateTime:LastPingDateTime,AgentVersion:AgentVersion}' \
136
+ --output table 2>/dev/null || echo "Could not retrieve SSM status"
137
+
138
+ exit 2
139
+ fi
140
+ echo "Retrying in 20 seconds..."
141
+ sleep 20
142
+ done
143
+
144
+ # --- 4) Install/update runner ---
145
+ echo "Installing runner..."
146
+
147
+ # Determine environment and version
148
+ TD_ENV="${TD_ENV:-stable}"
149
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
150
+ SDK_PKG_JSON="${SCRIPT_DIR}/../../../sdk/package.json"
151
+ RUNNER_DIR="${SCRIPT_DIR}/../../../runner"
152
+
153
+ if [ -f "$SDK_PKG_JSON" ]; then
154
+ RUNNER_VERSION=$(jq -r '.version' "$SDK_PKG_JSON")
155
+ echo "Runner version from SDK: $RUNNER_VERSION"
156
+ else
157
+ RUNNER_VERSION="$TD_ENV"
158
+ echo "SDK package.json not found, using env tag: $RUNNER_VERSION"
159
+ fi
160
+
161
+ if [ "$TD_ENV" = "dev" ]; then
162
+ echo "Dev mode: packing and uploading local runner to S3..."
163
+
164
+ # Pack local runner
165
+ TMPDIR=$(mktemp -d)
166
+ pushd "$RUNNER_DIR" > /dev/null
167
+ npm pack --pack-destination "$TMPDIR" > /dev/null 2>&1
168
+ TARBALL=$(ls "$TMPDIR"/*.tgz | head -1)
169
+ popd > /dev/null
170
+
171
+ # Upload to S3
172
+ S3_BUCKET="${AWS_BUCKET_IMAGE_TRANSFER:-v7-transfer}"
173
+ S3_KEY="runner-dev/$(date +%s)-$(openssl rand -hex 4)/runner.tgz"
174
+ aws s3 cp "$TARBALL" "s3://${S3_BUCKET}/${S3_KEY}" --region "$AWS_REGION"
175
+
176
+ # Generate presigned URL (15 min)
177
+ DOWNLOAD_URL=$(aws s3 presign "s3://${S3_BUCKET}/${S3_KEY}" --expires-in 900 --region "$AWS_REGION")
178
+ rm -rf "$TMPDIR"
179
+
180
+ # Build SSM parameters JSON in a temp file to avoid shell escaping issues with URL
181
+ PARAMS_FILE=$(mktemp)
182
+ cat > "$PARAMS_FILE" << 'PARAMS_EOF'
183
+ {
184
+ "commands": [
185
+ "Write-Host '=== Starting runner dev install ==='",
186
+ "Write-Host 'Stopping existing runner processes...'",
187
+ "Stop-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue",
188
+ "Stop-Process -Name node -Force -ErrorAction SilentlyContinue",
189
+ "Start-Sleep -Seconds 2",
190
+ "Write-Host 'Current runner version:'",
191
+ "Get-Content 'C:\\testdriver\\sandbox-agent\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
192
+ "Set-Location 'C:\\testdriver\\sandbox-agent'",
193
+ "Write-Host 'Dev mode: downloading runner from S3...'",
194
+ "$tarball = 'C:\\Windows\\Temp\\runner-dev.tgz'",
195
+ PARAMS_EOF
196
+
197
+ # Add the URL line with proper JSON escaping
198
+ echo " \"Invoke-WebRequest -Uri '$(echo "$DOWNLOAD_URL" | sed 's/"/\\"/g')' -OutFile \$tarball\"," >> "$PARAMS_FILE"
199
+
200
+ cat >> "$PARAMS_FILE" << 'PARAMS_EOF'
201
+ "Write-Host 'Downloaded tarball size:'",
202
+ "(Get-Item $tarball).Length",
203
+ "Write-Host 'Extracting runner...'",
204
+ "tar -xzf $tarball -C 'C:\\Windows\\Temp'",
205
+ "Write-Host 'Extracted package contents:'",
206
+ "Get-ChildItem 'C:\\Windows\\Temp\\package' -Recurse | Select-Object FullName",
207
+ "Write-Host 'New runner version in package:'",
208
+ "Get-Content 'C:\\Windows\\Temp\\package\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
209
+ "Write-Host 'Clearing old lib folder...'",
210
+ "Remove-Item 'C:\\testdriver\\sandbox-agent\\lib' -Recurse -Force -ErrorAction SilentlyContinue",
211
+ "Write-Host 'Copying files to sandbox-agent...'",
212
+ "xcopy 'C:\\Windows\\Temp\\package\\*' 'C:\\testdriver\\sandbox-agent\\' /E /Y /I",
213
+ "Write-Host 'Files after copy:'",
214
+ "Get-ChildItem 'C:\\testdriver\\sandbox-agent' | Select-Object Name",
215
+ "Remove-Item 'C:\\Windows\\Temp\\package' -Recurse -Force -ErrorAction SilentlyContinue",
216
+ "Remove-Item $tarball -Force -ErrorAction SilentlyContinue",
217
+ "Write-Host 'Runner version after copy:'",
218
+ "Get-Content 'C:\\testdriver\\sandbox-agent\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
219
+ "Write-Host 'Installing npm dependencies...'",
220
+ "npm install --omit=dev 2>&1 | Write-Host",
221
+ "Write-Host 'Final verification - ably-service.js exists:'",
222
+ "Test-Path 'C:\\testdriver\\sandbox-agent\\lib\\ably-service.js'",
223
+ "Write-Host 'Restarting RunTestDriverAgent scheduled task...'",
224
+ "Start-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue",
225
+ "Write-Host '=== Runner install complete (dev) ==='"
226
+ ]
227
+ }
228
+ PARAMS_EOF
229
+
230
+ echo "Sending SSM command to download and install runner from S3..."
231
+ INSTALL_CMD=$(aws ssm send-command \
232
+ --region "$AWS_REGION" \
233
+ --instance-ids "$INSTANCE_ID" \
234
+ --document-name "AWS-RunPowerShellScript" \
235
+ --parameters "file://$PARAMS_FILE" \
236
+ --timeout-seconds 180 \
237
+ --output json)
238
+ rm -f "$PARAMS_FILE"
239
+ else
240
+ echo "Installing @testdriverai/runner@${RUNNER_VERSION} via npm..."
241
+ INSTALL_CMD=$(aws ssm send-command \
242
+ --region "$AWS_REGION" \
243
+ --instance-ids "$INSTANCE_ID" \
244
+ --document-name "AWS-RunPowerShellScript" \
245
+ --parameters "commands=[
246
+ \"Set-Location 'C:\\\\testdriver\\\\sandbox-agent'\",
247
+ \"Write-Host 'Installing @testdriverai/runner@${RUNNER_VERSION}...'\",
248
+ \"npm install @testdriverai/runner@${RUNNER_VERSION} --omit=dev 2>&1 | Write-Host\",
249
+ \"Write-Host 'Stopping runner (config not yet provisioned)...'\",
250
+ \"Stop-Process -Name node -Force -ErrorAction SilentlyContinue\",
251
+ \"Stop-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue\",
252
+ \"Start-Sleep -Seconds 2\",
253
+ \"Start-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue\",
254
+ \"Write-Host 'Runner install complete'\"
255
+ ]" \
256
+ --timeout-seconds 120 \
257
+ --output json)
258
+ fi
259
+
260
+ INSTALL_CMD_ID=$(jq -r '.Command.CommandId' <<<"$INSTALL_CMD")
261
+ echo "Runner install command sent (Command ID: $INSTALL_CMD_ID)"
262
+
263
+ # Wait for install to complete
264
+ echo "Waiting for runner install to complete..."
265
+ if aws ssm wait command-executed --region "$AWS_REGION" --command-id "$INSTALL_CMD_ID" --instance-id "$INSTANCE_ID" 2>/dev/null; then
266
+ echo "✓ Runner install succeeded"
267
+ else
268
+ INSTALL_STATUS=$(aws ssm get-command-invocation \
269
+ --region "$AWS_REGION" \
270
+ --command-id "$INSTALL_CMD_ID" \
271
+ --instance-id "$INSTANCE_ID" \
272
+ --output json 2>/dev/null || echo '{}')
273
+ echo "⚠ Runner install status: $(jq -r '.Status // "Unknown"' <<<"$INSTALL_STATUS")"
274
+ echo "Output: $(jq -r '.StandardOutputContent // "No output"' <<<"$INSTALL_STATUS" | head -20)"
275
+ echo "Errors: $(jq -r '.StandardErrorContent // "No errors"' <<<"$INSTALL_STATUS" | head -10)"
276
+ fi
277
+
278
+ echo "Getting Public IP..."
279
+
280
+ # --- 5) Get instance Public IP ---
281
+ DESC_JSON=$(aws ec2 describe-instances --region "$AWS_REGION" --instance-ids "$INSTANCE_ID" --output json)
282
+ PUBLIC_IP=$(jq -r '.Reservations[0].Instances[0].PublicIpAddress // empty' <<<"$DESC_JSON")
283
+ [ -n "$PUBLIC_IP" ] || PUBLIC_IP="No public IP assigned"
284
+
285
+ # --- 6) Output results ---
286
+ echo "Setup complete!"
287
+ echo "PUBLIC_IP=$PUBLIC_IP"
288
+ echo "INSTANCE_ID=$INSTANCE_ID"
289
+ echo "AWS_REGION=$AWS_REGION"
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Unit tests for the captcha solver script
3
+ * These tests verify the solver script is valid JavaScript and can be loaded correctly
4
+ */
5
+ import { describe, expect, it } from "vitest";
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import { fileURLToPath } from "url";
9
+ import vm from "vm";
10
+
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ const solverPath = path.join(__dirname, "..", "lib", "captcha", "solver.js");
13
+
14
+ // Extract safeParseJson function from the solver script for testing
15
+ function getSafeParseJson() {
16
+ const script = fs.readFileSync(solverPath, "utf8");
17
+ // Extract the safeParseJson function source
18
+ const funcMatch = script.match(
19
+ /function safeParseJson\(text\) \{[\s\S]*?^}/m,
20
+ );
21
+ if (!funcMatch) {
22
+ throw new Error("Could not find safeParseJson function in solver script");
23
+ }
24
+ // Create and return the function
25
+ const func = new Function("return " + funcMatch[0])();
26
+ return func;
27
+ }
28
+
29
+ describe("Captcha Solver Script", () => {
30
+ it("should exist", () => {
31
+ expect(fs.existsSync(solverPath)).toBe(true);
32
+ });
33
+
34
+ it("should be valid JavaScript syntax", () => {
35
+ const script = fs.readFileSync(solverPath, "utf8");
36
+
37
+ // This will throw if the syntax is invalid
38
+ expect(() => {
39
+ new vm.Script(script, { filename: "solver.js" });
40
+ }).not.toThrow();
41
+ });
42
+
43
+ it("should contain required functions and variables", () => {
44
+ const script = fs.readFileSync(solverPath, "utf8");
45
+
46
+ // Check for key components
47
+ expect(script).toContain('require("https")');
48
+ expect(script).toContain('require("chrome-remote-interface")');
49
+ expect(script).toContain("detectCaptchaScript");
50
+ expect(script).toContain("getInjectScript");
51
+ expect(script).toContain("autoSubmitScript");
52
+ expect(script).toContain("checkSuccessScript");
53
+ expect(script).toContain("2captcha.com");
54
+ });
55
+
56
+ it("should handle all supported captcha types", () => {
57
+ const script = fs.readFileSync(solverPath, "utf8");
58
+
59
+ // Check for captcha type handling
60
+ expect(script).toContain("recaptcha_v2");
61
+ expect(script).toContain("recaptcha_v3");
62
+ expect(script).toContain("hcaptcha");
63
+ expect(script).toContain("turnstile");
64
+ });
65
+
66
+ it("should have proper auto-detection for captcha elements", () => {
67
+ const script = fs.readFileSync(solverPath, "utf8");
68
+
69
+ // Check for DOM selectors used in auto-detection
70
+ expect(script).toContain(".g-recaptcha[data-sitekey]");
71
+ expect(script).toContain(".h-captcha[data-sitekey]");
72
+ expect(script).toContain(".cf-turnstile[data-sitekey]");
73
+ expect(script).toContain("[data-sitekey]");
74
+ });
75
+
76
+ it("should properly inject tokens into response fields", () => {
77
+ const script = fs.readFileSync(solverPath, "utf8");
78
+
79
+ // Check for token injection selectors
80
+ expect(script).toContain("[name=g-recaptcha-response]");
81
+ expect(script).toContain("[name=h-captcha-response]");
82
+ expect(script).toContain("[name=cf-turnstile-response]");
83
+ expect(script).toContain("___grecaptcha_cfg");
84
+ });
85
+
86
+ it("should contain safeParseJson function for robust JSON parsing", () => {
87
+ const script = fs.readFileSync(solverPath, "utf8");
88
+ expect(script).toContain("function safeParseJson");
89
+ expect(script).toContain("safeParseJson(await httpsGet");
90
+ });
91
+ });
92
+
93
+ describe("safeParseJson", () => {
94
+ let safeParseJson;
95
+ let extractionFailed = false;
96
+
97
+ // Try to extract the function for testing
98
+ try {
99
+ safeParseJson = getSafeParseJson();
100
+ } catch {
101
+ extractionFailed = true;
102
+ }
103
+
104
+ // Use it.skipIf to clearly indicate skipped tests
105
+ const testFn = extractionFailed ? it.skip : it;
106
+
107
+ testFn("should parse valid JSON normally", () => {
108
+ const result = safeParseJson('{"status":1,"request":"abc123"}');
109
+ expect(result).toEqual({ status: 1, request: "abc123" });
110
+ });
111
+
112
+ testFn("should handle JSON with leading/trailing whitespace", () => {
113
+ const result = safeParseJson(' {"status":1} \n');
114
+ expect(result).toEqual({ status: 1 });
115
+ });
116
+
117
+ testFn("should extract first JSON object from concatenated responses", () => {
118
+ // This is the exact error case: multiple JSON objects concatenated
119
+ const result = safeParseJson('{"status":1}{"status":2}');
120
+ expect(result).toEqual({ status: 1 });
121
+ });
122
+
123
+ testFn("should handle JSON with trailing garbage characters", () => {
124
+ const result = safeParseJson('{"status":1}xxx');
125
+ expect(result).toEqual({ status: 1 });
126
+ });
127
+
128
+ testFn("should handle nested objects correctly", () => {
129
+ const result = safeParseJson('{"data":{"nested":true}}extra');
130
+ expect(result).toEqual({ data: { nested: true } });
131
+ });
132
+
133
+ testFn("should handle strings containing braces", () => {
134
+ const result = safeParseJson('{"text":"hello {world}"}extra');
135
+ expect(result).toEqual({ text: "hello {world}" });
136
+ });
137
+
138
+ testFn("should handle escaped quotes in strings", () => {
139
+ const result = safeParseJson('{"text":"say \\"hello\\""}extra');
140
+ expect(result).toEqual({ text: 'say "hello"' });
141
+ });
142
+
143
+ testFn("should throw for responses without JSON", () => {
144
+ expect(() => safeParseJson("not json at all")).toThrow(
145
+ "No JSON object found",
146
+ );
147
+ });
148
+
149
+ testFn("should throw for incomplete JSON", () => {
150
+ expect(() => safeParseJson('{"incomplete')).toThrow("Invalid JSON");
151
+ });
152
+ });
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Test that validates Chrome remote debugging is working
3
+ * Installs chrome-remote-interface and connects to the active tab
4
+ */
5
+ import { describe, expect, it } from "vitest";
6
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
7
+
8
+ describe("Chrome Remote Debugging", () => {
9
+
10
+ it("should connect to Chrome via CDP and get page title", async (context) => {
11
+ const testdriver = TestDriver(context);
12
+
13
+ // Launch Chrome with a known URL
14
+ await testdriver.provision.chrome({
15
+ url: 'https://example.com',
16
+ });
17
+
18
+ // Take a screenshot to verify Chrome launched
19
+ await testdriver.screenshot();
20
+
21
+ // Install chrome-remote-interface (needs sudo for global install)
22
+ const installResult = await testdriver.exec(
23
+ 'sh',
24
+ 'sudo npm install -g chrome-remote-interface',
25
+ 60000
26
+ );
27
+ console.log('Install result:', installResult);
28
+
29
+ // Write the CDP script to a file to avoid quoting issues
30
+ const cdpScript = `
31
+ const CDP = require('chrome-remote-interface');
32
+ (async () => {
33
+ try {
34
+ const client = await CDP();
35
+ const { Runtime } = client;
36
+ const result = await Runtime.evaluate({
37
+ expression: 'document.title'
38
+ });
39
+ console.log('PAGE_TITLE:' + result.result.value);
40
+ await client.close();
41
+ process.exit(0);
42
+ } catch (err) {
43
+ console.error('CDP_ERROR:' + err.message);
44
+ process.exit(1);
45
+ }
46
+ })();
47
+ `;
48
+
49
+ // Write script to file
50
+ await testdriver.exec('sh', `cat > /tmp/cdp-test.js << 'SCRIPT'
51
+ ${cdpScript}
52
+ SCRIPT`, 5000);
53
+
54
+ // Run the CDP script with NODE_PATH set to find globally installed modules
55
+ const cdpResult = await testdriver.exec(
56
+ 'sh',
57
+ 'NODE_PATH=/usr/lib/node_modules node /tmp/cdp-test.js 2>&1 || echo "CDP_EXIT_CODE:$?"',
58
+ 30000
59
+ );
60
+ console.log('CDP result:', cdpResult);
61
+
62
+ // Verify we got the page title
63
+ expect(cdpResult).toContain('PAGE_TITLE:');
64
+ expect(cdpResult).toContain('Example Domain');
65
+ });
66
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Experiment file - reconnects to existing sandbox
3
+ * Run AFTER setup.test.mjs passes
4
+ */
5
+ import { describe, expect, it } from "vitest";
6
+ import { TestDriver } from "../../lib/vitest/hooks.mjs";
7
+
8
+ describe("Experiment DuckDuckGo", () => {
9
+ it("should search for apples", async (context) => {
10
+ const testdriver = TestDriver(context, {
11
+ reconnect: true, // ← Key: reconnects to last sandbox
12
+ });
13
+
14
+ // NO provision here! The sandbox is already running from setup.test.mjs
15
+
16
+ // Find search input and type
17
+ const searchInput = await testdriver.find("search input");
18
+ await searchInput.click();
19
+ await testdriver.type("apples");
20
+ await testdriver.pressKeys(["enter"]);
21
+
22
+ // Assert results
23
+ const result = await testdriver.assert(
24
+ "I can see search results for apples",
25
+ );
26
+ expect(result).toBeTruthy();
27
+ });
28
+ });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Setup file - MINIMAL steps to get to starting state
3
+ * Only add more steps AFTER this passes!
4
+ */
5
+ import { afterAll, describe, expect, it } from "vitest";
6
+ import { TestDriver } from "../../lib/vitest/hooks.mjs";
7
+
8
+ describe("Setup DuckDuckGo", () => {
9
+ afterAll(async () => {
10
+ // DO NOT disconnect - keep sandbox alive for reconnect
11
+ console.log("Sandbox staying alive for 30 seconds (keepAlive)");
12
+ });
13
+
14
+ it("should set up the application state", async (context) => {
15
+ const testdriver = TestDriver(context);
16
+
17
+ await testdriver.provision.chrome({
18
+ url: "https://duckduckgo.com",
19
+ });
20
+
21
+ // Start with just ONE assertion to verify we're on the right page
22
+ const result = await testdriver.assert(
23
+ "I can see the DuckDuckGo search page",
24
+ );
25
+ expect(result).toBeTruthy();
26
+
27
+ console.log("✅ Setup ready - run experiment.test.mjs now");
28
+ });
29
+ });
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Debug script to inspect the full locate API response
5
+ * Run this with: TD_API_KEY=your_key node debug-locate-response.js
6
+ */
7
+
8
+ const TestDriverSDK = require("./sdk.js");
9
+
10
+ async function debugLocateResponse() {
11
+ const client = new TestDriverSDK(process.env.TD_API_KEY);
12
+
13
+ try {
14
+ console.log("Connecting to sandbox (Linux)...");
15
+ await client.connect({ headless: true });
16
+
17
+ console.log("Opening a test page...");
18
+ await client.focusApplication("Google Chrome");
19
+ await client.type("https://example.com");
20
+ await client.pressKeys(["enter"]);
21
+
22
+ // Wait for page to load
23
+ await new Promise((resolve) => setTimeout(resolve, 3000));
24
+
25
+ console.log("\nFinding an element to inspect the response...");
26
+ const element = await client.find("the heading that says Example Domain");
27
+
28
+ console.log("\n=".repeat(60));
29
+ console.log("FULL LOCATE API RESPONSE:");
30
+ console.log("=".repeat(60));
31
+
32
+ const response = element.getResponse();
33
+ console.log(JSON.stringify(response, null, 2));
34
+
35
+ console.log("\n=".repeat(60));
36
+ console.log("RESPONSE KEYS:");
37
+ console.log("=".repeat(60));
38
+
39
+ if (response) {
40
+ Object.keys(response).forEach((key) => {
41
+ const value = response[key];
42
+ const type = Array.isArray(value) ? "array" : typeof value;
43
+ const preview =
44
+ typeof value === "string" && value.length > 100
45
+ ? `${value.substring(0, 100)}... (${value.length} chars)`
46
+ : typeof value === "object"
47
+ ? JSON.stringify(value)
48
+ : value;
49
+
50
+ console.log(` ${key} (${type}): ${preview}`);
51
+ });
52
+ }
53
+
54
+ console.log("\n=".repeat(60));
55
+ console.log("ELEMENT PROPERTIES:");
56
+ console.log("=".repeat(60));
57
+ console.log(" found:", element.found());
58
+ console.log(" x:", element.x);
59
+ console.log(" y:", element.y);
60
+ console.log(" centerX:", element.centerX);
61
+ console.log(" centerY:", element.centerY);
62
+ console.log(" width:", element.width);
63
+ console.log(" height:", element.height);
64
+ console.log(" confidence:", element.confidence);
65
+ console.log(" text:", element.text);
66
+ console.log(" label:", element.label);
67
+ console.log(
68
+ " screenshot:",
69
+ element.screenshot ? `${element.screenshot.length} chars` : null,
70
+ );
71
+ console.log(" boundingBox:", element.boundingBox);
72
+
73
+ await client.disconnect();
74
+ } catch (error) {
75
+ console.error("Error:", error.message);
76
+ console.error(error.stack);
77
+ await client.disconnect();
78
+ process.exit(1);
79
+ }
80
+ }
81
+
82
+ debugLocateResponse();