testdriverai 6.2.2 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/.github/workflows/acceptance-linux.yml +75 -0
  2. package/.github/workflows/acceptance-sdk-tests.yml +133 -0
  3. package/.vscode/settings.json +5 -1
  4. package/AGENTS.md +550 -0
  5. package/CODEOWNERS +0 -1
  6. package/README.md +126 -0
  7. package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
  8. package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
  9. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  10. package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
  11. package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
  12. package/_testdriver/lifecycle/prerun.yaml +15 -0
  13. package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
  14. package/agent/index.js +300 -85
  15. package/agent/interface.js +15 -0
  16. package/agent/lib/cache.js +142 -0
  17. package/agent/lib/commander.js +1 -39
  18. package/agent/lib/commands.js +910 -296
  19. package/agent/lib/redraw.js +129 -41
  20. package/agent/lib/sandbox.js +29 -6
  21. package/agent/lib/sdk.js +22 -0
  22. package/agent/lib/system.js +0 -3
  23. package/agent/lib/validation.js +1 -7
  24. package/debug-locate-response.js +82 -0
  25. package/debugger/index.html +15 -4
  26. package/docs/ARCHITECTURE.md +424 -0
  27. package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
  28. package/docs/MIGRATION.md +425 -0
  29. package/docs/PRESETS.md +210 -0
  30. package/docs/QUICK_START_TEST_RECORDING.md +215 -0
  31. package/docs/SDK_AWESOME_LOGS.md +468 -0
  32. package/docs/TEST_RECORDING.md +388 -0
  33. package/docs/docs.json +286 -152
  34. package/docs/guide/best-practices-polling.mdx +154 -0
  35. package/docs/sdk-browser-rendering.md +167 -0
  36. package/docs/v6/getting-started/self-hosting.mdx +407 -0
  37. package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
  38. package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
  39. package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
  40. package/docs/v6/overview/comparison.mdx +101 -0
  41. package/docs/v7/README.md +135 -0
  42. package/docs/v7/api/ai.mdx +205 -0
  43. package/docs/v7/api/assert.mdx +285 -0
  44. package/docs/v7/api/assertions.mdx +403 -0
  45. package/docs/v7/api/click.mdx +287 -0
  46. package/docs/v7/api/client.mdx +322 -0
  47. package/docs/v7/api/dashcam.mdx +497 -0
  48. package/docs/v7/api/doubleClick.mdx +102 -0
  49. package/docs/v7/api/elements.mdx +479 -0
  50. package/docs/v7/api/exec.mdx +346 -0
  51. package/docs/v7/api/find.mdx +316 -0
  52. package/docs/v7/api/focusApplication.mdx +294 -0
  53. package/docs/v7/api/hover.mdx +279 -0
  54. package/docs/v7/api/mouseDown.mdx +161 -0
  55. package/docs/v7/api/mouseUp.mdx +164 -0
  56. package/docs/v7/api/pressKeys.mdx +349 -0
  57. package/docs/v7/api/rightClick.mdx +123 -0
  58. package/docs/v7/api/sandbox.mdx +404 -0
  59. package/docs/v7/api/scroll.mdx +300 -0
  60. package/docs/v7/api/type.mdx +314 -0
  61. package/docs/v7/commands/assert.mdx +45 -0
  62. package/docs/v7/commands/exec.mdx +282 -0
  63. package/docs/v7/commands/focus-application.mdx +44 -0
  64. package/docs/v7/commands/hover-image.mdx +69 -0
  65. package/docs/v7/commands/hover-text.mdx +47 -0
  66. package/docs/v7/commands/if.mdx +53 -0
  67. package/docs/v7/commands/match-image.mdx +67 -0
  68. package/docs/v7/commands/press-keys.mdx +87 -0
  69. package/docs/v7/commands/remember.mdx +49 -0
  70. package/docs/v7/commands/run.mdx +44 -0
  71. package/docs/v7/commands/scroll-until-image.mdx +66 -0
  72. package/docs/v7/commands/scroll-until-text.mdx +60 -0
  73. package/docs/v7/commands/scroll.mdx +69 -0
  74. package/docs/v7/commands/type.mdx +45 -0
  75. package/docs/v7/commands/wait-for-image.mdx +54 -0
  76. package/docs/v7/commands/wait-for-text.mdx +48 -0
  77. package/docs/v7/commands/wait.mdx +45 -0
  78. package/docs/v7/getting-started/configuration.mdx +380 -0
  79. package/docs/v7/getting-started/quickstart.mdx +332 -0
  80. package/docs/v7/guides/best-practices.mdx +486 -0
  81. package/docs/v7/guides/caching-ai.mdx +215 -0
  82. package/docs/v7/guides/caching-selectors.mdx +292 -0
  83. package/docs/v7/guides/caching.mdx +366 -0
  84. package/docs/v7/guides/ci-cd/azure.mdx +587 -0
  85. package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
  86. package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
  87. package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
  88. package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
  89. package/docs/v7/guides/ci-cd/travis.mdx +438 -0
  90. package/docs/v7/guides/debugging.mdx +349 -0
  91. package/docs/v7/guides/faq.mdx +393 -0
  92. package/docs/v7/guides/migration.mdx +562 -0
  93. package/docs/v7/guides/performance.mdx +517 -0
  94. package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
  95. package/docs/v7/guides/troubleshooting.mdx +526 -0
  96. package/docs/v7/guides/vitest-plugin.mdx +477 -0
  97. package/docs/v7/guides/vitest.mdx +535 -0
  98. package/docs/v7/platforms/linux.mdx +308 -0
  99. package/docs/v7/platforms/macos.mdx +433 -0
  100. package/docs/v7/platforms/windows.mdx +430 -0
  101. package/docs/v7/playwright.mdx +342 -0
  102. package/docs/v7/presets/chrome-extension.mdx +223 -0
  103. package/docs/v7/presets/chrome.mdx +287 -0
  104. package/docs/v7/presets/electron.mdx +435 -0
  105. package/docs/v7/presets/vscode.mdx +398 -0
  106. package/docs/v7/presets/webapp.mdx +396 -0
  107. package/docs/v7/progressive-apis/CORE.md +459 -0
  108. package/docs/v7/progressive-apis/HOOKS.md +360 -0
  109. package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
  110. package/docs/v7/progressive-apis/PROVISION.md +266 -0
  111. package/eslint.config.js +19 -1
  112. package/interfaces/cli/lib/base.js +10 -4
  113. package/interfaces/logger.js +2 -1
  114. package/interfaces/shared-test-state.mjs +69 -0
  115. package/interfaces/vitest-plugin.mjs +830 -0
  116. package/package.json +29 -5
  117. package/schema.json +8 -29
  118. package/scripts/view-test-results.mjs +96 -0
  119. package/sdk-log-formatter.js +714 -0
  120. package/sdk.d.ts +1028 -0
  121. package/sdk.js +2567 -0
  122. package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
  123. package/setup/aws/cloudformation.yaml +9 -2
  124. package/src/core/Dashcam.js +469 -0
  125. package/src/core/index.d.ts +150 -0
  126. package/src/core/index.js +12 -0
  127. package/src/presets/index.mjs +331 -0
  128. package/src/vitest/extended.mjs +108 -0
  129. package/src/vitest/hooks.d.ts +119 -0
  130. package/src/vitest/hooks.mjs +298 -0
  131. package/src/vitest/index.mjs +64 -0
  132. package/src/vitest/lifecycle.mjs +277 -0
  133. package/src/vitest/utils.mjs +150 -0
  134. package/test/dashcam.test.js +137 -0
  135. package/test/mcp-example-test.yaml +27 -0
  136. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
  137. package/testdriver/acceptance-sdk/README.md +128 -0
  138. package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
  139. package/testdriver/acceptance-sdk/assert.test.mjs +26 -0
  140. package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
  141. package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
  142. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +58 -0
  143. package/testdriver/acceptance-sdk/element-not-found.test.mjs +25 -0
  144. package/testdriver/acceptance-sdk/exec-js.test.mjs +43 -0
  145. package/testdriver/acceptance-sdk/exec-output.test.mjs +59 -0
  146. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +57 -0
  147. package/testdriver/acceptance-sdk/focus-window.test.mjs +36 -0
  148. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +26 -0
  149. package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
  150. package/testdriver/acceptance-sdk/hover-image.test.mjs +34 -0
  151. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +38 -0
  152. package/testdriver/acceptance-sdk/hover-text.test.mjs +27 -0
  153. package/testdriver/acceptance-sdk/match-image.test.mjs +36 -0
  154. package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
  155. package/testdriver/acceptance-sdk/press-keys.test.mjs +50 -0
  156. package/testdriver/acceptance-sdk/prompt.test.mjs +33 -0
  157. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +38 -0
  158. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +39 -0
  159. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +28 -0
  160. package/testdriver/acceptance-sdk/scroll.test.mjs +41 -0
  161. package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
  162. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +420 -0
  163. package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
  164. package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
  165. package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
  166. package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
  167. package/testdriver/acceptance-sdk/type.test.mjs +45 -0
  168. package/verify-element-api.js +89 -0
  169. package/verify-types.js +0 -0
  170. package/vitest.config.example.js +19 -0
  171. package/vitest.config.mjs +66 -0
  172. package/vitest.config.mjs.bak +44 -0
  173. package/.github/workflows/acceptance-v6.yml +0 -169
  174. package/.vscode/mcp.json +0 -9
  175. package/docs/overview/comparison.mdx +0 -82
  176. package/testdriver/lifecycle/prerun.yaml +0 -17
  177. /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
  178. /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
  179. /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
  180. /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
  181. /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
  182. /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
  183. /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
  184. /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
  185. /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
  186. /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
  187. /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
  188. /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
  189. /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
  190. /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
  191. /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
  192. /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
  193. /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
  194. /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
  195. /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
  196. /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
  197. /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
  198. /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
  199. /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
  200. /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
  201. /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
  202. /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
  203. /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
  204. /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
  205. /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
  206. /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
  207. /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
  208. /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
  209. /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
  210. /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
  211. /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
  212. /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
  213. /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
  214. /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
  215. /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
  216. /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
  217. /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
  218. /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
  219. /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
  220. /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
  221. /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
  222. /package/docs/{account → v6/account}/dashboard.mdx +0 -0
  223. /package/docs/{account → v6/account}/enterprise.mdx +0 -0
  224. /package/docs/{account → v6/account}/pricing.mdx +0 -0
  225. /package/docs/{account → v6/account}/projects.mdx +0 -0
  226. /package/docs/{account → v6/account}/team.mdx +0 -0
  227. /package/docs/{action → v6/action}/ami.mdx +0 -0
  228. /package/docs/{action → v6/action}/performance.mdx +0 -0
  229. /package/docs/{action → v6/action}/secrets.mdx +0 -0
  230. /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
  231. /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
  232. /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
  233. /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
  234. /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
  235. /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
  236. /package/docs/{cli → v6/cli}/overview.mdx +0 -0
  237. /package/docs/{commands → v6/commands}/assert.mdx +0 -0
  238. /package/docs/{commands → v6/commands}/exec.mdx +0 -0
  239. /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
  240. /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
  241. /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
  242. /package/docs/{commands → v6/commands}/if.mdx +0 -0
  243. /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
  244. /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
  245. /package/docs/{commands → v6/commands}/remember.mdx +0 -0
  246. /package/docs/{commands → v6/commands}/run.mdx +0 -0
  247. /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
  248. /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
  249. /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
  250. /package/docs/{commands → v6/commands}/type.mdx +0 -0
  251. /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
  252. /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
  253. /package/docs/{commands → v6/commands}/wait.mdx +0 -0
  254. /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
  255. /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
  256. /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
  257. /package/docs/{features → v6/features}/generation.mdx +0 -0
  258. /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
  259. /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
  260. /package/docs/{features → v6/features}/selectorless.mdx +0 -0
  261. /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
  262. /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
  263. /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
  264. /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
  265. /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
  266. /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
  267. /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
  268. /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
  269. /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
  270. /package/docs/{guide → v6/guide}/code.mdx +0 -0
  271. /package/docs/{guide → v6/guide}/locating.mdx +0 -0
  272. /package/docs/{guide → v6/guide}/protips.mdx +0 -0
  273. /package/docs/{guide → v6/guide}/variables.mdx +0 -0
  274. /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
  275. /package/docs/{importing → v6/importing}/csv.mdx +0 -0
  276. /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
  277. /package/docs/{importing → v6/importing}/jira.mdx +0 -0
  278. /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
  279. /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
  280. /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
  281. /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
  282. /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
  283. /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
  284. /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
  285. /package/docs/{overview → v6/overview}/faq.mdx +0 -0
  286. /package/docs/{overview → v6/overview}/performance.mdx +0 -0
  287. /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
  288. /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
  289. /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
  290. /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
  291. /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
  292. /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
  293. /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
  294. /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
  295. /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
  296. /package/docs/{security → v6/security}/action.mdx +0 -0
  297. /package/docs/{security → v6/security}/agent.mdx +0 -0
  298. /package/docs/{security → v6/security}/platform.mdx +0 -0
  299. /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
  300. /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
