testdriverai 7.1.0 → 7.1.2

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 (325) hide show
  1. package/.env.example +2 -0
  2. package/.github/workflows/linux-tests.yml +28 -0
  3. package/agent/index.js +18 -45
  4. package/agent/interface.js +13 -2
  5. package/agent/lib/commands.js +1 -1
  6. package/agent/lib/redraw.js +1 -1
  7. package/agent/lib/sandbox.js +30 -2
  8. package/agent/lib/valid-version.js +2 -2
  9. package/debugger/index.html +1 -1
  10. package/docs/docs.json +140 -131
  11. package/docs/v6/getting-started/self-hosting.mdx +3 -2
  12. package/docs/v7/_drafts/agents.mdx +852 -0
  13. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  14. package/docs/v7/{guides → _drafts}/caching-selectors.mdx +125 -17
  15. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  16. package/docs/v7/_drafts/error-handling.mdx +501 -0
  17. package/docs/v7/_drafts/implementation-plan.mdx +994 -0
  18. package/docs/v7/_drafts/init-command.mdx +95 -0
  19. package/docs/v7/_drafts/optimal-sdk-design.mdx +1348 -0
  20. package/docs/v7/_drafts/plugin-migration.mdx +222 -0
  21. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  22. package/docs/{QUICK_START_TEST_RECORDING.md → v7/_drafts/quick-start-test-recording.mdx} +3 -3
  23. package/docs/v7/_drafts/sdk-logging.mdx +222 -0
  24. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  25. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  26. package/docs/v7/{guides → _drafts}/self-hosting.mdx +1 -1
  27. package/docs/v7/{guides → _drafts}/troubleshooting.mdx +2 -2
  28. package/docs/v7/{guides → _drafts}/vitest-plugin.mdx +4 -4
  29. package/docs/v7/api/{ai.mdx → act.mdx} +24 -24
  30. package/docs/v7/api/client.mdx +1 -1
  31. package/docs/v7/api/dashcam.mdx +2 -2
  32. package/docs/v7/api/elements.mdx +143 -41
  33. package/docs/v7/api/find.mdx +258 -0
  34. package/docs/v7/api/type.mdx +51 -7
  35. package/docs/v7/features/ai-native.mdx +427 -0
  36. package/docs/v7/features/easy-to-write.mdx +351 -0
  37. package/docs/v7/features/enterprise.mdx +540 -0
  38. package/docs/v7/features/fast.mdx +424 -0
  39. package/docs/v7/features/observable.mdx +623 -0
  40. package/docs/v7/features/powerful.mdx +531 -0
  41. package/docs/v7/features/scalable.mdx +417 -0
  42. package/docs/v7/features/stable.mdx +514 -0
  43. package/docs/v7/getting-started/configuration.mdx +1 -1
  44. package/docs/v7/getting-started/generating-tests.mdx +525 -0
  45. package/docs/v7/getting-started/installation.mdx +486 -0
  46. package/docs/v7/getting-started/quickstart.mdx +51 -5
  47. package/docs/v7/getting-started/running-and-debugging.mdx +511 -0
  48. package/docs/v7/getting-started/setting-up-in-ci.mdx +612 -0
  49. package/docs/v7/getting-started/writing-tests.mdx +535 -0
  50. package/docs/v7/overview/what-is-testdriver.mdx +398 -0
  51. package/docs/v7/playwright.mdx +3 -3
  52. package/docs/v7/presets/chrome.mdx +16 -0
  53. package/docs/v7/presets/electron.mdx +18 -0
  54. package/docs/v7/presets/vscode.mdx +19 -0
  55. package/examples/run-tests-with-recording.sh +70 -0
  56. package/examples/screenshot-example.js +63 -0
  57. package/examples/sdk-awesome-logs-demo.js +177 -0
  58. package/examples/sdk-cache-thresholds.js +96 -0
  59. package/examples/sdk-element-properties.js +155 -0
  60. package/examples/sdk-simple-example.js +65 -0
  61. package/examples/test-recording-example.test.js +166 -0
  62. package/interfaces/cli/commands/init.js +358 -0
  63. package/interfaces/vitest-plugin.mjs +214 -10
  64. package/{src → lib}/core/Dashcam.js +41 -4
  65. package/{src → lib}/vitest/hooks.mjs +118 -100
  66. package/lib/vitest/setup.mjs +44 -0
  67. package/package.json +9 -10
  68. package/sdk.d.ts +15 -2
  69. package/sdk.js +72 -17
  70. package/{self-hosted.yml → setup/aws/self-hosted.yml} +1 -1
  71. package/{testdriver/acceptance-sdk → test/manual}/test-console-logs.test.mjs +1 -1
  72. package/test/manual/test-find-api.js +73 -0
  73. package/test/manual/test-init.sh +54 -0
  74. package/test/manual/test-prompt-cache.js +96 -0
  75. package/test/manual/test-provision-auth.mjs +22 -0
  76. package/test/manual/test-sandbox-render.js +28 -0
  77. package/test/manual/test-sdk-methods.js +15 -0
  78. package/test/manual/test-sdk-refactor.js +53 -0
  79. package/test/manual/test-stack-trace.mjs +57 -0
  80. package/test/testdriver/assert.test.mjs +41 -0
  81. package/{testdriver/acceptance-sdk → test/testdriver}/auto-cache-key-demo.test.mjs +1 -1
  82. package/{testdriver/acceptance-sdk → test/testdriver}/drag-and-drop.test.mjs +1 -1
  83. package/{testdriver/acceptance-sdk → test/testdriver}/element-not-found.test.mjs +1 -1
  84. package/{testdriver/acceptance-sdk → test/testdriver}/exec-js.test.mjs +1 -1
  85. package/{testdriver/acceptance-sdk → test/testdriver}/exec-output.test.mjs +3 -3
  86. package/{testdriver/acceptance-sdk → test/testdriver}/exec-pwsh.test.mjs +3 -3
  87. package/{testdriver/acceptance-sdk → test/testdriver}/focus-window.test.mjs +1 -1
  88. package/{testdriver/acceptance-sdk → test/testdriver}/formatted-logging.test.mjs +1 -1
  89. package/{testdriver/acceptance-sdk → test/testdriver}/hover-image.test.mjs +1 -1
  90. package/{testdriver/acceptance-sdk → test/testdriver}/hover-text-with-description.test.mjs +1 -1
  91. package/{testdriver/acceptance-sdk → test/testdriver}/hover-text.test.mjs +1 -1
  92. package/{testdriver/acceptance-sdk → test/testdriver}/match-image.test.mjs +1 -1
  93. package/{testdriver/acceptance-sdk → test/testdriver}/press-keys.test.mjs +1 -1
  94. package/{testdriver/acceptance-sdk → test/testdriver}/prompt.test.mjs +2 -2
  95. package/{testdriver/acceptance-sdk → test/testdriver}/scroll-keyboard.test.mjs +1 -1
  96. package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-image.test.mjs +1 -1
  97. package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-text.test.mjs +1 -1
  98. package/{testdriver/acceptance-sdk → test/testdriver}/scroll.test.mjs +1 -1
  99. package/{src/vitest/lifecycle.mjs → test/testdriver/setup/lifecycleHelpers.mjs} +84 -99
  100. package/test/testdriver/setup/testHelpers.mjs +653 -0
  101. package/{testdriver/acceptance-sdk → test/testdriver}/type.test.mjs +1 -1
  102. package/vitest.config.mjs +8 -59
  103. package/.github/dependabot.yml +0 -11
  104. package/.github/workflows/acceptance-linux.yml +0 -75
  105. package/.github/workflows/acceptance-sdk-tests.yml +0 -133
  106. package/.github/workflows/acceptance-tests.yml +0 -130
  107. package/.github/workflows/lint.yml +0 -27
  108. package/.github/workflows/publish-canary.yml +0 -40
  109. package/.github/workflows/publish-latest.yml +0 -61
  110. package/.github/workflows/test-install.yml +0 -29
  111. package/.vscode/extensions.json +0 -3
  112. package/.vscode/launch.json +0 -22
  113. package/.vscode/settings.json +0 -14
  114. package/AGENTS.md +0 -550
  115. package/CODEOWNERS +0 -2
  116. package/_testdriver/acceptance/assert.yaml +0 -7
  117. package/_testdriver/acceptance/dashcam.yaml +0 -9
  118. package/_testdriver/acceptance/drag-and-drop.yaml +0 -49
  119. package/_testdriver/acceptance/embed.yaml +0 -9
  120. package/_testdriver/acceptance/exec-js.yaml +0 -29
  121. package/_testdriver/acceptance/exec-output.yaml +0 -43
  122. package/_testdriver/acceptance/exec-shell.yaml +0 -40
  123. package/_testdriver/acceptance/focus-window.yaml +0 -16
  124. package/_testdriver/acceptance/hover-image.yaml +0 -18
  125. package/_testdriver/acceptance/hover-text-with-description.yaml +0 -29
  126. package/_testdriver/acceptance/hover-text.yaml +0 -14
  127. package/_testdriver/acceptance/if-else.yaml +0 -31
  128. package/_testdriver/acceptance/match-image.yaml +0 -15
  129. package/_testdriver/acceptance/press-keys.yaml +0 -35
  130. package/_testdriver/acceptance/prompt.yaml +0 -11
  131. package/_testdriver/acceptance/remember.yaml +0 -27
  132. package/_testdriver/acceptance/screenshots/cart.png +0 -0
  133. package/_testdriver/acceptance/scroll-keyboard.yaml +0 -34
  134. package/_testdriver/acceptance/scroll-until-image.yaml +0 -26
  135. package/_testdriver/acceptance/scroll-until-text.yaml +0 -20
  136. package/_testdriver/acceptance/scroll.yaml +0 -33
  137. package/_testdriver/acceptance/snippets/login.yaml +0 -29
  138. package/_testdriver/acceptance/snippets/match-cart.yaml +0 -8
  139. package/_testdriver/acceptance/type.yaml +0 -29
  140. package/_testdriver/behavior/failure.yaml +0 -7
  141. package/_testdriver/behavior/hover-text.yaml +0 -13
  142. package/_testdriver/behavior/lifecycle/postrun.yaml +0 -10
  143. package/_testdriver/behavior/lifecycle/prerun.yaml +0 -8
  144. package/_testdriver/behavior/lifecycle/provision.yaml +0 -8
  145. package/_testdriver/behavior/secrets.yaml +0 -7
  146. package/_testdriver/edge-cases/dashcam-chrome.yaml +0 -8
  147. package/_testdriver/edge-cases/exec-pwsh-multiline.yaml +0 -10
  148. package/_testdriver/edge-cases/js-exception.yaml +0 -8
  149. package/_testdriver/edge-cases/js-promise.yaml +0 -19
  150. package/_testdriver/edge-cases/lifecycle/postrun.yaml +0 -10
  151. package/_testdriver/edge-cases/prompt-in-middle.yaml +0 -23
  152. package/_testdriver/edge-cases/prompt-nested.yaml +0 -7
  153. package/_testdriver/edge-cases/success-test.yaml +0 -9
  154. package/_testdriver/examples/android/example.yaml +0 -12
  155. package/_testdriver/examples/android/lifecycle/postrun.yaml +0 -11
  156. package/_testdriver/examples/android/lifecycle/provision.yaml +0 -47
  157. package/_testdriver/examples/android/readme.md +0 -7
  158. package/_testdriver/examples/chrome-extension/lifecycle/provision.yaml +0 -74
  159. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  160. package/_testdriver/examples/desktop/lifecycle/provision.yaml +0 -64
  161. package/_testdriver/examples/vscode-extension/lifecycle/provision.yaml +0 -73
  162. package/_testdriver/examples/web/lifecycle/postrun.yaml +0 -7
  163. package/_testdriver/examples/web/lifecycle/prerun.yaml +0 -22
  164. package/_testdriver/lifecycle/postrun.yaml +0 -8
  165. package/_testdriver/lifecycle/prerun.yaml +0 -15
  166. package/_testdriver/lifecycle/provision.yaml +0 -25
  167. package/docs/v7/guides/ci-cd/azure.mdx +0 -587
  168. package/docs/v7/guides/ci-cd/circleci.mdx +0 -523
  169. package/docs/v7/guides/ci-cd/github-actions.mdx +0 -457
  170. package/docs/v7/guides/ci-cd/gitlab.mdx +0 -498
  171. package/docs/v7/guides/ci-cd/jenkins.mdx +0 -664
  172. package/docs/v7/guides/ci-cd/travis.mdx +0 -438
  173. package/scripts/view-test-results.mjs +0 -96
  174. package/src/vitest/extended.mjs +0 -108
  175. package/src/vitest/index.mjs +0 -64
  176. package/src/vitest/utils.mjs +0 -150
  177. package/styles/.vale-config/2-MDX.ini +0 -5
  178. package/styles/Microsoft/AMPM.yml +0 -9
  179. package/styles/Microsoft/Accessibility.yml +0 -30
  180. package/styles/Microsoft/Acronyms.yml +0 -64
  181. package/styles/Microsoft/Adverbs.yml +0 -272
  182. package/styles/Microsoft/Auto.yml +0 -11
  183. package/styles/Microsoft/Avoid.yml +0 -14
  184. package/styles/Microsoft/Contractions.yml +0 -50
  185. package/styles/Microsoft/Dashes.yml +0 -13
  186. package/styles/Microsoft/DateFormat.yml +0 -8
  187. package/styles/Microsoft/DateNumbers.yml +0 -40
  188. package/styles/Microsoft/DateOrder.yml +0 -8
  189. package/styles/Microsoft/Ellipses.yml +0 -9
  190. package/styles/Microsoft/FirstPerson.yml +0 -16
  191. package/styles/Microsoft/Foreign.yml +0 -13
  192. package/styles/Microsoft/Gender.yml +0 -8
  193. package/styles/Microsoft/GenderBias.yml +0 -42
  194. package/styles/Microsoft/GeneralURL.yml +0 -11
  195. package/styles/Microsoft/HeadingAcronyms.yml +0 -7
  196. package/styles/Microsoft/HeadingColons.yml +0 -8
  197. package/styles/Microsoft/HeadingPunctuation.yml +0 -13
  198. package/styles/Microsoft/Headings.yml +0 -28
  199. package/styles/Microsoft/Hyphens.yml +0 -14
  200. package/styles/Microsoft/Negative.yml +0 -13
  201. package/styles/Microsoft/Ordinal.yml +0 -13
  202. package/styles/Microsoft/OxfordComma.yml +0 -8
  203. package/styles/Microsoft/Passive.yml +0 -183
  204. package/styles/Microsoft/Percentages.yml +0 -7
  205. package/styles/Microsoft/Plurals.yml +0 -7
  206. package/styles/Microsoft/Quotes.yml +0 -7
  207. package/styles/Microsoft/RangeTime.yml +0 -13
  208. package/styles/Microsoft/Semicolon.yml +0 -8
  209. package/styles/Microsoft/SentenceLength.yml +0 -6
  210. package/styles/Microsoft/Spacing.yml +0 -8
  211. package/styles/Microsoft/Suspended.yml +0 -7
  212. package/styles/Microsoft/Terms.yml +0 -42
  213. package/styles/Microsoft/URLFormat.yml +0 -9
  214. package/styles/Microsoft/Units.yml +0 -16
  215. package/styles/Microsoft/Vocab.yml +0 -25
  216. package/styles/Microsoft/We.yml +0 -11
  217. package/styles/Microsoft/Wordiness.yml +0 -127
  218. package/styles/Microsoft/meta.json +0 -4
  219. package/styles/alex/Ablist.yml +0 -274
  220. package/styles/alex/Condescending.yml +0 -16
  221. package/styles/alex/Gendered.yml +0 -110
  222. package/styles/alex/LGBTQ.yml +0 -55
  223. package/styles/alex/OCD.yml +0 -10
  224. package/styles/alex/Press.yml +0 -12
  225. package/styles/alex/ProfanityLikely.yml +0 -1289
  226. package/styles/alex/ProfanityMaybe.yml +0 -282
  227. package/styles/alex/ProfanityUnlikely.yml +0 -251
  228. package/styles/alex/README.md +0 -27
  229. package/styles/alex/Race.yml +0 -85
  230. package/styles/alex/Suicide.yml +0 -26
  231. package/styles/alex/meta.json +0 -4
  232. package/styles/config/vocabularies/Docs/accept.txt +0 -47
  233. package/styles/config/vocabularies/Docs/reject.txt +0 -4
  234. package/styles/proselint/Airlinese.yml +0 -8
  235. package/styles/proselint/AnimalLabels.yml +0 -48
  236. package/styles/proselint/Annotations.yml +0 -9
  237. package/styles/proselint/Apologizing.yml +0 -8
  238. package/styles/proselint/Archaisms.yml +0 -52
  239. package/styles/proselint/But.yml +0 -8
  240. package/styles/proselint/Cliches.yml +0 -782
  241. package/styles/proselint/CorporateSpeak.yml +0 -30
  242. package/styles/proselint/Currency.yml +0 -5
  243. package/styles/proselint/Cursing.yml +0 -15
  244. package/styles/proselint/DateCase.yml +0 -7
  245. package/styles/proselint/DateMidnight.yml +0 -7
  246. package/styles/proselint/DateRedundancy.yml +0 -10
  247. package/styles/proselint/DateSpacing.yml +0 -7
  248. package/styles/proselint/DenizenLabels.yml +0 -52
  249. package/styles/proselint/Diacritical.yml +0 -95
  250. package/styles/proselint/GenderBias.yml +0 -45
  251. package/styles/proselint/GroupTerms.yml +0 -39
  252. package/styles/proselint/Hedging.yml +0 -8
  253. package/styles/proselint/Hyperbole.yml +0 -6
  254. package/styles/proselint/Jargon.yml +0 -11
  255. package/styles/proselint/LGBTOffensive.yml +0 -13
  256. package/styles/proselint/LGBTTerms.yml +0 -15
  257. package/styles/proselint/Malapropisms.yml +0 -8
  258. package/styles/proselint/Needless.yml +0 -358
  259. package/styles/proselint/Nonwords.yml +0 -38
  260. package/styles/proselint/Oxymorons.yml +0 -22
  261. package/styles/proselint/P-Value.yml +0 -6
  262. package/styles/proselint/RASSyndrome.yml +0 -30
  263. package/styles/proselint/README.md +0 -12
  264. package/styles/proselint/Skunked.yml +0 -13
  265. package/styles/proselint/Spelling.yml +0 -17
  266. package/styles/proselint/Typography.yml +0 -11
  267. package/styles/proselint/Uncomparables.yml +0 -50
  268. package/styles/proselint/Very.yml +0 -6
  269. package/styles/proselint/meta.json +0 -15
  270. package/styles/write-good/Cliches.yml +0 -702
  271. package/styles/write-good/E-Prime.yml +0 -32
  272. package/styles/write-good/Illusions.yml +0 -11
  273. package/styles/write-good/Passive.yml +0 -183
  274. package/styles/write-good/README.md +0 -27
  275. package/styles/write-good/So.yml +0 -5
  276. package/styles/write-good/ThereIs.yml +0 -6
  277. package/styles/write-good/TooWordy.yml +0 -221
  278. package/styles/write-good/Weasel.yml +0 -29
  279. package/styles/write-good/meta.json +0 -4
  280. package/test/dashcam.test.js +0 -137
  281. package/test/mcp-example-test.yaml +0 -27
  282. package/test/test_parser.js +0 -47
  283. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +0 -61
  284. package/testdriver/acceptance-sdk/README.md +0 -128
  285. package/testdriver/acceptance-sdk/TEST_REPORTING.md +0 -245
  286. package/testdriver/acceptance-sdk/assert.test.mjs +0 -26
  287. package/testdriver/acceptance-sdk/hooks-example.test.mjs +0 -38
  288. package/testdriver/acceptance-sdk/presets-example.test.mjs +0 -87
  289. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +0 -420
  290. package/testdriver/acceptance-sdk/sully-ai.test.mjs +0 -234
  291. package/testdriver/acceptance-sdk/type-checking-demo.js +0 -49
  292. package/vale.ini +0 -18
  293. package/vitest.config.example.js +0 -19
  294. package/vitest.config.mjs.bak +0 -44
  295. /package/docs/{ARCHITECTURE.md → v7/_drafts/architecture.mdx} +0 -0
  296. /package/docs/{AWESOME_LOGS_QUICK_REF.md → v7/_drafts/awesome-logs-quick-ref.mdx} +0 -0
  297. /package/docs/v7/{guides → _drafts}/best-practices.mdx +0 -0
  298. /package/docs/v7/{guides → _drafts}/caching-ai.mdx +0 -0
  299. /package/docs/v7/{guides → _drafts}/caching.mdx +0 -0
  300. /package/docs/{MIGRATION.md → v7/_drafts/cli-to-sdk-migration.mdx} +0 -0
  301. /package/{CONTRIBUTING.md → docs/v7/_drafts/contributing.mdx} +0 -0
  302. /package/docs/v7/{progressive-apis/CORE.md → _drafts/core.mdx} +0 -0
  303. /package/docs/v7/{guides → _drafts}/debugging.mdx +0 -0
  304. /package/docs/v7/{guides → _drafts}/faq.mdx +0 -0
  305. /package/docs/v7/{progressive-apis/HOOKS.md → _drafts/hooks.mdx} +0 -0
  306. /package/docs/v7/{guides → _drafts}/migration.mdx +0 -0
  307. /package/docs/v7/{guides → _drafts}/performance.mdx +0 -0
  308. /package/docs/{PRESETS.md → v7/_drafts/presets.mdx} +0 -0
  309. /package/docs/v7/{progressive-apis/PROGRESSIVE_DISCLOSURE.md → _drafts/progressive-disclosure.mdx} +0 -0
  310. /package/docs/v7/{progressive-apis/PROVISION.md → _drafts/provision.mdx} +0 -0
  311. /package/docs/{SDK_AWESOME_LOGS.md → v7/_drafts/sdk-awesome-logs.mdx} +0 -0
  312. /package/docs/{sdk-browser-rendering.md → v7/_drafts/sdk-browser-rendering.mdx} +0 -0
  313. /package/docs/{TEST_RECORDING.md → v7/_drafts/test-recording.mdx} +0 -0
  314. /package/docs/v7/{guides → _drafts}/vitest.mdx +0 -0
  315. /package/docs/v7/{README.md → overview/readme.mdx} +0 -0
  316. /package/{src → lib}/core/index.d.ts +0 -0
  317. /package/{src → lib}/core/index.js +0 -0
  318. /package/{src → lib}/presets/index.mjs +0 -0
  319. /package/{src → lib}/vitest/hooks.d.ts +0 -0
  320. /package/{debug-locate-response.js → test/manual/debug-locate-response.js} +0 -0
  321. /package/{verify-element-api.js → test/manual/verify-element-api.js} +0 -0
  322. /package/{verify-types.js → test/manual/verify-types.js} +0 -0
  323. /package/{testdriver/acceptance-sdk → test/testdriver}/chrome-extension.test.mjs +0 -0
  324. /package/{testdriver/acceptance-sdk → test/testdriver}/setup/globalTeardown.mjs +0 -0
  325. /package/{testdriver/acceptance-sdk → test/testdriver}/setup/vitestSetup.mjs +0 -0
