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,535 @@
1
+ ---
2
+ title: "Writing Tests"
3
+ description: "Learn how to write effective TestDriver tests with natural language"
4
+ icon: "pencil"
5
+ ---
6
+
7
+ TestDriver makes writing tests intuitive by using natural language to describe interactions. This guide covers everything you need to know to write effective, maintainable tests.
8
+
9
+ ## Basic Test Structure
10
+
11
+ Every TestDriver test follows this simple pattern:
12
+
13
+ ```javascript
14
+ import { test } from 'vitest';
15
+ import { chrome } from 'testdriverai/presets';
16
+
17
+ test('descriptive test name', async (context) => {
18
+ // 1. Setup: Launch and navigate
19
+ const { testdriver } = await chrome(context, {
20
+ url: 'https://myapp.com'
21
+ });
22
+
23
+ // 2. Act: Interact with your application
24
+ await testdriver.find('email input').type('user@example.com');
25
+ await testdriver.find('submit button').click();
26
+
27
+ // 3. Assert: Verify expected state
28
+ await testdriver.assert('Welcome message is visible');
29
+ });
30
+ ```
31
+
32
+ <Tip>
33
+ The preset handles all setup and cleanup automatically - no need for manual browser management!
34
+ </Tip>
35
+
36
+ ## Finding Elements
37
+
38
+ Use natural language to describe elements:
39
+
40
+ <Tabs>
41
+ <Tab title="Good Descriptions">
42
+ ```javascript
43
+ // ✅ Specific and contextual
44
+ await testdriver.find('submit button in the login form');
45
+ await testdriver.find('email input field');
46
+ await testdriver.find('delete button in the top right corner');
47
+ await testdriver.find('first product card in the grid');
48
+ await testdriver.find('dropdown menu labeled "Country"');
49
+ ```
50
+
51
+ These descriptions are:
52
+ - Specific enough to locate the element
53
+ - Include context (location, parent container)
54
+ - Use natural human language
55
+ </Tab>
56
+
57
+ <Tab title="Avoid Vague">
58
+ ```javascript
59
+ // ❌ Too vague
60
+ await testdriver.find('button');
61
+ await testdriver.find('input');
62
+ await testdriver.find('link');
63
+ await testdriver.find('text');
64
+
65
+ // ✅ Better
66
+ await testdriver.find('submit button');
67
+ await testdriver.find('email input');
68
+ await testdriver.find('contact us link');
69
+ await testdriver.find('welcome message text');
70
+ ```
71
+
72
+ Add specificity to help AI locate the exact element.
73
+ </Tab>
74
+ </Tabs>
75
+
76
+ ## Chaining Actions
77
+
78
+ TestDriver supports method chaining for cleaner code:
79
+
80
+ ```javascript
81
+ // Chain find() with actions
82
+ await testdriver.find('Login button').click();
83
+ await testdriver.find('email input').type('user@example.com');
84
+ await testdriver.find('dropdown menu').hover();
85
+ await testdriver.find('menu item').doubleClick();
86
+ await testdriver.find('context option').rightClick();
87
+
88
+ // Or save element reference
89
+ const button = await testdriver.find('submit button');
90
+ await button.click();
91
+ ```
92
+
93
+ ## Common Interactions
94
+
95
+ <AccordionGroup>
96
+ <Accordion title="Clicking Elements">
97
+ ```javascript
98
+ // Regular click
99
+ await testdriver.find('button').click();
100
+
101
+ // Double-click
102
+ await testdriver.find('file item').doubleClick();
103
+
104
+ // Right-click (context menu)
105
+ await testdriver.find('text area').rightClick();
106
+
107
+ // Click at specific coordinates
108
+ await testdriver.click(500, 300);
109
+ ```
110
+ </Accordion>
111
+
112
+ <Accordion title="Typing Text">
113
+ ```javascript
114
+ // Basic typing
115
+ await testdriver.find('search input').type('query text');
116
+
117
+ // Type sensitive data (won't be logged)
118
+ await testdriver.find('password input').type('secret', { secret: true });
119
+
120
+ // Type with delay between keystrokes
121
+ await testdriver.find('input').type('slow typing', { delay: 500 });
122
+
123
+ // Type numbers
124
+ await testdriver.find('age input').type(25);
125
+ ```
126
+
127
+ <Warning>
128
+ Always use `{ secret: true }` for passwords and sensitive data to prevent logging!
129
+ </Warning>
130
+ </Accordion>
131
+
132
+ <Accordion title="Keyboard Shortcuts">
133
+ ```javascript
134
+ // Single keys
135
+ await testdriver.pressKeys(['enter']);
136
+ await testdriver.pressKeys(['tab']);
137
+ await testdriver.pressKeys(['escape']);
138
+
139
+ // Combinations
140
+ await testdriver.pressKeys(['ctrl', 'c']); // Copy
141
+ await testdriver.pressKeys(['ctrl', 'v']); // Paste
142
+ await testdriver.pressKeys(['ctrl', 's']); // Save
143
+
144
+ // macOS modifiers
145
+ await testdriver.pressKeys(['cmd', 'c']); // macOS copy
146
+ await testdriver.pressKeys(['cmd', 'shift', 'p']); // Command palette
147
+ ```
148
+ </Accordion>
149
+
150
+ <Accordion title="Hovering">
151
+ ```javascript
152
+ // Hover over element to reveal dropdown
153
+ await testdriver.find('Products menu').hover();
154
+ await testdriver.find('Laptops submenu').click();
155
+
156
+ // Hover at coordinates
157
+ await testdriver.hover(400, 200);
158
+ ```
159
+ </Accordion>
160
+
161
+ <Accordion title="Scrolling">
162
+ ```javascript
163
+ // Scroll down
164
+ await testdriver.scroll('down', 500);
165
+
166
+ // Scroll up
167
+ await testdriver.scroll('up', 300);
168
+
169
+ // Scroll until text appears
170
+ await testdriver.scrollUntilText('Footer content');
171
+
172
+ // Scroll until element is visible
173
+ await testdriver.scroll('down', 1000);
174
+ await testdriver.find('load more button').click();
175
+ ```
176
+ </Accordion>
177
+ </AccordionGroup>
178
+
179
+ ## Making Assertions
180
+
181
+ Use AI-powered assertions to verify application state:
182
+
183
+ ```javascript
184
+ // Verify visibility
185
+ await testdriver.assert('login page is displayed');
186
+ await testdriver.assert('submit button is visible');
187
+ await testdriver.assert('loading spinner is not visible');
188
+
189
+ // Verify content
190
+ await testdriver.assert('page title is "Welcome"');
191
+ await testdriver.assert('success message says "Account created"');
192
+ await testdriver.assert('error message contains "Invalid email"');
193
+
194
+ // Verify state
195
+ await testdriver.assert('checkbox is checked');
196
+ await testdriver.assert('dropdown shows "United States"');
197
+ await testdriver.assert('button is disabled');
198
+
199
+ // Verify visual appearance
200
+ await testdriver.assert('submit button is blue');
201
+ await testdriver.assert('form has red border');
202
+ ```
203
+
204
+ <Tip>
205
+ Assertions automatically wait for the condition to be true, making tests more stable.
206
+ </Tip>
207
+
208
+ ## Working with Multiple Elements
209
+
210
+ Find and interact with multiple elements:
211
+
212
+ ```javascript
213
+ // Find all matching elements
214
+ const products = await testdriver.findAll('product card');
215
+ console.log(`Found ${products.length} products`);
216
+
217
+ // Interact with each
218
+ for (const product of products) {
219
+ const title = await product.find('title text');
220
+ console.log('Product:', title.text);
221
+
222
+ await product.find('add to cart button').click();
223
+ }
224
+
225
+ // Or find specific element
226
+ const firstProduct = products[0];
227
+ await firstProduct.click();
228
+ ```
229
+
230
+ ## Handling Forms
231
+
232
+ Complete form example:
233
+
234
+ ```javascript
235
+ test('fill out contact form', async (context) => {
236
+ const { testdriver } = await chrome(context, {
237
+ url: 'https://example.com/contact'
238
+ });
239
+
240
+ // Fill text inputs
241
+ await testdriver.find('name input').type('John Doe');
242
+ await testdriver.find('email input').type('john@example.com');
243
+ await testdriver.find('phone input').type('555-1234');
244
+
245
+ // Select from dropdown
246
+ await testdriver.find('country dropdown').click();
247
+ await testdriver.find('United States option').click();
248
+
249
+ // Check checkbox
250
+ await testdriver.find('newsletter checkbox').click();
251
+
252
+ // Select radio button
253
+ await testdriver.find('urgent priority radio button').click();
254
+
255
+ // Fill textarea
256
+ await testdriver.find('message textarea').type('This is my message.');
257
+
258
+ // Submit
259
+ await testdriver.find('send message button').click();
260
+
261
+ // Verify success
262
+ await testdriver.assert('thank you message is displayed');
263
+ });
264
+ ```
265
+
266
+ ## Navigation Patterns
267
+
268
+ <Tabs>
269
+ <Tab title="Multi-Page Flow">
270
+ ```javascript
271
+ test('checkout flow', async (context) => {
272
+ const { testdriver } = await chrome(context, {
273
+ url: 'https://shop.example.com'
274
+ });
275
+
276
+ // Page 1: Browse products
277
+ await testdriver.find('first product').click();
278
+ await testdriver.find('add to cart button').click();
279
+
280
+ // Page 2: Cart
281
+ await testdriver.find('cart icon').click();
282
+ await testdriver.find('checkout button').click();
283
+
284
+ // Page 3: Shipping info
285
+ await testdriver.find('address input').type('123 Main St');
286
+ await testdriver.find('continue button').click();
287
+
288
+ // Page 4: Payment
289
+ await testdriver.find('card number').type('4242424242424242');
290
+ await testdriver.find('place order').click();
291
+
292
+ // Page 5: Confirmation
293
+ await testdriver.assert('order confirmation is shown');
294
+ });
295
+ ```
296
+ </Tab>
297
+
298
+ <Tab title="Back Navigation">
299
+ ```javascript
300
+ // Navigate forward
301
+ await testdriver.find('next page link').click();
302
+ await testdriver.assert('page 2 is displayed');
303
+
304
+ // Go back
305
+ await testdriver.pressKeys(['alt', 'left']); // Browser back
306
+ await testdriver.assert('page 1 is displayed');
307
+ ```
308
+ </Tab>
309
+
310
+ <Tab title="Opening Links in New Tab">
311
+ ```javascript
312
+ // Open link in new tab (cmd+click / ctrl+click)
313
+ const link = await testdriver.find('external link');
314
+ await testdriver.pressKeys(['cmd']); // Hold cmd
315
+ await link.click();
316
+ // New tab opens
317
+
318
+ // Switch between windows
319
+ await testdriver.focusWindow(1); // Switch to second window
320
+ ```
321
+ </Tab>
322
+ </Tabs>
323
+
324
+ ## Best Practices
325
+
326
+ <CardGroup cols={2}>
327
+ <Card title="Write Descriptive Selectors" icon="text">
328
+ ```javascript
329
+ // ✅ Good
330
+ await testdriver.find('blue submit button in the bottom right');
331
+
332
+ // ❌ Too vague
333
+ await testdriver.find('button');
334
+ ```
335
+ </Card>
336
+
337
+ <Card title="Use secret: true for Passwords" icon="lock">
338
+ ```javascript
339
+ // ✅ Secure
340
+ await testdriver.type('password', { secret: true });
341
+
342
+ // ❌ Logged in dashcam
343
+ await testdriver.type('password');
344
+ ```
345
+ </Card>
346
+
347
+ <Card title="Test User Flows, Not Implementation" icon="route">
348
+ ```javascript
349
+ // ✅ User-focused
350
+ test('user can purchase item', async (context) => {
351
+ // Test the complete flow
352
+ });
353
+
354
+ // ❌ Implementation-focused
355
+ test('click button #12345', async (context) => {
356
+ // Too specific to implementation
357
+ });
358
+ ```
359
+ </Card>
360
+
361
+ <Card title="Use Meaningful Test Names" icon="tag">
362
+ ```javascript
363
+ // ✅ Clear intent
364
+ test('user can reset password via email');
365
+
366
+ // ❌ Vague
367
+ test('test login');
368
+ ```
369
+ </Card>
370
+ </CardGroup>
371
+
372
+ ## Advanced Patterns
373
+
374
+ <AccordionGroup>
375
+ <Accordion title="Conditional Logic">
376
+ ```javascript
377
+ // Check if element exists
378
+ try {
379
+ await testdriver.find('cookie banner', { timeout: 5000 });
380
+ // Banner found, dismiss it
381
+ await testdriver.find('accept cookies button').click();
382
+ } catch (error) {
383
+ // Banner not found, continue
384
+ console.log('No cookie banner');
385
+ }
386
+
387
+ // Conditional actions
388
+ const loginButton = await testdriver.find('login button');
389
+ if (loginButton) {
390
+ await loginButton.click();
391
+ }
392
+ ```
393
+ </Accordion>
394
+
395
+ <Accordion title="Data-Driven Tests">
396
+ ```javascript
397
+ const testCases = [
398
+ { email: 'valid@example.com', password: 'pass123', shouldPass: true },
399
+ { email: 'invalid', password: 'pass123', shouldPass: false },
400
+ { email: 'user@example.com', password: 'wrong', shouldPass: false },
401
+ ];
402
+
403
+ testCases.forEach(({ email, password, shouldPass }) => {
404
+ test(`login with ${email}`, async (context) => {
405
+ const { testdriver } = await chrome(context, { url });
406
+
407
+ await testdriver.find('email').type(email);
408
+ await testdriver.find('password').type(password, { secret: true });
409
+ await testdriver.find('submit').click();
410
+
411
+ if (shouldPass) {
412
+ await testdriver.assert('dashboard is visible');
413
+ } else {
414
+ await testdriver.assert('error message is shown');
415
+ }
416
+ });
417
+ });
418
+ ```
419
+ </Accordion>
420
+
421
+ <Accordion title="Reusable Helpers">
422
+ ```javascript
423
+ // helpers.js
424
+ export async function login(testdriver, email, password) {
425
+ await testdriver.find('email input').type(email);
426
+ await testdriver.find('password input').type(password, { secret: true });
427
+ await testdriver.find('login button').click();
428
+ await testdriver.assert('dashboard is visible');
429
+ }
430
+
431
+ // test.test.js
432
+ import { login } from './helpers';
433
+
434
+ test('user can view profile', async (context) => {
435
+ const { testdriver } = await chrome(context, { url });
436
+
437
+ await login(testdriver, 'user@example.com', 'password');
438
+
439
+ await testdriver.find('profile link').click();
440
+ await testdriver.assert('profile page is displayed');
441
+ });
442
+ ```
443
+ </Accordion>
444
+ </AccordionGroup>
445
+
446
+ ## Common Patterns
447
+
448
+ <Tabs>
449
+ <Tab title="Login Flow">
450
+ ```javascript
451
+ test('user login', async (context) => {
452
+ const { testdriver } = await chrome(context, {
453
+ url: 'https://myapp.com/login'
454
+ });
455
+
456
+ await testdriver.find('email input').type('user@example.com');
457
+ await testdriver.find('password input').type('secret', { secret: true });
458
+ await testdriver.find('Login button').click();
459
+
460
+ await testdriver.assert('Dashboard is visible');
461
+ await testdriver.assert('Welcome message shows user name');
462
+ });
463
+ ```
464
+ </Tab>
465
+
466
+ <Tab title="Search">
467
+ ```javascript
468
+ test('search functionality', async (context) => {
469
+ const { testdriver } = await chrome(context, { url });
470
+
471
+ await testdriver.find('search input').type('laptop');
472
+ await testdriver.pressKeys(['enter']);
473
+
474
+ await testdriver.assert('search results are displayed');
475
+ await testdriver.assert('results contain "laptop"');
476
+
477
+ const results = await testdriver.findAll('result item');
478
+ console.log(`Found ${results.length} results`);
479
+ });
480
+ ```
481
+ </Tab>
482
+
483
+ <Tab title="Shopping Cart">
484
+ ```javascript
485
+ test('add to cart', async (context) => {
486
+ const { testdriver } = await chrome(context, { url });
487
+
488
+ await testdriver.find('first product').click();
489
+ await testdriver.find('add to cart button').click();
490
+
491
+ await testdriver.assert('cart badge shows 1');
492
+
493
+ await testdriver.find('cart icon').click();
494
+ await testdriver.assert('product is in cart');
495
+ await testdriver.assert('subtotal is correct');
496
+ });
497
+ ```
498
+ </Tab>
499
+ </Tabs>
500
+
501
+ ## Next Steps
502
+
503
+ <CardGroup cols={2}>
504
+ <Card
505
+ title="Generate Tests with AI"
506
+ icon="wand-magic-sparkles"
507
+ href="/v7/getting-started/generating-tests"
508
+ >
509
+ Use Claude to write tests automatically
510
+ </Card>
511
+
512
+ <Card
513
+ title="Running & Debugging"
514
+ icon="bug"
515
+ href="/v7/getting-started/running-and-debugging"
516
+ >
517
+ Run tests and debug failures
518
+ </Card>
519
+
520
+ <Card
521
+ title="API Reference"
522
+ icon="book"
523
+ href="/v7/api/client"
524
+ >
525
+ Complete API documentation
526
+ </Card>
527
+
528
+ <Card
529
+ title="Examples"
530
+ icon="code"
531
+ href="/v7/presets/chrome"
532
+ >
533
+ View more examples
534
+ </Card>
535
+ </CardGroup>