@@ -0,0 +1,457 @@
1
+ ---
2
+ title: "GitHub Actions"
3
+ description: "Run TestDriver tests in GitHub Actions"
4
+ icon: "github"
5
+ ---
6
+
7
+ ## Basic Setup
8
+
9
+ Create `.github/workflows/test.yml`:
10
+
11
+ ```yaml
12
+ name: TestDriver Tests
13
+
14
+ on:
15
+ push:
16
+ branches: [main, develop]
17
+ pull_request:
18
+ branches: [main, develop]
19
+
20
+ jobs:
21
+ test:
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - uses: actions/checkout@v3
26
+
27
+ - name: Setup Node.js
28
+ uses: actions/setup-node@v3
29
+ with:
30
+ node-version: '18'
31
+ cache: 'npm'
32
+
33
+ - name: Install dependencies
34
+ run: npm ci
35
+
36
+ - name: Run TestDriver tests
37
+ env:
38
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
39
+ run: npx vitest
40
+
41
+ - name: Upload test results
42
+ if: always()
43
+ uses: actions/upload-artifact@v3
44
+ with:
45
+ name: test-results
46
+ path: test-results/
47
+ ```
48
+
49
+ ## Add API Key
50
+
51
+ 1. Go to repository **Settings** → **Secrets and variables** → **Actions**
52
+ 2. Click **New repository secret**
53
+ 3. Name: `TD_API_KEY`
54
+ 4. Value: Your API key from [dashboard.testdriver.ai](https://dashboard.testdriver.ai)
55
+ 5. Click **Add secret**
56
+
57
+ ## Parallel Tests
58
+
59
+ Run tests in parallel using matrix strategy:
60
+
61
+ ```yaml
62
+ jobs:
63
+ test:
64
+ runs-on: ubuntu-latest
65
+ strategy:
66
+ matrix:
67
+ shard: [1, 2, 3, 4]
68
+
69
+ steps:
70
+ - uses: actions/checkout@v3
71
+
72
+ - name: Setup Node.js
73
+ uses: actions/setup-node@v3
74
+ with:
75
+ node-version: '18'
76
+ cache: 'npm'
77
+
78
+ - name: Install dependencies
79
+ run: npm ci
80
+
81
+ - name: Run shard ${{ matrix.shard }}
82
+ env:
83
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
84
+ run: npx vitest --shard=${{ matrix.shard }}/4
85
+ ```
86
+
87
+ This runs 4 test shards in parallel, completing in ~25% of the time.
88
+
89
+ ## Save Dashcam URLs
90
+
91
+ Capture replay URLs for debugging failures:
92
+
93
+ ```yaml
94
+ - name: Run tests
95
+ env:
96
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
97
+ run: npx vitest 2>&1 | tee test-output.log
98
+
99
+ - name: Extract Dashcam URLs
100
+ if: always()
101
+ run: |
102
+ grep -o 'https://dashcam.testdriver.ai/[a-zA-Z0-9-]*' test-output.log > dashcam-urls.txt || true
103
+
104
+ - name: Upload Dashcam URLs
105
+ if: always()
106
+ uses: actions/upload-artifact@v3
107
+ with:
108
+ name: dashcam-urls
109
+ path: dashcam-urls.txt
110
+
111
+ - name: Comment on PR
112
+ if: failure() && github.event_name == 'pull_request'
113
+ uses: actions/github-script@v6
114
+ with:
115
+ script: |
116
+ const fs = require('fs');
117
+ const urls = fs.readFileSync('dashcam-urls.txt', 'utf8').trim().split('\n');
118
+ const body = '## ❌ Tests Failed\n\n**Dashcam Replays:**\n' +
119
+ urls.map(url => `- ${url}`).join('\n');
120
+
121
+ github.rest.issues.createComment({
122
+ issue_number: context.issue.number,
123
+ owner: context.repo.owner,
124
+ repo: context.repo.repo,
125
+ body: body
126
+ });
127
+ ```
128
+
129
+ ## Scheduled Tests
130
+
131
+ Run tests on schedule:
132
+
133
+ ```yaml
134
+ on:
135
+ schedule:
136
+ - cron: '0 */6 * * *' # Every 6 hours
137
+ workflow_dispatch: # Manual trigger button
138
+ push:
139
+ branches: [main]
140
+ pull_request:
141
+ ```
142
+
143
+ ## Cache Dependencies
144
+
145
+ Speed up workflow with dependency caching:
146
+
147
+ ```yaml
148
+ - name: Setup Node.js
149
+ uses: actions/setup-node@v3
150
+ with:
151
+ node-version: '18'
152
+ cache: 'npm' # Built-in npm cache
153
+
154
+ # Or manually cache
155
+ - name: Cache node modules
156
+ uses: actions/cache@v3
157
+ with:
158
+ path: ~/.npm
159
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
160
+ restore-keys: |
161
+ ${{ runner.os }}-node-
162
+ ```
163
+
164
+ ## Conditional Execution
165
+
166
+ Skip tests on documentation changes:
167
+
168
+ ```yaml
169
+ on:
170
+ pull_request:
171
+ paths-ignore:
172
+ - '**.md'
173
+ - 'docs/**'
174
+ - 'README.md'
175
+ ```
176
+
177
+ Or run only on specific file changes:
178
+
179
+ ```yaml
180
+ on:
181
+ pull_request:
182
+ paths:
183
+ - 'src/**'
184
+ - 'test/**'
185
+ - 'package.json'
186
+ ```
187
+
188
+ ## Test Results
189
+
190
+ Publish test results to GitHub UI:
191
+
192
+ ```yaml
193
+ - name: Run tests
194
+ env:
195
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
196
+ run: npx vitest
197
+
198
+ - name: Publish test results
199
+ if: always()
200
+ uses: dorny/test-reporter@v1
201
+ with:
202
+ name: TestDriver Tests
203
+ path: test-results/junit.xml
204
+ reporter: java-junit
205
+ ```
206
+
207
+ Requires JUnit reporter in `vitest.config.mjs`:
208
+
209
+ ```javascript
210
+ export default defineConfig({
211
+ test: {
212
+ reporters: ['default', 'junit'],
213
+ outputFile: {
214
+ junit: './test-results/junit.xml'
215
+ }
216
+ }
217
+ });
218
+ ```
219
+
220
+ ## Multiple Node Versions
221
+
222
+ Test across Node.js versions:
223
+
224
+ ```yaml
225
+ jobs:
226
+ test:
227
+ runs-on: ubuntu-latest
228
+ strategy:
229
+ matrix:
230
+ node-version: [16, 18, 20]
231
+
232
+ steps:
233
+ - uses: actions/checkout@v3
234
+
235
+ - name: Use Node.js ${{ matrix.node-version }}
236
+ uses: actions/setup-node@v3
237
+ with:
238
+ node-version: ${{ matrix.node-version }}
239
+
240
+ - run: npm ci
241
+ - run: npx vitest
242
+ env:
243
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
244
+ ```
245
+
246
+ ## Fail Fast
247
+
248
+ Stop on first failure to save minutes:
249
+
250
+ ```yaml
251
+ - name: Run tests
252
+ env:
253
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
254
+ run: npx vitest --bail
255
+ ```
256
+
257
+ Or stop other jobs when one fails:
258
+
259
+ ```yaml
260
+ jobs:
261
+ test:
262
+ strategy:
263
+ fail-fast: true # Stop all jobs on first failure
264
+ matrix:
265
+ shard: [1, 2, 3, 4]
266
+ ```
267
+
268
+ ## Reusable Workflow
269
+
270
+ Create reusable workflow for multiple repos:
271
+
272
+ ```yaml
273
+ # .github/workflows/testdriver-reusable.yml
274
+ name: TestDriver (Reusable)
275
+
276
+ on:
277
+ workflow_call:
278
+ secrets:
279
+ TD_API_KEY:
280
+ required: true
281
+
282
+ jobs:
283
+ test:
284
+ runs-on: ubuntu-latest
285
+ steps:
286
+ - uses: actions/checkout@v3
287
+ - uses: actions/setup-node@v3
288
+ with:
289
+ node-version: '18'
290
+ - run: npm ci
291
+ - run: npx vitest
292
+ env:
293
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
294
+ ```
295
+
296
+ Use in other workflows:
297
+
298
+ ```yaml
299
+ # .github/workflows/test.yml
300
+ name: Tests
301
+
302
+ on: [push, pull_request]
303
+
304
+ jobs:
305
+ test:
306
+ uses: ./.github/workflows/testdriver-reusable.yml
307
+ secrets:
308
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
309
+ ```
310
+
311
+ ## Environment-Specific Tests
312
+
313
+ Test against different environments:
314
+
315
+ ```yaml
316
+ jobs:
317
+ test:
318
+ runs-on: ubuntu-latest
319
+ strategy:
320
+ matrix:
321
+ environment: [staging, production]
322
+
323
+ steps:
324
+ - uses: actions/checkout@v3
325
+ - uses: actions/setup-node@v3
326
+ with:
327
+ node-version: '18'
328
+ - run: npm ci
329
+ - run: npx vitest
330
+ env:
331
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
332
+ TEST_URL: ${{ matrix.environment == 'staging' && 'https://staging.example.com' || 'https://example.com' }}
333
+ ```
334
+
335
+ ## Troubleshooting
336
+
337
+ ### Tests timeout
338
+
339
+ Increase timeout:
340
+
341
+ ```yaml
342
+ - name: Run tests
343
+ timeout-minutes: 30 # Default is 360
344
+ env:
345
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
346
+ run: npx vitest
347
+ ```
348
+
349
+ ### API key not found
350
+
351
+ Debug environment variables:
352
+
353
+ ```yaml
354
+ - name: Debug
355
+ run: |
356
+ echo "Has TD_API_KEY: ${{ secrets.TD_API_KEY != '' }}"
357
+ echo "Node version: $(node --version)"
358
+ ```
359
+
360
+ ### Out of disk space
361
+
362
+ Clean up before running:
363
+
364
+ ```yaml
365
+ - name: Free disk space
366
+ run: |
367
+ sudo rm -rf /usr/share/dotnet
368
+ sudo rm -rf /opt/ghc
369
+ sudo rm -rf /usr/local/share/boost
370
+ ```
371
+
372
+ ## Complete Example
373
+
374
+ Full-featured workflow:
375
+
376
+ ```yaml
377
+ name: TestDriver Tests
378
+
379
+ on:
380
+ push:
381
+ branches: [main, develop]
382
+ pull_request:
383
+ branches: [main, develop]
384
+ schedule:
385
+ - cron: '0 2 * * *' # 2 AM daily
386
+ workflow_dispatch:
387
+
388
+ jobs:
389
+ test:
390
+ runs-on: ubuntu-latest
391
+ timeout-minutes: 30
392
+ strategy:
393
+ fail-fast: false
394
+ matrix:
395
+ shard: [1, 2, 3, 4]
396
+
397
+ steps:
398
+ - name: Checkout
399
+ uses: actions/checkout@v3
400
+
401
+ - name: Setup Node.js
402
+ uses: actions/setup-node@v3
403
+ with:
404
+ node-version: '18'
405
+ cache: 'npm'
406
+
407
+ - name: Install dependencies
408
+ run: npm ci
409
+
410
+ - name: Run tests (shard ${{ matrix.shard }}/4)
411
+ env:
412
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
413
+ run: npx vitest --shard=${{ matrix.shard }}/4 2>&1 | tee test-output.log
414
+
415
+ - name: Extract Dashcam URLs
416
+ if: always()
417
+ run: |
418
+ grep -o 'https://dashcam.testdriver.ai/[a-zA-Z0-9-]*' test-output.log > dashcam-urls.txt || true
419
+
420
+ - name: Upload test results
421
+ if: always()
422
+ uses: actions/upload-artifact@v3
423
+ with:
424
+ name: test-results-${{ matrix.shard }}
425
+ path: |
426
+ test-results/
427
+ test-output.log
428
+ dashcam-urls.txt
429
+
430
+ - name: Publish test results
431
+ if: always()
432
+ uses: dorny/test-reporter@v1
433
+ with:
434
+ name: Tests (Shard ${{ matrix.shard }})
435
+ path: test-results/junit.xml
436
+ reporter: java-junit
437
+ ```
438
+
439
+ ## See Also
440
+
441
+ <CardGroup cols={2}>
442
+ <Card title="CI/CD Overview" icon="arrows-spin" href="/v7/guides/ci-cd/overview">
443
+ CI/CD concepts
444
+ </Card>
445
+
446
+ <Card title="Performance" icon="gauge" href="/v7/guides/performance">
447
+ Optimize tests
448
+ </Card>
449
+
450
+ <Card title="Troubleshooting" icon="circle-question" href="/v7/guides/troubleshooting">
451
+ Common issues
452
+ </Card>
453
+
454
+ <Card title="GitHub Actions Docs" icon="book" href="https://docs.github.com/en/actions">
455
+ Official docs
456
+ </Card>
457
+ </CardGroup>