@@ -0,0 +1,167 @@
1
+ # Auto-Generated Cache Keys from File Hash
2
+
3
+ ## Overview
4
+
5
+ When you create a TestDriver instance without providing an explicit `cacheKey`, the SDK will automatically generate one based on the SHA-256 hash of the calling file. This provides automatic cache invalidation when your test file changes, while enabling cache hits for identical test runs.
6
+
7
+ ## How It Works
8
+
9
+ 1. **Stack Trace Analysis**: When `TestDriver()` is called, the SDK analyzes the call stack to find the caller file
10
+ 2. **File Hashing**: The content of the caller file is hashed using SHA-256
11
+ 3. **Cache Key Generation**: The first 16 characters of the hash are used as the cache key
12
+ 4. **Automatic Updates**: When the test file is modified, the hash changes, automatically invalidating the cache
13
+
14
+ ## Benefits
15
+
16
+ - ✅ **No Manual Cache Management**: Cache keys are automatically generated and updated
17
+ - ✅ **File-Scoped Caching**: All tests in the same file share the same cache
18
+ - ✅ **Automatic Invalidation**: Cache is invalidated when the test file changes
19
+ - ✅ **Explicit Override**: You can still provide a manual `cacheKey` if needed
20
+
21
+ ## Usage Examples
22
+
23
+ ### Automatic Cache Key (Recommended)
24
+
25
+ ```javascript
26
+ import { TestDriver } from 'testdriverai/vitest/hooks';
27
+
28
+ test('login test', async (context) => {
29
+ // No cacheKey provided - will be auto-generated from this file's hash
30
+ const testdriver = TestDriver(context, {
31
+ headless: true
32
+ });
33
+
34
+ // Cache key is automatically set based on this file
35
+ console.log(testdriver.options.cacheKey); // e.g., "4cae7be040f293b9"
36
+
37
+ const button = await testdriver.find('login button');
38
+ // Subsequent calls in this test file will use the same cache
39
+ });
40
+ ```
41
+
42
+ ### Explicit Cache Key (Override)
43
+
44
+ ```javascript
45
+ import { TestDriver } from 'testdriverai/vitest/hooks';
46
+
47
+ test('login test', async (context) => {
48
+ // Explicit cacheKey provided - auto-generation is skipped
49
+ const testdriver = TestDriver(context, {
50
+ headless: true,
51
+ cacheKey: 'my-custom-key-v1'
52
+ });
53
+
54
+ console.log(testdriver.options.cacheKey); // "my-custom-key-v1"
55
+
56
+ const button = await testdriver.find('login button');
57
+ });
58
+ ```
59
+
60
+ ## Cache Behavior
61
+
62
+ ### With Auto-Generated Key
63
+
64
+ 1. **First Run**: Creates cache entries with key = hash of test file
65
+ 2. **Subsequent Runs** (file unchanged): Cache hits
66
+ 3. **After File Modification**: New hash = new cache key = cache miss
67
+
68
+ ### Cache Hit Example
69
+
70
+ ```javascript
71
+ // File: login.test.mjs (hash: 4cae7be040f293b9)
72
+
73
+ const testdriver = TestDriver(context);
74
+ // Auto-generated cacheKey: "4cae7be040f293b9"
75
+
76
+ const button1 = await testdriver.find('login button'); // Cache MISS (first time)
77
+ const button2 = await testdriver.find('login button'); // Cache HIT (same file, same test run)
78
+ ```
79
+
80
+ After modifying the file (adding a comment, changing test logic, etc.):
81
+
82
+ ```javascript
83
+ // File: login.test.mjs (hash: 7f3d9a2b1c5e8f6a) <- changed!
84
+
85
+ const testdriver = TestDriver(context);
86
+ // Auto-generated cacheKey: "7f3d9a2b1c5e8f6a" <- different from before
87
+
88
+ const button1 = await testdriver.find('login button'); // Cache MISS (new hash)
89
+ ```
90
+
91
+ ## Debug Mode
92
+
93
+ To see the auto-generated cache key in debug logs:
94
+
95
+ ```bash
96
+ # Set environment variable
97
+ export TD_DEBUG=1
98
+
99
+ # Or in your test
100
+ process.env.TD_DEBUG = '1';
101
+ ```
102
+
103
+ With debug mode enabled, you'll see:
104
+ ```
105
+ 🔍 find() threshold: 0.05 (cache ENABLED, cacheKey: 4cae7be040f293b9 (auto-generated from file hash))
106
+ ```
107
+
108
+ ## Implementation Details
109
+
110
+ ### Stack Trace Filtering
111
+
112
+ The auto-generation skips the following in the stack trace to find the actual test file:
113
+ - `sdk.js` (TestDriver SDK)
114
+ - `hooks.mjs` / `hooks.js` (Vitest hooks)
115
+ - `node_modules` (dependencies)
116
+ - `node:internal` (Node.js internals)
117
+
118
+ ### File Path Handling
119
+
120
+ The implementation handles both:
121
+ - Regular file paths: `/Users/you/project/test.mjs`
122
+ - File URL format: `file:///Users/you/project/test.mjs`
123
+
124
+ ### Hash Format
125
+
126
+ - Algorithm: SHA-256
127
+ - Output: First 16 hexadecimal characters (e.g., `4cae7be040f293b9`)
128
+ - Collision probability: Effectively zero for practical purposes
129
+
130
+ ## When to Use Manual Cache Keys
131
+
132
+ Consider using manual `cacheKey` values when:
133
+
134
+ 1. **Cross-File Caching**: You want to share cache across multiple test files
135
+ 2. **Version-Based Caching**: You want explicit control over cache invalidation
136
+ 3. **CI/CD Integration**: You want to tie caching to build numbers or git commits
137
+
138
+ Example:
139
+
140
+ ```javascript
141
+ const cacheKey = \`test-suite-\${process.env.GIT_COMMIT}\`;
142
+ const testdriver = TestDriver(context, { cacheKey });
143
+ ```
144
+
145
+ ## Migration from Manual Keys
146
+
147
+ If you currently use manual cache keys:
148
+
149
+ ### Before
150
+ ```javascript
151
+ const testdriver = TestDriver(context, {
152
+ cacheKey: 'login-test-v1'
153
+ });
154
+ ```
155
+
156
+ ### After (automatic)
157
+ ```javascript
158
+ // Just remove the cacheKey - it will be auto-generated!
159
+ const testdriver = TestDriver(context);
160
+ ```
161
+
162
+ The cache will automatically invalidate when the test file changes, which is usually the desired behavior.
163
+
164
+ ## See Also
165
+
166
+ - [SDK_README.md](./SDK_README.md) - Cache configuration options
167
+ - [CACHE_ARCHITECTURE.md](../api/CACHE_ARCHITECTURE.md) - Cache system architecture
@@ -9,12 +9,76 @@ icon: "crosshairs"
9
9
 
