testdriverai 6.2.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/.github/workflows/acceptance-linux.yml +75 -0
  2. package/.github/workflows/acceptance-sdk-tests.yml +133 -0
  3. package/.vscode/settings.json +5 -1
  4. package/MIGRATION.md +389 -0
  5. package/PLUGIN_MIGRATION.md +222 -0
  6. package/PROMPT_CACHE.md +200 -0
  7. package/SDK_LOGGING.md +222 -0
  8. package/SDK_MIGRATION.md +474 -0
  9. package/SDK_README.md +1122 -0
  10. package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
  11. package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
  12. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  13. package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
  14. package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
  15. package/_testdriver/lifecycle/prerun.yaml +15 -0
  16. package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
  17. package/agent/index.js +258 -68
  18. package/agent/interface.js +15 -0
  19. package/agent/lib/cache.js +142 -0
  20. package/agent/lib/commander.js +1 -39
  21. package/agent/lib/commands.js +143 -188
  22. package/agent/lib/redraw.js +6 -3
  23. package/agent/lib/sandbox.js +19 -5
  24. package/agent/lib/sdk.js +1 -0
  25. package/agent/lib/system.js +0 -3
  26. package/agent/lib/validation.js +1 -7
  27. package/debug-locate-response.js +82 -0
  28. package/debug-screenshot-1763401388589.png +0 -0
  29. package/debugger/index.html +16 -5
  30. package/docs/ARCHITECTURE.md +424 -0
  31. package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
  32. package/docs/QUICK_START_TEST_RECORDING.md +215 -0
  33. package/docs/SDK_AWESOME_LOGS.md +468 -0
  34. package/docs/TEST_RECORDING.md +388 -0
  35. package/docs/docs.json +232 -152
  36. package/docs/sdk-browser-rendering.md +167 -0
  37. package/docs/v6/getting-started/self-hosting.mdx +407 -0
  38. package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
  39. package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
  40. package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
  41. package/docs/v6/overview/comparison.mdx +101 -0
  42. package/docs/v7/README.md +135 -0
  43. package/docs/v7/api/ai.mdx +205 -0
  44. package/docs/v7/api/assert.mdx +285 -0
  45. package/docs/v7/api/assertions.mdx +403 -0
  46. package/docs/v7/api/click.mdx +287 -0
  47. package/docs/v7/api/client.mdx +322 -0
  48. package/docs/v7/api/elements.mdx +479 -0
  49. package/docs/v7/api/exec.mdx +346 -0
  50. package/docs/v7/api/find.mdx +316 -0
  51. package/docs/v7/api/focusApplication.mdx +294 -0
  52. package/docs/v7/api/hover.mdx +279 -0
  53. package/docs/v7/api/pressKeys.mdx +349 -0
  54. package/docs/v7/api/sandbox.mdx +404 -0
  55. package/docs/v7/api/scroll.mdx +300 -0
  56. package/docs/v7/api/type.mdx +314 -0
  57. package/docs/v7/commands/assert.mdx +45 -0
  58. package/docs/v7/commands/exec.mdx +282 -0
  59. package/docs/v7/commands/focus-application.mdx +44 -0
  60. package/docs/v7/commands/hover-image.mdx +69 -0
  61. package/docs/v7/commands/hover-text.mdx +47 -0
  62. package/docs/v7/commands/if.mdx +53 -0
  63. package/docs/v7/commands/match-image.mdx +67 -0
  64. package/docs/v7/commands/press-keys.mdx +87 -0
  65. package/docs/v7/commands/remember.mdx +49 -0
  66. package/docs/v7/commands/run.mdx +44 -0
  67. package/docs/v7/commands/scroll-until-image.mdx +66 -0
  68. package/docs/v7/commands/scroll-until-text.mdx +60 -0
  69. package/docs/v7/commands/scroll.mdx +69 -0
  70. package/docs/v7/commands/type.mdx +45 -0
  71. package/docs/v7/commands/wait-for-image.mdx +54 -0
  72. package/docs/v7/commands/wait-for-text.mdx +48 -0
  73. package/docs/v7/commands/wait.mdx +45 -0
  74. package/docs/v7/getting-started/quickstart.mdx +199 -0
  75. package/docs/v7/guides/migration.mdx +562 -0
  76. package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
  77. package/docs/v7/playwright.mdx +342 -0
  78. package/eslint.config.js +19 -1
  79. package/examples/run-tests-with-recording.sh +70 -0
  80. package/examples/screenshot-example.js +63 -0
  81. package/examples/sdk-awesome-logs-demo.js +177 -0
  82. package/examples/sdk-cache-thresholds.js +96 -0
  83. package/examples/sdk-element-properties.js +155 -0
  84. package/examples/sdk-simple-example.js +65 -0
  85. package/examples/test-recording-example.test.js +166 -0
  86. package/interfaces/cli/lib/base.js +10 -4
  87. package/interfaces/logger.js +2 -1
  88. package/interfaces/shared-test-state.mjs +69 -0
  89. package/interfaces/vitest-plugin.mjs +744 -0
  90. package/mcp-server/AI_GUIDELINES.md +57 -0
  91. package/package.json +18 -5
  92. package/schema.json +8 -29
  93. package/scripts/view-test-results.mjs +96 -0
  94. package/sdk-log-formatter.js +714 -0
  95. package/sdk.d.ts +735 -0
  96. package/sdk.js +1906 -0
  97. package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
  98. package/setup/aws/cloudformation.yaml +9 -2
  99. package/test/mcp-example-test.yaml +27 -0
  100. package/test-find-api.js +73 -0
  101. package/test-prompt-cache.js +96 -0
  102. package/test-sandbox-render.js +28 -0
  103. package/test-sdk-methods.js +15 -0
  104. package/test-sdk-refactor.js +53 -0
  105. package/test-stack-trace.mjs +57 -0
  106. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
  107. package/testdriver/acceptance-sdk/README.md +128 -0
  108. package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
  109. package/testdriver/acceptance-sdk/assert.test.mjs +44 -0
  110. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +70 -0
  111. package/testdriver/acceptance-sdk/element-not-found.test.mjs +38 -0
  112. package/testdriver/acceptance-sdk/exec-js.test.mjs +55 -0
  113. package/testdriver/acceptance-sdk/exec-output.test.mjs +71 -0
  114. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +69 -0
  115. package/testdriver/acceptance-sdk/focus-window.test.mjs +48 -0
  116. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +41 -0
  117. package/testdriver/acceptance-sdk/hover-image.test.mjs +43 -0
  118. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +50 -0
  119. package/testdriver/acceptance-sdk/hover-text.test.mjs +41 -0
  120. package/testdriver/acceptance-sdk/match-image.test.mjs +48 -0
  121. package/testdriver/acceptance-sdk/press-keys.test.mjs +64 -0
  122. package/testdriver/acceptance-sdk/prompt.test.mjs +45 -0
  123. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +52 -0
  124. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +51 -0
  125. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +42 -0
  126. package/testdriver/acceptance-sdk/scroll.test.mjs +50 -0
  127. package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
  128. package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +239 -0
  129. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +648 -0
  130. package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
  131. package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
  132. package/testdriver/acceptance-sdk/type.test.mjs +84 -0
  133. package/verify-element-api.js +89 -0
  134. package/verify-types.js +0 -0
  135. package/vitest.config.example.js +19 -0
  136. package/vitest.config.mjs +65 -0
  137. package/vitest.config.mjs.bak +44 -0
  138. package/.github/workflows/acceptance-v6.yml +0 -169
  139. package/docs/overview/comparison.mdx +0 -82
  140. package/testdriver/lifecycle/prerun.yaml +0 -17
  141. /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
  142. /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
  143. /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
  144. /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
  145. /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
  146. /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
  147. /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
  148. /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
  149. /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
  150. /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
  151. /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
  152. /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
  153. /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
  154. /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
  155. /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
  156. /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
  157. /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
  158. /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
  159. /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
  160. /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
  161. /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
  162. /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
  163. /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
  164. /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
  165. /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
  166. /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
  167. /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
  168. /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
  169. /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
  170. /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
  171. /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
  172. /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
  173. /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
  174. /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
  175. /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
  176. /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
  177. /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
  178. /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
  179. /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
  180. /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
  181. /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
  182. /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
  183. /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
  184. /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
  185. /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
  186. /package/docs/{account → v6/account}/dashboard.mdx +0 -0
  187. /package/docs/{account → v6/account}/enterprise.mdx +0 -0
  188. /package/docs/{account → v6/account}/pricing.mdx +0 -0
  189. /package/docs/{account → v6/account}/projects.mdx +0 -0
  190. /package/docs/{account → v6/account}/team.mdx +0 -0
  191. /package/docs/{action → v6/action}/ami.mdx +0 -0
  192. /package/docs/{action → v6/action}/performance.mdx +0 -0
  193. /package/docs/{action → v6/action}/secrets.mdx +0 -0
  194. /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
  195. /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
  196. /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
  197. /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
  198. /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
  199. /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
  200. /package/docs/{cli → v6/cli}/overview.mdx +0 -0
  201. /package/docs/{commands → v6/commands}/assert.mdx +0 -0
  202. /package/docs/{commands → v6/commands}/exec.mdx +0 -0
  203. /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
  204. /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
  205. /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
  206. /package/docs/{commands → v6/commands}/if.mdx +0 -0
  207. /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
  208. /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
  209. /package/docs/{commands → v6/commands}/remember.mdx +0 -0
  210. /package/docs/{commands → v6/commands}/run.mdx +0 -0
  211. /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
  212. /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
  213. /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
  214. /package/docs/{commands → v6/commands}/type.mdx +0 -0
  215. /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
  216. /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
  217. /package/docs/{commands → v6/commands}/wait.mdx +0 -0
  218. /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
  219. /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
  220. /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
  221. /package/docs/{features → v6/features}/generation.mdx +0 -0
  222. /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
  223. /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
  224. /package/docs/{features → v6/features}/selectorless.mdx +0 -0
  225. /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
  226. /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
  227. /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
  228. /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
  229. /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
  230. /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
  231. /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
  232. /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
  233. /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
  234. /package/docs/{guide → v6/guide}/code.mdx +0 -0
  235. /package/docs/{guide → v6/guide}/locating.mdx +0 -0
  236. /package/docs/{guide → v6/guide}/protips.mdx +0 -0
  237. /package/docs/{guide → v6/guide}/variables.mdx +0 -0
  238. /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
  239. /package/docs/{importing → v6/importing}/csv.mdx +0 -0
  240. /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
  241. /package/docs/{importing → v6/importing}/jira.mdx +0 -0
  242. /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
  243. /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
  244. /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
  245. /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
  246. /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
  247. /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
  248. /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
  249. /package/docs/{overview → v6/overview}/faq.mdx +0 -0
  250. /package/docs/{overview → v6/overview}/performance.mdx +0 -0
  251. /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
  252. /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
  253. /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
  254. /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
  255. /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
  256. /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
  257. /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
  258. /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
  259. /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
  260. /package/docs/{security → v6/security}/action.mdx +0 -0
  261. /package/docs/{security → v6/security}/agent.mdx +0 -0
  262. /package/docs/{security → v6/security}/platform.mdx +0 -0
  263. /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
  264. /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
