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,514 @@
1
+ ---
2
+ title: "Stable & Reliable"
3
+ description: "Anti-flake technology that eliminates test instability"
4
+ icon: "shield-check"
5
+ ---
6
+
7
+ Test flakiness is the bane of CI/CD pipelines. TestDriver eliminates flaky tests with built-in anti-flake technology that automatically handles timing issues, animations, and dynamic content.
8
+
9
+ ## The Flaky Test Problem
10
+
11
+ Traditional test frameworks suffer from race conditions and timing issues:
12
+
13
+ <CodeGroup>
14
+ ```javascript Traditional - Flaky
15
+ // ❌ May fail randomly
16
+ await page.click('button');
17
+ await page.click('.dropdown-item'); // Element might not be ready!
18
+
19
+ // ❌ Arbitrary waits
20
+ await page.click('button');
21
+ await page.waitForTimeout(1000); // Hope 1 second is enough
22
+ await page.click('.dropdown-item');
23
+
24
+ // ❌ Complex wait logic
25
+ await page.click('button');
26
+ await page.waitForSelector('.dropdown-item', {
27
+ state: 'visible',
28
+ timeout: 5000
29
+ });
30
+ await page.waitForLoadState('networkidle');
31
+ await page.waitForTimeout(200); // Still need extra buffer!
32
+ await page.click('.dropdown-item');
33
+ ```
34
+
35
+ ```javascript TestDriver - Stable
36
+ // ✅ Just works
37
+ await testdriver.find('button').click();
38
+ await testdriver.find('dropdown item').click();
39
+ // TestDriver automatically waits for stability
40
+ ```
41
+ </CodeGroup>
42
+
43
+ <Check>
44
+ TestDriver handles all timing automatically. No explicit waits, no arbitrary timeouts, no flaky tests.
45
+ </Check>
46
+
47
+ ## Redraw Detection
48
+
49
+ TestDriver's redraw detection system automatically waits for the UI to stabilize before taking any action.
50
+
51
+ <Card title="What Redraw Detects" icon="eye">
52
+ The system monitors multiple stability signals:
53
+
54
+ - **DOM Mutations** - Element additions, removals, or attribute changes
55
+ - **Layout Reflows** - Position or size changes
56
+ - **CSS Animations** - Running animations and transitions
57
+ - **Network Activity** - Pending XHR/fetch requests
58
+ - **Visual Changes** - Pixel-level screenshot differences
59
+ - **Loading Indicators** - Spinners, progress bars, skeleton screens
60
+ </Card>
61
+
62
+ ### How It Works
63
+
64
+ ```mermaid
65
+ sequenceDiagram
66
+ participant Test as Your Test
67
+ participant TD as TestDriver
68
+ participant Monitor as Redraw Monitor
69
+ participant UI as Application UI
70
+
71
+ Test->>TD: find('dropdown item').click()
72
+ TD->>Monitor: Start monitoring stability
73
+ Monitor->>UI: Capture initial state
74
+
75
+ loop Stability Check
76
+ Monitor->>UI: Check for changes
77
+ alt UI is changing
78
+ UI-->>Monitor: DOM mutation detected
79
+ Monitor->>Monitor: Reset stability timer
80
+ else UI is stable
81
+ UI-->>Monitor: No changes
82
+ Monitor->>Monitor: Increment stable duration
83
+ end
84
+ end
85
+
86
+ Monitor->>TD: UI stable for 200ms
87
+ TD->>UI: Perform click action
88
+ TD-->>Test: Action completed
89
+ ```
90
+
91
+ ### Configurable Stability
92
+
93
+ Fine-tune stability detection for your application's needs:
94
+
95
+ ```javascript
96
+ // Default stability settings (recommended)
97
+ await testdriver.find('button').click();
98
+
99
+ // Custom stability delay
100
+ await testdriver.find('animated button', {
101
+ stabilityDelay: 500 // Wait 500ms of stability before acting
102
+ }).click();
103
+
104
+ // Bypass stability (advanced)
105
+ await testdriver.find('element', {
106
+ stabilityDelay: 0 // Act immediately
107
+ }).click();
108
+ ```
109
+
110
+ <Tip>
111
+ The default 200ms stability delay works for 95% of applications. Only adjust if you have unusually long animations or need instant actions.
112
+ </Tip>
113
+
114
+ ## Network Monitoring
115
+
116
+ TestDriver waits for network activity to complete before asserting or locating elements:
117
+
118
+ <AccordionGroup>
119
+ <Accordion title="Automatic Network Waiting">
120
+ ```javascript
121
+ // TestDriver automatically waits for:
122
+ // 1. Pending XHR/fetch requests to complete
123
+ // 2. WebSocket messages to be processed
124
+ // 3. Image/asset loading to finish
125
+
126
+ await testdriver.find('submit button').click();
127
+ // ↑ Triggers API call
128
+
129
+ await testdriver.assert('Success message is visible');
130
+ // ↑ Automatically waits for API response before asserting
131
+ ```
132
+
133
+ No need for manual `waitForResponse` or `waitForLoadState` calls.
134
+ </Accordion>
135
+
136
+ <Accordion title="Loading Indicator Detection">
137
+ ```javascript
138
+ // TestDriver detects common loading patterns:
139
+ await testdriver.find('Load More button').click();
140
+
141
+ // Automatically waits for:
142
+ // - Loading spinner to appear and disappear
143
+ // - Skeleton screens to be replaced
144
+ // - Progress bars to complete
145
+ // - "Loading..." text to disappear
146
+
147
+ await testdriver.find('newly loaded content').click();
148
+ ```
149
+
150
+ Common loading indicators are recognized and waited for automatically.
151
+ </Accordion>
152
+
153
+ <Accordion title="Custom Network Conditions">
154
+ ```javascript
155
+ // For slow networks or long-running requests
156
+ await testdriver.find('submit button', {
157
+ timeout: 60000, // Wait up to 60 seconds
158
+ networkTimeout: 30000 // Allow 30s for network requests
159
+ }).click();
160
+ ```
161
+ </Accordion>
162
+ </AccordionGroup>
163
+
164
+ ## Screen Stability Monitoring
165
+
166
+ Visual stability is critical for reliable element location:
167
+
168
+ ```javascript
169
+ // TestDriver monitors pixel-level changes
170
+ await testdriver.find('animated element').click();
171
+
172
+ // Waits for:
173
+ // ✓ CSS animations to complete
174
+ // ✓ Fade-in/fade-out effects to finish
175
+ // ✓ Slide transitions to settle
176
+ // ✓ Scroll animations to stop
177
+ // ✓ Dynamic content to load
178
+ ```
179
+
180
+ <Card title="Example: Accordion Animation" icon="angles-down">
181
+ ```javascript
182
+ // Traditional approach - prone to failure
183
+ await page.click('.accordion-header');
184
+ await page.waitForTimeout(300); // Hope animation is done
185
+ await page.click('.accordion-content button'); // Might fail!
186
+
187
+ // TestDriver - just works
188
+ await testdriver.find('accordion header').click();
189
+ await testdriver.find('button inside accordion content').click();
190
+ // ✅ Automatically waits for accordion animation to complete
191
+ ```
192
+ </Card>
193
+
194
+ ## Retry Logic
195
+
196
+ TestDriver includes intelligent retry logic that adapts to your application:
197
+
198
+ <Steps>
199
+ <Step title="Initial Attempt">
200
+ Try to locate the element immediately.
201
+
202
+ ```javascript
203
+ const element = await testdriver.find('button');
204
+ // Attempts location immediately
205
+ ```
206
+ </Step>
207
+
208
+ <Step title="Wait for Stability">
209
+ If not found, wait for UI stability and retry.
210
+
211
+ ```javascript
212
+ // Waits for:
213
+ // - DOM mutations to stop
214
+ // - Network requests to complete
215
+ // - Animations to finish
216
+ ```
217
+ </Step>
218
+
219
+ <Step title="Retry with Interval">
220
+ Continue retrying at regular intervals until timeout.
221
+
222
+ ```javascript
223
+ await testdriver.find('button', {
224
+ timeout: 30000, // Try for up to 30 seconds
225
+ retryInterval: 500 // Check every 500ms
226
+ });
227
+ ```
228
+ </Step>
229
+
230
+ <Step title="Provide Debug Info">
231
+ If still not found, provide detailed debugging information.
232
+
233
+ ```javascript
234
+ try {
235
+ await testdriver.find('missing button');
236
+ } catch (error) {
237
+ console.log('Debug screenshot:', error.debugScreenshot);
238
+ console.log('Similarity score:', error.similarity);
239
+ console.log('Cache info:', error.cacheInfo);
240
+ }
241
+ ```
242
+ </Step>
243
+ </Steps>
244
+
245
+ ## Configurable Timeouts
246
+
247
+ Customize retry behavior for different scenarios:
248
+
249
+ <Tabs>
250
+ <Tab title="Fast Elements">
251
+ ```javascript
252
+ // For elements that appear quickly
253
+ await testdriver.find('header logo', {
254
+ timeout: 5000 // 5 seconds (faster failure)
255
+ });
256
+ ```
257
+ </Tab>
258
+
259
+ <Tab title="Slow Elements">
260
+ ```javascript
261
+ // For elements that take time to load
262
+ await testdriver.find('search results', {
263
+ timeout: 30000, // 30 seconds
264
+ retryInterval: 1000 // Check every second
265
+ });
266
+ ```
267
+ </Tab>
268
+
269
+ <Tab title="Critical Elements">
270
+ ```javascript
271
+ // For absolutely critical elements
272
+ await testdriver.find('payment confirmation', {
273
+ timeout: 60000, // 1 minute
274
+ retryInterval: 2000, // Check every 2 seconds
275
+ stabilityDelay: 1000 // Wait 1 second of stability
276
+ });
277
+ ```
278
+ </Tab>
279
+ </Tabs>
280
+
281
+ ## Real-World Stability Improvements
282
+
283
+ Compare flake rates before and after TestDriver:
284
+
285
+ <CardGroup cols={2}>
286
+ <Card title="Before TestDriver" icon="triangle-exclamation">
287
+ ```
288
+ Test Suite: E2E Tests
289
+ Total: 100 tests
290
+ Passed: 87
291
+ Failed: 13
292
+
293
+ Flaky tests:
294
+ - login_test (timing)
295
+ - dropdown_test (animation)
296
+ - modal_test (async content)
297
+ - search_test (debounce)
298
+
299
+ Flake rate: 13%
300
+ CI reruns needed: 3-5x
301
+ ```
302
+ </Card>
303
+
304
+ <Card title="After TestDriver" icon="circle-check">
305
+ ```
306
+ Test Suite: E2E Tests
307
+ Total: 100 tests
308
+ Passed: 100
309
+ Failed: 0
310
+
311
+ Flaky tests: None
312
+
313
+ Flake rate: 0%
314
+ CI reruns needed: 0
315
+ Stable builds: 100%
316
+ ```
317
+ </Card>
318
+ </CardGroup>
319
+
320
+ <Check>
321
+ **Result: 100% stability** - Eliminated all flaky tests without changing test code.
322
+ </Check>
323
+
324
+ ## Advanced: Redraw Configuration
325
+
326
+ The redraw system is configurable through [redraw.js](/agent/lib/redraw.js):
327
+
328
+ ```javascript
329
+ // Global redraw settings
330
+ const testdriver = new TestDriver({
331
+ apiKey: process.env.TD_API_KEY,
332
+ redraw: {
333
+ enabled: true,
334
+ stabilityDelay: 200, // Default stability wait (ms)
335
+ maxStabilityWait: 5000, // Maximum time to wait for stability
336
+ checkInterval: 50, // How often to check for stability
337
+ networkIdle: true, // Wait for network idle
338
+ domIdle: true, // Wait for DOM mutations to stop
339
+ animationIdle: true, // Wait for CSS animations
340
+ }
341
+ });
342
+ ```
343
+
344
+ ### Per-Action Configuration
345
+
346
+ ```javascript
347
+ // Override redraw settings for specific actions
348
+ await testdriver.find('fast element', {
349
+ redraw: {
350
+ enabled: false // Skip redraw detection
351
+ }
352
+ }).click();
353
+
354
+ await testdriver.find('slow element', {
355
+ redraw: {
356
+ stabilityDelay: 1000, // Wait longer for stability
357
+ networkIdle: true
358
+ }
359
+ }).click();
360
+ ```
361
+
362
+ ## Debugging Stability Issues
363
+
364
+ If you encounter stability issues, TestDriver provides detailed diagnostics:
365
+
366
+ ```javascript
367
+ try {
368
+ await testdriver.find('unstable element', {
369
+ debug: true // Enable debug logging
370
+ });
371
+ } catch (error) {
372
+ console.log('Stability info:', error.stabilityInfo);
373
+ // Output:
374
+ // {
375
+ // domMutations: 15,
376
+ // layoutReflows: 3,
377
+ // networkRequests: 2,
378
+ // animations: ['fade-in', 'slide-up'],
379
+ // waitedMs: 5000,
380
+ // stableMs: 150
381
+ // }
382
+ }
383
+ ```
384
+
385
+ ## Common Stability Patterns
386
+
387
+ <AccordionGroup>
388
+ <Accordion title="Dropdown Menus">
389
+ ```javascript
390
+ // Traditional - flaky
391
+ await page.click('.menu-button');
392
+ await page.waitForTimeout(200);
393
+ await page.click('.menu-item');
394
+
395
+ // TestDriver - stable
396
+ await testdriver.find('menu button').click();
397
+ await testdriver.find('menu item').click();
398
+ ```
399
+ </Accordion>
400
+
401
+ <Accordion title="Modal Dialogs">
402
+ ```javascript
403
+ // Traditional - flaky
404
+ await page.click('.open-modal');
405
+ await page.waitForSelector('.modal', { state: 'visible' });
406
+ await page.waitForTimeout(300); // Wait for animation
407
+ await page.click('.modal-button');
408
+
409
+ // TestDriver - stable
410
+ await testdriver.find('open modal button').click();
411
+ await testdriver.find('modal button').click();
412
+ ```
413
+ </Accordion>
414
+
415
+ <Accordion title="Infinite Scroll">
416
+ ```javascript
417
+ // Traditional - flaky
418
+ await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
419
+ await page.waitForTimeout(1000);
420
+ await page.waitForLoadState('networkidle');
421
+ await page.click('.load-more');
422
+
423
+ // TestDriver - stable
424
+ await testdriver.scroll('down', 1000);
425
+ await testdriver.find('load more button').click();
426
+ ```
427
+ </Accordion>
428
+
429
+ <Accordion title="Form Submissions">
430
+ ```javascript
431
+ // Traditional - flaky
432
+ await page.fill('input[name="email"]', 'user@example.com');
433
+ await page.click('button[type="submit"]');
434
+ await page.waitForNavigation();
435
+ await page.waitForTimeout(500);
436
+
437
+ // TestDriver - stable
438
+ await testdriver.find('email input').type('user@example.com');
439
+ await testdriver.find('submit button').click();
440
+ await testdriver.assert('success message is visible');
441
+ ```
442
+ </Accordion>
443
+ </AccordionGroup>
444
+
445
+ ## Best Practices
446
+
447
+ <Card title="Let TestDriver Handle Timing" icon="clock">
448
+ **Don't:**
449
+ ```javascript
450
+ await testdriver.find('button').click();
451
+ await new Promise(resolve => setTimeout(resolve, 1000)); // ❌
452
+ ```
453
+
454
+ **Do:**
455
+ ```javascript
456
+ await testdriver.find('button').click();
457
+ await testdriver.find('next element').click(); // ✅
458
+ ```
459
+
460
+ Trust TestDriver's automatic stability detection.
461
+ </Card>
462
+
463
+ <Card title="Use Natural Assertions" icon="check">
464
+ **Don't:**
465
+ ```javascript
466
+ await testdriver.find('button').click();
467
+ const element = await testdriver.find('result');
468
+ expect(element).toBeTruthy(); // ❌ Redundant
469
+ ```
470
+
471
+ **Do:**
472
+ ```javascript
473
+ await testdriver.find('button').click();
474
+ await testdriver.assert('result is visible'); // ✅ Natural
475
+ ```
476
+
477
+ TestDriver's assert automatically waits for stability.
478
+ </Card>
479
+
480
+ ## Learn More
481
+
482
+ <CardGroup cols={2}>
483
+ <Card
484
+ title="Redraw Implementation"
485
+ icon="code"
486
+ href="/agent/lib/redraw.js"
487
+ >
488
+ View the redraw detection source code
489
+ </Card>
490
+
491
+ <Card
492
+ title="Error Handling Guide"
493
+ icon="triangle-exclamation"
494
+ href="/v7/guides/error-handling"
495
+ >
496
+ Learn about error handling patterns
497
+ </Card>
498
+
499
+ <Card
500
+ title="Best Practices"
501
+ icon="star"
502
+ href="/v7/guides/best-practices"
503
+ >
504
+ Testing best practices with TestDriver
505
+ </Card>
506
+
507
+ <Card
508
+ title="Debugging Guide"
509
+ icon="bug"
510
+ href="/v7/guides/debugging"
511
+ >
512
+ Debug failing tests effectively
513
+ </Card>
514
+ </CardGroup>
@@ -236,7 +236,7 @@ await testdriver.find('button', { threshold: -1 }); // disable cache
236
236
  ## Dashcam Configuration
237
237
 
238
238
  ```javascript
239
- import Dashcam from 'testdriverai/src/core/Dashcam.js';
239
+ import Dashcam from 'testdriverai/lib/core/Dashcam.js';
240
240
 
241
241
  const dashcam = new Dashcam(client, {
242
242
  apiKey: process.env.TD_API_KEY,