10
10
  The Selector Cache stores element locations on the server, so `.find()` calls can skip the AI vision analysis.
11
11
 
12
+ **Important:** Selector caching is **disabled by default** as of v7.1. You must provide a `cacheKey` to enable caching.
13
+
12
14
  This provides:
13
15
  - ⚡ **Up to 10x faster** - Skip AI vision analysis
14
16
  - 💰 **Lower AI costs** - Fewer vision API calls
15
17
  - 🎯 **Consistent results** - Same UI = same coordinates
16
18
  - 📊 **Metrics tracking** - See cache hit rates in console
17
19
 
20
+ ## Enabling the Cache
21
+
22
+ ### Auto-Generated Cache Keys (Recommended)
23
+
24
+ TestDriver automatically generates cache keys based on your test file:
25
+
26
+ ```javascript
27
+ // Cache automatically enabled - uses file hash as cache key
28
+ const button = await testdriver.find('submit button');
29
+ // Cache key: "a1b2c3d4e5f6..." (first 16 chars of file SHA-256)
30
+ ```
31
+
32
+ **Benefits:**
33
+ - ✅ **Per-file isolation** - Each test file has its own cache
34
+ - ✅ **Auto-invalidation** - Cache updates when test code changes
35
+ - ✅ **Zero configuration** - Works out of the box
36
+ - ✅ **Safe** - No cross-test pollution
37
+
38
+ ### Custom Cache Keys
39
+
40
+ Provide your own cache key for more control:
41
+
42
+ ```javascript
43
+ // Custom cache key
44
+ const button = await testdriver.find('submit button', {
45
+ cacheKey: 'my-test-key'
46
+ });
47
+
48
+ // Share cache across tests
49
+ const button = await testdriver.find('submit button', {
50
+ cacheKey: 'shared-submit-button'
51
+ });
52
+ ```
53
+
54
+ ### Global Cache Key
55
+
56
+ Enable caching for all finds in your test:
57
+
58
+ ```javascript
59
+ const client = new TestDriver(apiKey, {
60
+ cacheKey: 'my-global-key' // All finds will use this cache
61
+ });
62
+
63
+ // Now all finds are cached
64
+ await testdriver.find('button 1'); // Uses 'my-global-key'
65
+ await testdriver.find('button 2'); // Uses 'my-global-key'
66
+ ```
67
+
68
+ ### Disable Auto-Cache
69
+
70
+ If you don't want automatic caching:
71
+
72
+ ```javascript
73
+ // Disable cache for this find
74
+ await testdriver.find('button', { cacheThreshold: -1 });
75
+
76
+ // Or use a threshold of -1 globally
77
+ const client = new TestDriver(apiKey, {
78
+ cacheThreshold: { find: -1, findAll: -1 }
79
+ });
80
+ ```
81
+
18
82
  ## How It Works