@@ -1,10 +1,19 @@
1
1
  name: AWS
2
-
3
2
  on:
4
3
  workflow_dispatch:
5
4
  push:
5
+ branches:
6
+ - main
6
7
  paths-ignore:
7
8
  - "docs/**"
9
+ pull_request:
10
+ branches:
11
+ - main
12
+ types:
13
+ - ready_for_review
14
+ pull_request_review:
15
+ types:
16
+ - submitted
8
17
 
9
18
  jobs:
10
19
  gather:
@@ -54,6 +63,7 @@ jobs:
54
63
  - name: Setup AWS Instance
55
64
  id: aws-setup
56
65
  run: |
66
+ chmod +x ./setup/aws/spawn-runner.sh
57
67
  OUTPUT=$(./setup/aws/spawn-runner.sh | tee /dev/stderr) # Capture and display output
58
68
  echo "$OUTPUT"
59
69
  PUBLIC_IP=$(echo "$OUTPUT" | grep "PUBLIC_IP=" | cut -d'=' -f2)
@@ -68,9 +78,8 @@ jobs:
68
78
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
69
79
  AWS_REGION: us-east-2
70
80
  AWS_LAUNCH_TEMPLATE_ID: lt-00d02f31cfc602f27
71
- AMI_ID: ami-085f872ca0cd80fed
72
- RESOLUTION_WIDTH: 1920
73
- RESOLUTION_HEIGHT: 1080
81
+ AMI_ID: ami-055cd47506a2f39bb
82
+ RESOLUTION: 1920x1080
74
83
  - name: Run TestDriver
