@testdriverai/agent 7.8.0-canary.10

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,90 @@
1
+ ---
2
+ name: testdriver:waiting-for-elements
3
+ description: Handle async operations and prevent flaky tests
4
+ ---
5
+ <!-- Generated from waiting-for-elements.mdx. DO NOT EDIT. -->
6
+
7
+ ## Waiting for Elements
8
+
9
+ By default, `find()` automatically polls for up to 10 seconds, retrying every 5 seconds until the element is found. This means most elements that appear after short async operations will be found without any extra configuration.
10
+
11
+ For longer operations, increase the `timeout`:
12
+
13
+ ```javascript
14
+ // Default behavior - polls for up to 10 seconds automatically
15
+ const element = await testdriver.find('Loading complete indicator');
16
+ await element.click();
17
+
18
+ // Wait up to 30 seconds for slower operations
19
+ const element = await testdriver.find('Loading complete indicator', { timeout: 30000 });
20
+ await element.click();
21
+
22
+ // Useful after actions that trigger loading states
23
+ await testdriver.find('submit button').click();
24
+ await testdriver.find('success message', { timeout: 15000 });
25
+
26
+ // Disable polling for instant checks
27
+ const toast = await testdriver.find('notification toast', { timeout: 0 });
28
+ ```
29
+
30
+ ## Flake Prevention
31
+
32
+ TestDriver automatically waits for the screen and network to stabilize after each action using **redraw detection**. This prevents flaky tests caused by animations, loading states, or dynamic content updates.
33
+
34
+ <Note>
35
+ Redraw detection adds a small delay after each action but significantly reduces test flakiness.
36
+ </Note>
37
+
38
+ For example, when clicking a submit button that navigates to a new page:
39
+
40
+ ```javascript
41
+ // Click submit - TestDriver automatically waits for the new page to load
42
+ await testdriver.find('submit button').click();
43
+
44
+ // By the time this runs, the page has fully loaded and stabilized
45
+ await testdriver.assert('dashboard is displayed');
46
+ await testdriver.find('welcome message');
47
+ ```
48
+
49
+ Without redraw detection, you'd need manual waits or retries to handle the page transition. TestDriver handles this automatically by detecting when the screen stops changing and network requests complete.
50
+
51
+ You can disable redraw detection or customize its behavior:
52
+
53
+ ```javascript
54
+ // Disable redraw detection for faster tests (less reliable)
55
+ const testdriver = TestDriver(context, {
56
+ redraw: false
57
+ });
58
+ ```
59
+
60
+ Here is an example of customizing redraw detection:
61
+
62
+ ```javascript
63
+ // Fine-tune redraw detection
64
+ const testdriver = TestDriver(context, {
65
+ redraw: {
66
+ enabled: true,
67
+ diffThreshold: 0.1, // Pixel difference threshold (0-1)
68
+ screenRedraw: true, // Monitor screen changes
69
+ networkMonitor: true, // Wait for network idle
70
+ }
71
+ });
72
+ ```
73
+
74
+ ## Simple Delays with `wait()`
75
+
76
+ For simple pauses — waiting for animations, transitions, or state changes after an action — use `wait()`:
77
+
78
+ ```javascript
79
+ // Wait for an animation to complete
80
+ await testdriver.find('menu toggle').click();
81
+ await testdriver.wait(2000);
82
+
83
+ // Wait for a page transition to settle
84
+ await testdriver.find('next page button').click();
85
+ await testdriver.wait(1000);
86
+ ```
87
+
88
+ <Note>
89
+ For waiting for specific **elements** to appear, prefer `find()` with a `timeout` option. Use `wait()` only for simple time-based pauses.
90
+ </Note>
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: testdriver:what-is-testdriver
3
+ description: Reliably test your most difficult user flows
4
+ ---
5
+ <!-- Generated from what-is-testdriver.mdx. DO NOT EDIT. -->
6
+
7
+ ## The problem with modern testing tools
8
+
9
+ Modern testing tools like Playwright are designed to test a single web application, running in a single browser tab using selectors.
10
+
11
+ However, selectors are often either unreliable or unavailable in complex scenarios, leading to brittle and flaky tests:
12
+
13
+ | Challenge | Problem | Examples |
14
+ |-----------|---------|----------|
15
+ | **Fast moving teams** | Frequently change UI structure, breaking CSS/XPath selectors | Agile teams, startups, vibe-coders |
16
+ | **Dynamic content** | Cannot be targeted with selectors | AI chatbots, PDFs, images, videos |
17
+ | **Software you don't own** | May lack proper accessibility attributes | Other websites, extensions, third-party applications |
18
+ | **Multi-application workflows** | Cannot be tested with web-only tools | Desktop apps, browser extensions, IDEs |
19
+ | **Visual states** | Impossible to verify with code-based selectors | Charts, graphs, videos, images, spelling errors, UI layout |
20
+
21
+ ## The TestDriver Solution
22
+
23
+ TestDriver is a complete testing platform built specifically for handling these scenarios. It consists of a Javascript SDK, hosted infrastructure, and debugging tools that make it easy to write, run, and maintain tests for your most difficult user flows.
24
+
25
+ ### Javascript SDK
26
+
27
+ Here is an example of a TestDriver test that installs a production Chrome extension from the Chrome Web Store and verifies that it appears in the extensions menu:
28
+
29
+ ```javascript Installing Loom from the Chrome Web Store
30
+ import { describe, expect, it } from "vitest";
31
+ import { TestDriver } from "testdriverai/vitest/hooks";
32
+
33
+ describe("Chrome Extension Test", () => {
34
+ const testdriver = TestDriver(context);
35
+
36
+ // Launch Chrome with Loom loaded by its Chrome Web Store ID
37
+ await testdriver.provision.chromeExtension({
38
+ extensionId: 'liecbddmkiiihnedobmlmillhodjkdmb'
39
+ });
40
+
41
+ // Click on the extensions button (puzzle piece icon) in Chrome toolbar
42
+ const extensionsButton = await testdriver.find("The puzzle-shaped icon in the Chrome toolbar.");
43
+ await extensionsButton.click();
44
+
45
+ // Look for Loom in the extensions menu
46
+ const loomExtension = await testdriver.find("Loom extension in the extensions dropdown");
47
+ expect(loomExtension.found()).toBeTruthy();
48
+ });
49
+ ```
50
+
51
+
52
+ <Tip>[vitest](https://vitest.dev/) is the preferred test runner for TestDriver.</Tip>
53
+
54
+ ,
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Initialize Sentry first, before any other modules
4
+ const sentry = require("../lib/sentry");
5
+
6
+ // Set process priority if possible
7
+ const os = require("os");
8
+ try {
9
+ const pid = process.pid;
10
+ os.setPriority(pid, -20);
11
+ // eslint-disable-next-line no-unused-vars
12
+ } catch (error) {
13
+ // Ignore if not permitted
14
+ }
15
+
16
+ // Ensure Sentry flushes on exit
17
+ process.on("beforeExit", async () => {
18
+ await sentry.flush();
19
+ });
20
+
21
+ // Run the CLI
22
+ require("../interfaces/cli.js");
Binary file
Binary file
@@ -0,0 +1,469 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
6
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
7
+ <link
8
+ href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
9
+ rel="stylesheet"
10
+ />
11
+ <link rel="icon" type="image/png" href="icon.png" />
12
+ <title>TestDriver - Debugger</title>
13
+ <style>
14
+ body {
15
+ background-color: #111;
16
+ background-image: url("bg.png");
17
+ background-repeat: repeat;
18
+ background-size: auto;
19
+ }
20
+
21
+ * {
22
+ margin: 0;
23
+ padding: 0;
24
+ box-sizing: border-box;
25
+ font-family: "IBM Plex Mono", monospace;
26
+ font-weight: 400;
27
+ font-style: normal;
28
+ font-size: 14px;
29
+ scrollbar-width: none; /* Hide scrollbars for Firefox */
30
+ pointer-events: none;
31
+ }
32
+
33
+ #overlay {
34
+ position: absolute;
35
+ top: 0;
36
+ left: 0;
37
+ transform-origin: top left;
38
+ overflow: hidden;
39
+ }
40
+
41
+ html,
42
+ body {
43
+ overflow: hidden;
44
+ width: 100%;
45
+ height: 100%;
46
+ }
47
+
48
+ *::-webkit-scrollbar {
49
+ display: none; /* Hide scrollbars for WebKit browsers */
50
+ }
51
+
52
+ @keyframes animate-glow {
53
+ 0% {
54
+ opacity: 0;
55
+ filter: brightness(3) saturate(3);
56
+ transform: scale(0.8, 0.8);
57
+ }
58
+
59
+ 30% {
60
+ opacity: 1;
61
+ filter: brightness(1) saturate(1);
62
+ transform: scale(1, 1);
63
+ }
64
+
65
+ 100% {
66
+ /* opacity: 0; */
67
+ opacity: 1;
68
+ transform: scale(1, 1);
69
+ }
70
+ }
71
+
72
+ .overlay {
73
+ position: relative;
74
+ overflow: hidden;
75
+ }
76
+
77
+ .screenshot {
78
+ position: absolute;
79
+ inset: 0;
80
+ z-index: 1;
81
+ opacity: 0;
82
+ }
83
+
84
+ .box {
85
+ border: 1px solid #b0cf34;
86
+ position: absolute;
87
+ border-radius: 5px;
88
+ animation-duration: 5s;
89
+ animation-delay: 0s;
90
+ animation-timing-function: cubic-bezier(0.26, 0.53, 0.74, 1.48);
91
+ animation-fill-mode: backwards;
92
+ animation-name: animate-glow;
93
+ animation-timing-function: ease;
94
+ animation-fill-mode: forwards;
95
+ border-radius: 5px;
96
+ }
97
+
98
+ .effects {
99
+ inset: 0;
100
+ position: absolute;
101
+ z-index: 20;
102
+ }
103
+
104
+ #mouse {
105
+ margin-left: -100px;
106
+ margin-top: -100px;
107
+ width: 50px;
108
+ height: 50px;
109
+ opacity: 0;
110
+ position: absolute;
111
+ transform: translate(-50%, -50%);
112
+ border-radius: 70%;
113
+ background: #b0cf34;
114
+ }
115
+
116
+ #mouse #dot {
117
+ width: 7px;
118
+ height: 7px;
119
+ position: absolute;
120
+ top: 50%;
121
+ left: 50%;
122
+ transform: translate(-50%, -50%);
123
+ border-radius: 50%;
124
+ background-color: black;
125
+ }
126
+
127
+ .single-click {
128
+ animation: singleClick 0.7s ease-in-out forwards;
129
+ }
130
+
131
+ .double-click {
132
+ animation: doubleClick 0.7s ease-in-out forwards;
133
+ }
134
+
135
+ @keyframes singleClick {
136
+ 0% {
137
+ opacity: 1;
138
+ transform: translate(-50%, -50%) scale(1);
139
+ }
140
+
141
+ 100% {
142
+ opacity: 0;
143
+ transform: translate(-50%, -50%) scale(2);
144
+ }
145
+ }
146
+
147
+ @keyframes doubleClick {
148
+ 0% {
149
+ opacity: 1;
150
+ transform: translate(-50%, -50%) scale(1);
151
+ }
152
+
153
+ 45% {
154
+ opacity: 0;
155
+ transform: translate(-50%, -50%) scale(1.2);
156
+ }
157
+
158
+ 55% {
159
+ opacity: 1;
160
+ transform: translate(-50%, -50%) scale(1);
161
+ }
162
+
163
+ 100% {
164
+ opacity: 0;
165
+ transform: scale(2);
166
+ }
167
+ }
168
+
169
+ #boxes {
170
+ position: absolute;
171
+ top: 25px;
172
+ left: 0;
173
+ right: 0;
174
+ bottom: 0;
175
+ z-index: 2;
176
+ }
177
+
178
+ #vm-iframe {
179
+ display: none;
180
+ border: none;
181
+ pointer-events: none; /* view-only by default, enabled on user click */
182
+ position: absolute;
183
+ top: 0px;
184
+ left: 0px;
185
+ width: 100%;
186
+ height: 100%;
187
+ z-index: 1;
188
+ overflow: hidden;
189
+ }
190
+
191
+ #vm-iframe.interactive {
192
+ pointer-events: auto;
193
+ }
194
+
195
+ /* Loading screen styles */
196
+ .loading-screen {
197
+ position: absolute;
198
+ top: 0;
199
+ left: 0;
200
+ width: 100%;
201
+ height: 100%;
202
+ background-color: black;
203
+ display: flex;
204
+ flex-direction: column;
205
+ align-items: center;
206
+ justify-content: center;
207
+ z-index: 10;
208
+ transition: opacity 0.5s ease-out;
209
+ }
210
+
211
+ .loading-screen.hidden {
212
+ opacity: 0;
213
+ pointer-events: none;
214
+ }
215
+
216
+ .loading-text {
217
+ color: #b0cf34;
218
+ font-size: 18px;
219
+ font-weight: 500;
220
+ margin-top: 10px;
221
+ animation: fadeInOut 1.5s infinite;
222
+ }
223
+
224
+ @keyframes pulse {
225
+ 0% {
226
+ transform: scale(1);
227
+ box-shadow: 0 8px 32px rgba(176, 207, 52, 0.3);
228
+ }
229
+ 50% {
230
+ transform: scale(1.05);
231
+ box-shadow: 0 12px 48px rgba(176, 207, 52, 0.5);
232
+ }
233
+ 100% {
234
+ transform: scale(1);
235
+ box-shadow: 0 8px 32px rgba(176, 207, 52, 0.3);
236
+ }
237
+ }
238
+
239
+ @keyframes fadeInOut {
240
+ 0%,
241
+ 100% {
242
+ opacity: 0.6;
243
+ }
244
+ 50% {
245
+ opacity: 1;
246
+ }
247
+ }
248
+
249
+ .status {
250
+ position: absolute;
251
+ top: 20px;
252
+ left: 20px;
253
+ background: rgba(0, 0, 0, 0.8);
254
+ color: #b0cf34;
255
+ padding: 8px 12px;
256
+ border-radius: 4px;
257
+ font-size: 12px;
258
+ z-index: 11;
259
+ opacity: 0;
260
+ transition: opacity 0.3s ease;
261
+ pointer-events: none;
262
+ }
263
+
264
+ .status.visible {
265
+ opacity: 1;
266
+ }
267
+
268
+ .bounding-box {
269
+ position: absolute;
270
+ border: 2px solid #b0cf34;
271
+ background: rgba(176, 207, 52, 0.1);
272
+ pointer-events: none;
273
+ z-index: 9;
274
+ border-radius: 3px;
275
+ animation: animate-glow 0.6s ease-out;
276
+ }
277
+
278
+ .interaction-overlay {
279
+ position: absolute;
280
+ top: 0;
281
+ left: 0;
282
+ width: 100%;
283
+ height: 100%;
284
+ background: rgba(0, 0, 0, 0.5);
285
+ display: flex;
286
+ flex-direction: column;
287
+ align-items: center;
288
+ justify-content: center;
289
+ z-index: 12;
290
+ opacity: 0;
291
+ pointer-events: none;
292
+ transition: opacity 0.3s ease;
293
+ cursor: pointer;
294
+ color: white;
295
+ font-size: 16px;
296
+ font-weight: 500;
297
+ }
298
+
299
+ .interaction-overlay.visible {
300
+ opacity: 1;
301
+ pointer-events: auto;
302
+ }
303
+
304
+ .interaction-overlay .lock-icon {
305
+ width: 48px;
306
+ height: 48px;
307
+ margin-bottom: 12px;
308
+ fill: white;
309
+ }
310
+
311
+ .interaction-overlay .message {
312
+ text-align: center;
313
+ user-select: none;
314
+ }
315
+
316
+ </style>
317
+ </head>
318
+ <body>
319
+ <!-- Loading screen -->
320
+ <div class="loading-screen" id="loading-screen">
321
+ <div class="testdriver-logo">
322
+ <img
323
+ src="https://framerusercontent.com/images/eMQDjLmOzfeu91XBo1VPlIc1WmY.png"
324
+ height="120"
325
+ alt="TestDriver Logo"
326
+ />
327
+ </div>
328
+ <div class="loading-text">Loading...</div>
329
+ </div>
330
+
331
+ <div class="overlay" id="overlay">
332
+ <div class="effects" id="effects">
333
+ <div class="interaction-overlay" id="interaction-overlay">
334
+ <svg class="lock-icon" viewBox="0 0 24 24">
335
+ <path
336
+ d="M18,8h-1V6c0-2.76-2.24-5-5-5S7,3.24,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.71,1.39-3.1,3.1-3.1s3.1,1.39,3.1,3.1V8z"
337
+ />
338
+ </svg>
339
+ <div class="message">Click to interact with VM</div>
340
+ </div>
341
+ </div>
342
+ <iframe id="vm-iframe" src="" credentialless></iframe>
343
+ </div>
344
+
345
+ <script>
346
+ // Parse session data from URL
347
+ const urlParams = new URLSearchParams(window.location.search);
348
+ const data = urlParams.get("data");
349
+ let parsedData;
350
+ if (data) {
351
+ try {
352
+ parsedData = JSON.parse(atob(data));
353
+ } catch (e) {
354
+ console.error("Error parsing data:", e);
355
+ }
356
+ }
357
+ // Demo mode: use mock data if no data param provided (for local dev)
358
+ if (!parsedData || !parsedData.url) {
359
+ const isLocalDev = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1";
360
+ if (isLocalDev) {
361
+ console.log("[Debugger] No data param — using demo mode");
362
+ parsedData = {
363
+ url: "about:blank",
364
+ resolution: [1366, 768],
365
+ testFile: "demo-test.mjs",
366
+ os: "linux",
367
+ token: null,
368
+ };
369
+ } else {
370
+ alert("Missing or invalid data parameter.");
371
+ }
372
+ }
373
+
374
+ // Elements
375
+ const iframe = document.getElementById("vm-iframe");
376
+ const overlay = document.getElementById("overlay");
377
+ const loadingScreen = document.getElementById("loading-screen");
378
+ const interactionOverlay = document.getElementById("interaction-overlay");
379
+
380
+ let isInteractionEnabled = false;
381
+
382
+ const showInteractionOverlay = () => {
383
+ if (!isInteractionEnabled) {
384
+ interactionOverlay.classList.add("visible");
385
+ }
386
+ };
387
+
388
+ const hideInteractionOverlay = () => {
389
+ interactionOverlay.classList.remove("visible");
390
+ isInteractionEnabled = true;
391
+ iframe.classList.add("interactive");
392
+ };
393
+
394
+ const disableInteraction = () => {
395
+ isInteractionEnabled = false;
396
+ iframe.classList.remove("interactive");
397
+ };
398
+
399
+ overlay.addEventListener("mouseenter", showInteractionOverlay);
400
+ overlay.addEventListener("mouseleave", () => {
401
+ if (!isInteractionEnabled) {
402
+ interactionOverlay.classList.remove("visible");
403
+ }
404
+ });
405
+ interactionOverlay.addEventListener("click", hideInteractionOverlay);
406
+
407
+ window.addEventListener("blur", () => {
408
+ showInteractionOverlay();
409
+ disableInteraction();
410
+ });
411
+
412
+ // Set title from test file name
413
+ const testFileName = parsedData?.testFile
414
+ ? parsedData.testFile.split("/").pop().split("\\").pop()
415
+ : "TestDriver";
416
+ document.title = `${testFileName} - Debugger`;
417
+
418
+ // Embed the VNC URL in the iframe with token
419
+ iframe.style.display = "block";
420
+ const vncUrl = new URL(parsedData.url);
421
+ if (parsedData.token) {
422
+ vncUrl.searchParams.set("token", parsedData.token);
423
+ }
424
+ iframe.src = vncUrl.toString();
425
+
426
+ // Hide loading screen once iframe loads
427
+ iframe.addEventListener("load", () => {
428
+ loadingScreen.classList.add("hidden");
429
+ });
430
+ // Fallback: hide loading screen after 5s even if load event doesn't fire
431
+ setTimeout(() => loadingScreen.classList.add("hidden"), 5000);
432
+
433
+ // Resolution from session data
434
+ const overlayWidth = parsedData.resolution?.[0] || 1366;
435
+ const overlayHeight = parsedData.resolution?.[1] || 768;
436
+
437
+ iframe.style.width = overlayWidth + "px";
438
+ iframe.style.height = overlayHeight + "px";
439
+
440
+ // Throttle helper
441
+ function throttle(fn, wait) {
442
+ let last = 0;
443
+ return function (...args) {
444
+ const now = Date.now();
445
+ if (now - last >= wait) { last = now; fn.apply(this, args); }
446
+ };
447
+ }
448
+
449
+ // Responsive: scale and center the overlay to fit the window
450
+ const resizeOverlay = () => {
451
+ const ww = window.innerWidth;
452
+ const wh = window.innerHeight;
453
+ const scale = Math.min(ww / overlayWidth, wh / overlayHeight, 1);
454
+ const sw = overlayWidth * scale;
455
+ const sh = overlayHeight * scale;
456
+
457
+ overlay.style.width = overlayWidth + "px";
458
+ overlay.style.height = overlayHeight + "px";
459
+ overlay.style.position = "absolute";
460
+ overlay.style.transform = scale < 1 ? `scale(${scale})` : "none";
461
+ overlay.style.left = `${(ww - sw) / 2}px`;
462
+ overlay.style.top = `${(wh - sh) / 2}px`;
463
+ };
464
+
465
+ resizeOverlay();
466
+ window.addEventListener("resize", throttle(resizeOverlay, 100));
467
+ </script>
468
+ </body>
469
+ </html>
Binary file
Binary file
Binary file