19
83
 
20
84
  ```mermaid
@@ -65,22 +129,32 @@ The selector cache uses a three-tier matching system:
65
129
 
66
130
  ## Controlling Cache Threshold
67
131
 
68
- Adjust similarity threshold per call:
132
+ Adjust similarity threshold when cache is enabled:
69
133
 
70
134
  ```javascript
71
135
  // Default: 95% similarity (5% difference allowed)
72
- await testdriver.find('submit button');
136
+ await testdriver.find('submit button', { cacheKey: 'test-1' });
73
137
 
74
138
  // Stricter: 99% similarity (1% difference allowed)
75
- await testdriver.find('submit button', { threshold: 0.01 });
139
+ await testdriver.find('submit button', {
140
+ cacheKey: 'test-1',
141
+ cacheThreshold: 0.01
142
+ });
76
143
 
77
144
  // More lenient: 90% similarity (10% difference allowed)
78
- await testdriver.find('submit button', { threshold: 0.10 });
145
+ await testdriver.find('submit button', {
146
+ cacheKey: 'test-1',
147
+ cacheThreshold: 0.10
148
+ });
79
149
 
80
150
  // Disable cache: force fresh AI analysis
81
- await testdriver.find('submit button', { threshold: -1 });
151
+ await testdriver.find('submit button', { cacheThreshold: -1 });
82
152
  ```
83
153
 
154
+ <Note>
155
+ `cacheThreshold` only works when caching is enabled via `cacheKey` or global config.
156
+ </Note>
157
+
84
158
  ## Cache Filtering
85
159
 
86
160
  The selector cache automatically filters by:
@@ -126,13 +200,19 @@ test('find element', async (context) => {
126
200
  url: 'https://example.com'
127
201
  });
128
202
 
203
+ // Auto-cache enabled (uses file hash as cache key)
129
204
  // First call: AI vision analysis, saves to cache
130
205
  const button = await testdriver.find('More information link');
131
- console.log('Cache hit:', button.cacheHit); // false
206
+ console.log('Cache hit:', button.cacheHit); // false (first run)
132
207
 
133
208
  // Second call: uses cache (instant)
134
209
  const button2 = await testdriver.find('More information link');
135
- console.log('Cache hit:', button2.cacheHit); // true
210
+ console.log('Cache hit:', button2.cacheHit); // true (cache hit)
211
+
212
+ // Custom cache key
213
+ const button3 = await testdriver.find('submit button', {
214
+ cacheKey: 'my-button'
215
+ });
136
216
  });
137
217
  ```