75
84
  run: node bin/testdriverai.js run testdriver/acceptance/${{ matrix.test }} --ip="${{ steps.aws-setup.outputs.public-ip }}" --junit=out.xml
76
85
  env:
@@ -168,8 +168,15 @@ Resources:
168
168
  IpProtocol: tcp,
169
169
  FromPort: 8765,
170
170
  ToPort: 8765,
171
- CidrIp: !Ref AllowedIngressCidr,
172
- Description: "pyautogui-cli WebSockets",
171
+ CidrIp: 35.171.123.200/32,
172
+ Description: "pyautogui-cli WebSockets - Static IP 1",
173
+ }
174
+ - {
175
+ IpProtocol: tcp,
176
+ FromPort: 8765,
177
+ ToPort: 8765,
178
+ CidrIp: 52.201.199.222/32,
179
+ Description: "pyautogui-cli WebSockets - Static IP 2",
173
180
  }
174
181
  - {
175
182
  IpProtocol: tcp,
@@ -0,0 +1,27 @@
1
+ name: MCP Example Test
2
+ description: Test created using TestDriver MCP to navigate example.com
3
+
4
+ steps:
5
+ # Open Chrome browser and navigate to example.com
6
+ - exec:
7
+ code: Start-Process chrome "https://example.com"
8
+ language: pwsh
9
+ timeout: 5000
10
+
11
+ # Wait for the page to load
12
+ - wait-for-text:
13
+ text: Example Domain
14
+ timeout: 10000
15
+
16
+ # Assert that the Example Domain heading is visible
17
+ - assert:
18
+ expect: The text "Example Domain" is visible on the page
19
+
20
+ # Click on the "Learn more" link
21
+ - hover-text:
22
+ text: Learn more
23
+ action: click
24
+
25
+ # Wait for navigation to complete
26
+ - wait:
27
+ timeout: 2000
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Quick test of the new find() API
5
+ * This is a simple smoke test to verify the Element class works
6
+ */
7
+
8
+ const TestDriver = require("../sdk");
9
+
10
+ async function testFindAPI() {
11
+ console.log("Testing new find() API...\n");
12
+
13
+ const client = new TestDriver("test-key", {
14
+ logging: false,
15
+ });
16
+
17
+ // Test 1: Create element without connecting
18
+ console.log("✓ Test 1: Creating Element instance");
19
+ const element = client.find("test element");
20
+ console.log(" Element description:", element.description);
21
+ console.log(" Element found():", element.found());
22
+ console.log(" Element coordinates:", element.getCoordinates());
23
+
24
+ // Test 2: Verify element methods exist
25
+ console.log("\n✓ Test 2: Verifying Element methods");
26
+ console.log(" Has find():", typeof element.find === "function");
27
+ console.log(" Has click():", typeof element.click === "function");
28
+ console.log(" Has hover():", typeof element.hover === "function");
29
+ console.log(
30
+ " Has doubleClick():",
31
+ typeof element.doubleClick === "function",
32
+ );
33
+ console.log(" Has rightClick():", typeof element.rightClick === "function");
34
+ console.log(" Has mouseDown():", typeof element.mouseDown === "function");
35
+ console.log(" Has mouseUp():", typeof element.mouseUp === "function");
36
+ console.log(" Has found():", typeof element.found === "function");
37
+ console.log(
38
+ " Has getCoordinates():",
39
+ typeof element.getCoordinates === "function",
40
+ );
41
+
42
+ // Test 3: Verify error handling for clicking unfound element
43
+ console.log("\n✓ Test 3: Error handling for unfound element");
44
+ try {
45
+ await element.click();
46
+ console.log(" ❌ Should have thrown error");
47
+ } catch (error) {
48
+ console.log(" ✓ Correctly throws error:", error.message);
49
+ }
50
+
51
+ // Test 4: Verify TypeScript types exist (if running from TypeScript)
52
+ console.log("\n✓ Test 4: SDK methods");
53
+ console.log(" Has find():", typeof client.find === "function");
54
+ console.log(
55
+ " Has deprecated hoverText():",
56
+ typeof client.hoverText === "undefined" ? "not yet connected" : "exists",
57
+ );
58
+ console.log(
59
+ " Has deprecated waitForText():",
60
+ typeof client.waitForText === "undefined" ? "not yet connected" : "exists",
61
+ );
62
+
63
+ console.log("\n✅ All basic tests passed!");
64
+ console.log(
65
+ "\nNote: Full integration tests require connection to TestDriver sandbox.",
66
+ );
67
+ console.log("See examples/sdk-find-example.js for complete usage examples.");
68
+ }
69
+
70
+ testFindAPI().catch((error) => {
71
+ console.error("Test failed:", error);
72
+ process.exit(1);
73
+ });
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test to verify prompt caching functionality
5
+ *
6
+ * This test demonstrates that:
7
+ * 1. First .prompt() call makes an API request and caches the YAML response
8
+ * 2. Second .prompt() call with the same prompt uses the cached YAML
9
+ * 3. Cache can be disabled with TD_NO_PROMPT_CACHE=true
10
+ */
11
+
12
+ const TestDriver = require("./sdk.js");
13
+ const promptCache = require("./agent/lib/cache.js");
14
+
15
+ async function testPromptCache() {
16
+ console.log("Testing prompt caching functionality...\n");
17
+
18
+ const client = new TestDriver(process.env.TD_API_KEY, {
19
+ os: "linux",
20
+ logging: true,
21
+ });
22
+
23
+ try {
24
+ // Connect to sandbox
25
+ console.log("Connecting to sandbox...");
26
+ await client.connect();
27
+ console.log("Connected!\n");
28
+
29
+ const testPrompt = "click the search button";
30
+
31
+ // Clear cache for this prompt to start fresh
32
+ const cachePath = promptCache.getCachePath(testPrompt);
33
+ console.log(`Cache path for "${testPrompt}": ${cachePath}\n`);
34
+
35
+ // Test 1: First call (should make API request and cache)
36
+ console.log("Test 1: First .ai() call (should cache the response)");
37
+ const stats1 = promptCache.getCacheStats();
38
+ console.log(`Cache before: ${stats1.count} files`);
39
+
40
+ await client.ai(testPrompt);
41
+
42
+ const stats2 = promptCache.getCacheStats();
43
+ console.log(`Cache after: ${stats2.count} files`);
44
+ console.log(
45
+ `Cache hit: ${promptCache.hasCache(testPrompt) ? "YES" : "NO"}\n`,
46
+ );
47
+
48
+ // Test 2: Second call (should use cache)
49
+ console.log(
50
+ "Test 2: Second .ai() call with same prompt (should use cache)",
51
+ );
52
+ console.log('Look for "(using cached response)" message above...\n');
53
+ await client.ai(testPrompt);
54
+
55
+ // Test 3: Third call with cache disabled (should make API call)
56
+ console.log(
57
+ "\nTest 3: Third .ai() call with cache=false (should bypass cache)",
58
+ );
59
+ await client.ai(testPrompt, false);
60
+
61
+ // Test 4: Show cache contents
62
+ console.log("\nTest 4: Cache contents");
63
+ const cachedYaml = promptCache.readCache(testPrompt);
64
+ if (cachedYaml) {
65
+ console.log("Cached YAML preview (first 500 chars):");
66
+ console.log(cachedYaml.substring(0, 500));
67
+ console.log("...\n");
68
+ }
69
+
70
+ // Test 5: Cache statistics
71
+ console.log("Test 5: Cache statistics");
72
+ const finalStats = promptCache.getCacheStats();
73
+ console.log(`Total cached prompts: ${finalStats.count}`);
74
+ console.log(`Cache files:`, finalStats.files.slice(0, 5));
75
+
76
+ console.log("\n✅ Prompt caching test completed!");
77
+ console.log("\nTo disable caching, pass false: client.ai(prompt, false)");
78
+ console.log("To clear cache, delete .testdriver/.cache/*.yaml files");
79
+ } catch (error) {
80
+ console.error("❌ Test failed:", error.message);
81
+ throw error;
82
+ } finally {
83
+ // Disconnect
84
+ await client.disconnect();
85
+ }
86
+ }
87
+
88
+ // Run the test
89
+ if (require.main === module) {
90
+ testPromptCache().catch((error) => {
91
+ console.error("Test error:", error);
92
+ process.exit(1);
93
+ });
94
+ }
95
+
96
+ module.exports = testPromptCache;
@@ -0,0 +1,28 @@
1
+ const TestDriver = require("./sdk.js");
2
+
3
+ async function test() {
4
+ console.log("Testing sandbox rendering...");
5
+
6
+ const client = new TestDriver(process.env.TD_API_KEY, {
7
+ os: process.env.TEST_PLATFORM || "linux",
8
+ headless: false, // Should open browser
9
+ logging: true,
10
+ });
11
+
12
+ try {
13
+ console.log("Connecting to sandbox...");
14
+ const instance = await client.connect();
15
+ console.log("Connected to instance:", instance);
16
+
17
+ // Wait a bit to see if browser opens
18
+ await new Promise((resolve) => setTimeout(resolve, 5000));
19
+
20
+ await client.disconnect();
21
+ console.log("Test completed successfully");
22
+ } catch (error) {
23
+ console.error("Test failed:", error);
24
+ process.exit(1);
25
+ }
26
+ }
27
+
28
+ test();
@@ -0,0 +1,15 @@
1
+ const SDK = require("./sdk.js");
2
+
3
+ const client = new SDK("test-key");
4
+
5
+ // Get all public methods (non-private, non-constructor)
6
+ const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(client))
7
+ .filter((m) => !m.startsWith("_") && m !== "constructor")
8
+ .sort();
9
+
10
+ console.log("Public SDK Methods:");
11
+ console.log(methods.join(", "));
12
+ console.log("\nTotal:", methods.length, "methods");
13
+
14
+ // Check if commands will be set up after connect
15
+ console.log("\nCommands before connect:", client.commands);
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Quick test to verify SDK refactoring works correctly
5
+ */
6
+
7
+ const TestDriver = require("./sdk.js");
8
+
9
+ async function test() {
10
+ console.log("Testing SDK refactor...\n");
11
+
12
+ // Test 1: SDK construction
13
+ console.log("✓ Test 1: Creating SDK instance");
14
+ const client = new TestDriver(process.env.TD_API_KEY || "test-key", {
15
+ logging: false,
16
+ });
17
+
18
+ console.log(" - agent exists:", !!client.agent);
19
+ console.log(" - emitter exists:", !!client.emitter);
20
+ console.log(" - config exists:", !!client.config);
21
+ console.log(" - session exists:", !!client.session);
22
+ console.log(" - apiClient exists:", !!client.apiClient);
23
+ console.log(" - analytics exists:", !!client.analytics);
24
+ console.log(" - sandbox exists:", !!client.sandbox);
25
+ console.log(" - system exists:", !!client.system);
26
+
27
+ // Test 2: Check agent methods are accessible
28
+ console.log("\n✓ Test 2: Checking agent methods");
29
+ console.log(
30
+ " - agent.exploratoryLoop exists:",
31
+ typeof client.agent.exploratoryLoop,
32
+ );
33
+ console.log(" - agent.buildEnv exists:", typeof client.agent.buildEnv);
34
+ console.log(
35
+ " - agent.getRecentSandboxId exists:",
36
+ typeof client.agent.getRecentSandboxId,
37
+ );
38
+
39
+ // Test 3: Check SDK methods
40
+ console.log("\n✓ Test 3: Checking SDK methods");
41
+ console.log(" - ai() exists:", typeof client.ai);
42
+ console.log(" - auth() exists:", typeof client.auth);
43
+ console.log(" - connect() exists:", typeof client.connect);
44
+ console.log(" - disconnect() exists:", typeof client.disconnect);
45
+
46
+ console.log("\n✅ All basic tests passed!");
47
+ }
48
+
49
+ test().catch((error) => {
50
+ console.error("\n❌ Test failed:", error.message);
51
+ console.error(error.stack);
52
+ process.exit(1);
53
+ });
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Quick test to verify stack trace filtering works
3
+ */
4
+
5
+ // Mock the MatchError similar to commands.js
6
+ class MatchError extends Error {
7
+ constructor(message, fatal = false) {
8
+ super(message);
9
+ this.fatal = fatal;
10
+ this.attachScreenshot = true;
11
+ }
12
+ }
13
+
14
+ // Simulate SDK wrapper with stack filtering (improved version)
15
+ class TestSDK {
16
+ constructor() {
17
+ const command = async (message) => {
18
+ // Simulate the command throwing an error
19
+ throw new MatchError(`AI Assertion failed: ${message}`, true);
20
+ };
21
+
22
+ // Wrap the method with proper stack trace handling
23
+ this.assert = async function (...args) {
24
+ // Capture the call site for better error reporting
25
+ const callSite = {};
26
+ Error.captureStackTrace(callSite, this.assert);
27
+
28
+ try {
29
+ return await command(...args);
30
+ } catch (error) {
31
+ // Replace the stack trace to point to the actual caller
32
+ if (Error.captureStackTrace && callSite.stack) {
33
+ const errorMessage = error.stack?.split("\n")[0];
34
+ const callerStack = callSite.stack?.split("\n").slice(1);
35
+ error.stack = errorMessage + "\n" + callerStack.join("\n");
36
+ }
37
+ throw error;
38
+ }
39
+ }.bind(this);
40
+ }
41
+ }
42
+
43
+ // Test it
44
+ async function runTest() {
45
+ const client = new TestSDK();
46
+
47
+ try {
48
+ console.log("Testing stack trace...\n");
49
+ await client.assert("home page appears"); // Line 42 - this should show in stack
50
+ } catch (error) {
51
+ console.log("Error caught!");
52
+ console.log("Stack trace:");
53
+ console.log(error.stack);
54
+ }
55
+ }
56
+
57
+ runTest();
@@ -0,0 +1,61 @@
1
+ # SDK Test Reporting - Quick Reference
2
+
3
+ ## 🚀 Commands
4
+
5
+ ```bash
6
+ # Run all tests
7
+ npm run test:sdk
8
+
9
+ # View terminal summary
10
+ npm run test:sdk:results
11
+
12
+ # Open HTML report
13
+ npm run test:sdk:report
14
+
15
+ # Watch mode (dev)
16
+ npm run test:sdk:watch
17
+
18
+ # Interactive UI
19
+ npm run test:sdk:ui
20
+ ```
21
+
22
+ ## 📊 What You Get
23
+
24
+ ### Locally
25
+
26
+ 1. **Console**: Verbose logs with full test output
27
+ 2. **Terminal Summary**: `npm run test:sdk:results` - Quick pass/fail counts
28
+ 3. **HTML Report**: `npm run test:sdk:report` - Interactive browser viewer
29
+
30
+ ### GitHub Actions
31
+
32
+ 1. **Step Summary**: Markdown tables in workflow summary page
33
+ 2. **Test Summary Action**: Badge counts and annotations
34
+ 3. **Artifacts**: Download junit.xml, results.json, and index.html
35
+
36
+ ## 📁 Output Files
37
+
38
+ ```
39
+ test-results/
40
+ ├── junit.xml # For CI/CD tools
41
+ ├── results.json # Machine-readable
42
+ └── index.html # Interactive report
43
+ ```
44
+
45
+ ## ⚡ Quick Tips
46
+
47
+ - **Debugging failures?** → `npm run test:sdk:report` (HTML has best error context)
48
+ - **Quick status check?** → `npm run test:sdk:results` (terminal summary)
49
+ - **PR review?** → Check GitHub Actions summary tab
50
+ - **Need history?** → Download artifacts from GitHub Actions runs
51
+
52
+ ## 🔍 GitHub Summary Preview
53
+
54
+ Every test run creates a summary with:
55
+
56
+ - ✅ Pass/fail counts table
57
+ - ❌ Failed test details with errors
58
+ - ✅ List of all passing tests
59
+ - ⏱️ Duration metrics
60
+
61
+ Find it: Actions → Your workflow run → Summary tab
@@ -0,0 +1,128 @@
1
+ # TestDriver SDK Acceptance Tests
2
+
3
+ This directory contains acceptance tests for the TestDriver SDK using Vitest.
4
+
5
+ ## Running Tests
6
+
7
+ ### Run All Tests (Cross-Platform)
8
+
9
+ ```bash
10
+ npm run test:sdk
11
+ ```
12
+
13
+ ### Run Platform-Specific Tests
14
+
15
+ Use the `TEST_PLATFORM` environment variable to run tests for a specific platform:
16
+
17
+ ```bash
18
+ # Run Windows-only tests
19
+ npm run test:sdk:windows
20
+
21
+ # Run macOS-only tests
22
+ npm run test:sdk:mac
23
+
24
+ # Run Linux-only tests
25
+ npm run test:sdk:linux
26
+ ```
27
+
28
+ Or set the environment variable directly:
29
+
30
+ ```bash
31
+ TEST_PLATFORM=windows npm run test:sdk
32
+ TEST_PLATFORM=mac npm run test:sdk
33
+ ```
34
+
35
+ ## Test Organization
36
+
37
+ ### Cross-Platform Tests
38
+
39
+ Tests without a platform suffix run on all platforms:
40
+
41
+ - `hover-text.test.mjs` - Runs everywhere
42
+ - `scroll.test.mjs` - Runs everywhere
43
+ - `screenshot.test.mjs` - Runs everywhere
44
+
45
+ ### Platform-Specific Tests
46
+
47
+ Platform-specific tests use naming conventions:
48
+
49
+ - `*.windows.test.mjs` - Windows-only tests (e.g., `exec-pwsh.windows.test.mjs`)
50
+ - `*.mac.test.mjs` - macOS-only tests
51
+ - `*.linux.test.mjs` - Linux-only tests
52
+
53
+ ### Conditional Test Skipping
54
+
55
+ Some tests use `skipIf` to conditionally skip based on the platform:
56
+
57
+ ```javascript
58
+ it.skipIf(() => testdriver.os === "linux")(
59
+ "should run on Windows/Mac",
60
+ async () => {
61
+ // This test will be skipped on Linux
62
+ },
63
+ );
64
+ ```
65
+
66
+ ## Environment Variables
67
+
68
+ - `TEST_PLATFORM` - Filter tests by platform (`windows`, `mac`, `linux`)
69
+ - `TD_OS` - Override the sandbox OS (defaults to `linux`)
70
+ - `TD_API_KEY` - Your TestDriver API key (required)
71
+ - `TD_API_ROOT` - API endpoint (optional)
72
+ - `DEBUG_ENV` - Show environment variable loading (optional)
73
+ - `DEBUG_EVENTS` - Enable detailed event logging (optional)
74
+
75
+ ## Examples
76
+
77
+ ```bash
78
+ # Run only Windows tests on a Windows sandbox
79
+ TEST_PLATFORM=windows npm run test:sdk
80
+
81
+ # Run all tests but use a Windows sandbox
82
+ TD_OS=windows npm run test:sdk
83
+
84
+ # Run with debugging enabled
85
+ DEBUG_ENV=true DEBUG_EVENTS=true npm run test:sdk
86
+
87
+ # Watch mode for development
88
+ npm run test:sdk:watch
89
+
90
+ # Generate coverage report
91
+ npm run test:sdk:coverage
92
+ ```
93
+
94
+ ## Test Structure
95
+
96
+ Each test follows this pattern:
97
+
98
+ ```javascript
99
+ import { afterEach, beforeEach, describe, it } from "vitest";
100
+ import {
101
+ createTestClient,
102
+ setupTest,
103
+ teardownTest,
104
+ } from "./setup/testHelpers.mjs";
105
+
106
+ describe("My Test", () => {
107
+ let testdriver;
108
+
109
+ beforeEach(async () => {
110
+ testdriver = createTestClient();
111
+ await setupTest(testdriver);
112
+ });
113
+
114
+ afterEach(async () => {
115
+ await teardownTest(testdriver);
116
+ });
117
+
118
+ it("should do something", async () => {
119
+ // Your test logic
120
+ });
121
+ });
122
+ ```
123
+
124
+ ## See Also
125
+
126
+ - [SDK README](../../SDK_README.md) - Full SDK documentation
127
+ - [Quick Reference](./QUICK_REFERENCE.md) - SDK method quick reference
128
+ - [Test Reporting](./TEST_REPORTING.md) - Test recording and reporting docs