138
218
 
@@ -142,14 +222,20 @@ test('find element', async (context) => {
142
222
  test('strict vs lenient matching', async (context) => {
143
223
  const { testdriver } = await chrome(context, { url });
144
224
 
145
- // Strict: 99% similarity required
146
- const elem1 = await testdriver.find('button', { threshold: 0.01 });
225
+ // Strict: 99% similarity required (auto-cache key)
226
+ const elem1 = await testdriver.find('button', { cacheThreshold: 0.01 });
147
227
 
148
228
  // Lenient: 90% similarity acceptable
149
- const elem2 = await testdriver.find('button', { threshold: 0.10 });
229
+ const elem2 = await testdriver.find('button', { cacheThreshold: 0.10 });
230
+
231
+ // Bypass cache entirely (no cacheKey needed)
232
+ const elem3 = await testdriver.find('button', { cacheThreshold: -1 });
150
233
 
151
- // Bypass cache entirely
152
- const elem3 = await testdriver.find('button', { threshold: -1 });
234
+ // Custom cache key with threshold
235
+ const elem4 = await testdriver.find('button', {
236
+ cacheKey: 'my-button',
237
+ cacheThreshold: 0.05
238
+ });
153
239
  });
154
240
  ```
155
241
 
@@ -159,12 +245,21 @@ test('strict vs lenient matching', async (context) => {
159
245
  test('monitor cache performance', async (context) => {
160
246
  const { testdriver } = await chrome(context, { url });
161
247
 
248
+ // Auto-cache enabled
162
249
  const element = await testdriver.find('submit button');
163
250
 
164
251
  if (element.cacheHit) {
165
252
  console.log('✅ Cache hit - instant response');
253
+ console.log('Cache strategy:', element.cacheStrategy);
254
+ console.log('Cache age:', element.cacheCreatedAt);
166
255
  } else {
167
256
  console.log('⏱️ Cache miss - AI analysis performed');
257
+ console.log('New cache entry created');
258
+ }
259
+
260
+ // Check similarity score
261
+ if (element.similarity) {
262
+ console.log(`Similarity: ${(element.similarity * 100).toFixed(1)}%`);
168
263
  }
169
264
  });
170
265
  ```
@@ -174,17 +269,30 @@ test('monitor cache performance', async (context) => {
174
269
  ### 1. Use Appropriate Thresholds
175
270
 
176
271
  ```javascript
177
- // Stable UI: strict threshold
178
- await testdriver.find('logo', { threshold: 0.01 });
272
+ // Stable UI: strict threshold (auto-cache)
273
+ await testdriver.find('logo', { cacheThreshold: 0.01 });
179
274
 
180
275
  // Dynamic UI: lenient threshold
181
- await testdriver.find('news feed item', { threshold: 0.10 });
276
+ await testdriver.find('news feed item', { cacheThreshold: 0.10 });
182
277
 
183
278
  // Always fresh: disable cache
184
- await testdriver.find('timestamp', { threshold: -1 });
279
+ await testdriver.find('timestamp', { cacheThreshold: -1 });
185
280
  ```
186
281
 
187
- ### 2. Monitor Cache Performance
282
+ ### 2. Choose Cache Key Strategy
283
+
284
+ ```javascript
285
+ // Auto-cache (recommended) - per-file isolation
286
+ await testdriver.find('button');
287
+
288
+ // Custom key - share across tests
289
+ await testdriver.find('button', { cacheKey: 'global-submit' });
290
+
291
+ // Global key - all finds in test
292
+ const testdriver = new TestDriver(apiKey, {
293
+ cacheKey: 'test-suite-1'
294
+ });
295
+ ```
188
296
 
189
297
  Check [console.testdriver.ai](https://console.testdriver.ai) regularly to:
190
298
  - See cache hit rates
@@ -0,0 +1,89 @@
1
+ # Dashcam Recording Titles
2
+
3
+ ## Overview
4
+
5
+ Dashcam recordings now automatically use meaningful titles instead of the generic "Dashcam Recording" label.
6
+
7
+ ## Automatic Title Generation
8
+
9
+ When using TestDriver with Vitest, the dashcam recording title is automatically generated from:
10
+ 1. **Test file name** - Extracted from the test file path
11
+ 2. **Test name** - The name of the test case
12
+
13
+ ### Example
14
+
15
+ For a test file `login.test.mjs` with test case `"should login successfully"`:
16
+ ```
17
+ Recording title: "login - should login successfully"
18
+ ```
19
+
20
+ For standalone usage without test context:
21
+ ```
22
+ Recording title: "Recording 2025-12-02 14:30:45"
23
+ ```
24
+
25
+ ## Custom Titles
26
+
27
+ You can set a custom title before starting the dashcam recording:
28
+
29
+ ### With Vitest Integration
30
+
31
+ ```javascript
32
+ import { test } from 'vitest';
33
+ import { TestDriver } from 'testdriverai/vitest';
34
+
35
+ test('my test', async (context) => {
36
+ const testdriver = TestDriver(context, { headless: true });
37
+
38
+ // Set custom title before dashcam starts
39
+ testdriver.dashcam.setTitle('My Custom Recording Title');
40
+
41
+ // Start recording (provision methods start dashcam automatically)
42
+ await testdriver.provision.chrome({ url: 'https://example.com' });
43
+
44
+ await testdriver.find('button').click();
45
+ });
46
+ ```
47
+
48
+ ### Direct SDK Usage
49
+
50
+ ```javascript
51
+ const TestDriver = require('testdriverai');
52
+
53
+ const client = new TestDriver(process.env.TD_API_KEY);
54
+ await client.connect();
55
+
56
+ // Set custom title
57
+ client.dashcam.setTitle('Integration Test - Payment Flow');
58
+
59
+ // Start recording
60
+ await client.dashcam.start();
61
+
62
+ await client.provision.chrome({ url: 'https://example.com' });
63
+ await client.find('Checkout button').click();
64
+
65
+ // Stop recording and get URL
66
+ const dashcamUrl = await client.dashcam.stop();
67
+ console.log('Recording:', dashcamUrl);
68
+ ```
69
+
70
+ ## Constructor Option
71
+
72
+ You can also pass a title when creating the Dashcam instance:
73
+
74
+ ```javascript
75
+ const { Dashcam } = require('testdriverai/core');
76
+
77
+ const dashcam = new Dashcam(client, {
78
+ title: 'Custom Title',
79
+ autoStart: true
80
+ });
81
+ ```
82
+
83
+ ## Implementation Details
84
+
85
+ - **Default title generation** uses test context (`__vitestContext`) when available
86
+ - **Test file names** are cleaned (removes `.test`, `.spec`, file extensions)
87
+ - **Fallback** to ISO timestamp if no test context is available
88
+ - **Title escaping** handles special characters in shell commands properly
89
+ - **Cross-platform** support for Windows (PowerShell) and Linux/Mac (bash/zsh)