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,177 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * TestDriver SDK - AWESOME Logs Demo 🎨
5
+ *
6
+ * This example showcases the beautiful, emoji-rich logging with great DX
7
+ * that makes your test output a joy to read!
8
+ *
9
+ * Run: TD_API_KEY=your_key node examples/sdk-awesome-logs-demo.js
10
+ */
11
+
12
+ const TestDriver = require("../sdk.js");
13
+ const { formatter } = require("../sdk-log-formatter.js");
14
+
15
+ (async () => {
16
+ try {
17
+ console.log(
18
+ formatter.formatHeader("TestDriver SDK - AWESOME Logs Demo", "🚀"),
19
+ );
20
+
21
+ // Create client with logging enabled
22
+ const client = new TestDriver(process.env.TD_API_KEY, {
23
+ os: "windows",
24
+ logging: true,
25
+ });
26
+
27
+ // Demo 1: Connection
28
+ console.log(
29
+ formatter.formatConnection("connect", {
30
+ sandboxId: "demo-sandbox-123",
31
+ os: "Windows",
32
+ }),
33
+ );
34
+
35
+ await client.connect({ headless: true });
36
+
37
+ // Demo 2: Navigation
38
+ console.log(
39
+ "\n" + formatter.formatAction("navigate", "https://example.com"),
40
+ );
41
+ await client.focusApplication("Google Chrome");
42
+ await client.type("https://example.com");
43
+ await client.pressKeys(["enter"]);
44
+
45
+ // Demo 3: Wait with loading indicator
46
+ console.log("\n" + formatter.formatWaiting("for page to load", 2000));
47
+ await new Promise((resolve) => setTimeout(resolve, 2000));
48
+
49
+ // Demo 4: Finding elements (this will use the real formatElementFound from sdk.js)
50
+ console.log("\n" + formatter.formatHeader("Finding Elements", "🔍"));
51
+
52
+ const heading = await client.find("heading that says Example Domain");
53
+ // The actual find() call will emit the formatted log automatically
54
+
55
+ if (heading.found()) {
56
+ await heading.click();
57
+ // The click will also emit a formatted log automatically
58
+ }
59
+
60
+ // Demo 5: Multiple actions
61
+ console.log("\n" + formatter.formatHeader("User Actions", "👆"));
62
+
63
+ const link = await client.find("More information link");
64
+ if (link.found()) {
65
+ await link.hover();
66
+ await link.click();
67
+ }
68
+
69
+ // Demo 6: Typing
70
+ console.log(
71
+ "\n" +
72
+ formatter.formatAction("type", "search query", {
73
+ text: "TestDriver AI",
74
+ }),
75
+ );
76
+
77
+ // Demo 7: Scroll
78
+ console.log("\n" + formatter.formatAction("scroll", "down the page"));
79
+ await client.scroll("down", 300);
80
+
81
+ // Demo 8: Assertions
82
+ console.log("\n" + formatter.formatHeader("Assertions", "✅"));
83
+ console.log(
84
+ formatter.formatAssertion("Page title is correct", true, {
85
+ duration: "45ms",
86
+ }),
87
+ );
88
+ console.log(
89
+ formatter.formatAssertion("Footer is visible", true, {
90
+ duration: "23ms",
91
+ }),
92
+ );
93
+ console.log(
94
+ formatter.formatAssertion("Login button exists", false, {
95
+ duration: "1234ms",
96
+ }),
97
+ );
98
+
99
+ // Demo 9: Cache status
100
+ console.log("\n" + formatter.formatHeader("Cache Performance", "⚡"));
101
+ console.log(
102
+ formatter.formatCacheStatus(true, {
103
+ similarity: 0.98,
104
+ strategy: "image",
105
+ }),
106
+ );
107
+ console.log(
108
+ formatter.formatCacheStatus(false, {
109
+ strategy: "text",
110
+ }),
111
+ );
112
+
113
+ // Demo 10: Screenshot
114
+ console.log(
115
+ "\n" +
116
+ formatter.formatScreenshot({
117
+ path: "/tmp/testdriver-debug/screenshot-123.png",
118
+ size: "245 KB",
119
+ }),
120
+ );
121
+
122
+ // Demo 11: Progress
123
+ console.log("\n" + formatter.formatHeader("Multi-step Process", "📈"));
124
+ for (let i = 1; i <= 5; i++) {
125
+ console.log(formatter.formatProgress(i, 5, `Processing step ${i}`));
126
+ await new Promise((resolve) => setTimeout(resolve, 300));
127
+ }
128
+
129
+ // Demo 12: Divider
130
+ console.log("\n" + formatter.formatDivider());
131
+
132
+ // Demo 13: Test summary
133
+ console.log(
134
+ formatter.formatSummary({
135
+ passed: 12,
136
+ failed: 2,
137
+ skipped: 1,
138
+ total: 15,
139
+ duration: "45.23s",
140
+ }),
141
+ );
142
+
143
+ // Demo 14: Error handling
144
+ console.log(formatter.formatHeader("Error Examples", "🚨"));
145
+ console.log(
146
+ formatter.formatError(
147
+ "Element not found",
148
+ new Error("Timeout after 5000ms"),
149
+ ),
150
+ );
151
+ console.log(
152
+ formatter.formatError(
153
+ "Connection failed",
154
+ new Error("Network unreachable"),
155
+ ),
156
+ );
157
+
158
+ // Demo 15: Test lifecycle
159
+ console.log(formatter.formatTestStart("Login Flow Test"));
160
+ await new Promise((resolve) => setTimeout(resolve, 1000));
161
+ console.log(formatter.formatTestEnd("Login Flow Test", true, 2345));
162
+
163
+ console.log(formatter.formatTestStart("Checkout Process"));
164
+ await new Promise((resolve) => setTimeout(resolve, 800));
165
+ console.log(formatter.formatTestEnd("Checkout Process", false, 5678));
166
+
167
+ // Final summary
168
+ console.log("\n" + formatter.formatHeader("Demo Complete!", "🎉"));
169
+ console.log("\n✨ Your test logs now look AWESOME! ✨\n");
170
+
171
+ await client.disconnect();
172
+ console.log("\n" + formatter.formatConnection("disconnect"));
173
+ } catch (error) {
174
+ console.error(formatter.formatError("Demo failed", error));
175
+ process.exit(1);
176
+ }
177
+ })();
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * TestDriver SDK - Cache Thresholds Example
5
+ *
6
+ * This example demonstrates how to configure cache thresholds for different
7
+ * operations and view cache debugging information.
8
+ *
9
+ * Run with VERBOSE=true to see cache hit/miss information:
10
+ * TD_API_KEY=your_key VERBOSE=true node examples/sdk-cache-thresholds.js
11
+ */
12
+
13
+ const TestDriver = require("../sdk.js");
14
+
15
+ (async () => {
16
+ try {
17
+ // Create client with custom cache thresholds
18
+ const client = new TestDriver(process.env.TD_API_KEY, {
19
+ os: "windows",
20
+ logging: true,
21
+ cacheThreshold: {
22
+ find: 0.03, // 3% difference = 97% similarity required for cache hit
23
+ findAll: 0.05, // 5% difference = 95% similarity required for cache hit
24
+ },
25
+ });
26
+
27
+ console.log("\n=== TestDriver SDK - Cache Thresholds Demo ===\n");
28
+ console.log("Cache thresholds configured:");
29
+ console.log(" - find: 0.03 (97% similarity required)");
30
+ console.log(" - findAll: 0.05 (95% similarity required)\n");
31
+ console.log("You can also override thresholds per-command:");
32
+ console.log(' await client.find("element", 0.01) // 99% similarity\n');
33
+
34
+ // Connect to sandbox
35
+ console.log("Connecting to sandbox...");
36
+ await client.connect({ headless: true });
37
+
38
+ // Open a test page
39
+ console.log("Opening test page...");
40
+ await client.focusApplication("Google Chrome");
41
+ await client.type("https://example.com");
42
+ await client.pressKeys(["enter"]);
43
+
44
+ // Wait for page load
45
+ await new Promise((resolve) => setTimeout(resolve, 3000));
46
+
47
+ // Example 1: First find - should be a cache MISS
48
+ console.log("\n--- First find (cache MISS expected) ---");
49
+ const heading1 = await client.find("heading that says Example Domain");
50
+
51
+ if (heading1.found()) {
52
+ console.log(`✓ Element found at (${heading1.x}, ${heading1.y})`);
53
+ }
54
+
55
+ // Example 2: Second find - should be a cache HIT (same element, same screen)
56
+ console.log("\n--- Second find (cache HIT expected) ---");
57
+ // eslint-disable-next-line no-unused-vars
58
+ const _heading2 = await client.find("heading that says Example Domain");
59
+
60
+ // Example 3: Find with custom threshold override
61
+ console.log("\n--- Find with strict threshold (0.01 = 99% similarity) ---");
62
+ // eslint-disable-next-line no-unused-vars
63
+ const _heading3 = await client.find(
64
+ "heading that says Example Domain",
65
+ 0.01,
66
+ );
67
+
68
+ // Example 4: Find a different element - cache MISS
69
+ console.log("\n--- Finding different element (cache MISS expected) ---");
70
+ // eslint-disable-next-line no-unused-vars
71
+ const _paragraph = await client.find(
72
+ "paragraph with text about illustrative examples",
73
+ );
74
+
75
+ // Example 5: Find the same paragraph again - cache HIT
76
+ console.log("\n--- Finding same paragraph again (cache HIT expected) ---");
77
+ // eslint-disable-next-line no-unused-vars
78
+ const _paragraph2 = await client.find(
79
+ "paragraph with text about illustrative examples",
80
+ );
81
+
82
+ console.log("\n=== Demo Complete ===");
83
+ console.log(
84
+ "\nNote: Run with VERBOSE=true to see detailed cache information:",
85
+ );
86
+ console.log(" - Cache hit/miss status");
87
+ console.log(" - Cache strategy (image/text)");
88
+ console.log(" - Similarity scores");
89
+ console.log(" - Response times\n");
90
+
91
+ await client.disconnect();
92
+ } catch (error) {
93
+ console.error("Test failed:", error);
94
+ process.exit(1);
95
+ }
96
+ })();
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * TestDriver SDK - Element Properties Example
5
+ *
6
+ * This example demonstrates accessing all available properties from located elements,
7
+ * including coordinates, dimensions, confidence scores, screenshots, and more.
8
+ */
9
+
10
+ const TestDriverSDK = require("../sdk");
11
+
12
+ (async () => {
13
+ const client = new TestDriverSDK(process.env.TD_API_KEY);
14
+
15
+ try {
16
+ await client.connect();
17
+
18
+ // Example 1: Basic coordinate properties
19
+ console.log("=== Example 1: Basic Coordinates ===");
20
+ const button = await client.find("the login button");
21
+
22
+ if (button.found()) {
23
+ console.log("Button found!");
24
+ console.log(" X (top-left):", button.x);
25
+ console.log(" Y (top-left):", button.y);
26
+ console.log(" Center X:", button.centerX);
27
+ console.log(" Center Y:", button.centerY);
28
+ console.log(" Coordinates object:", button.getCoordinates());
29
+ }
30
+
31
+ // Example 2: Element dimensions
32
+ console.log("\n=== Example 2: Element Dimensions ===");
33
+ const input = await client.find("username input field");
34
+
35
+ if (input.found()) {
36
+ console.log("Input field found!");
37
+ console.log(" Width:", input.width);
38
+ console.log(" Height:", input.height);
39
+
40
+ if (input.boundingBox) {
41
+ console.log(" Bounding box:", input.boundingBox);
42
+ }
43
+ }
44
+
45
+ // Example 3: Confidence and text data
46
+ console.log("\n=== Example 3: Match Quality & Text ===");
47
+ const link = await client.find("sign up link");
48
+
49
+ if (link.found()) {
50
+ console.log("Link found!");
51
+ console.log(" Confidence score:", link.confidence);
52
+ console.log(" Text content:", link.text);
53
+ console.log(" Label:", link.label);
54
+ }
55
+
56
+ // Example 4: Screenshot data
57
+ console.log("\n=== Example 4: Element Screenshot ===");
58
+ const icon = await client.find("settings icon");
59
+
60
+ if (icon.found() && icon.screenshot) {
61
+ console.log("Icon found with screenshot!");
62
+ console.log(" Screenshot (base64) length:", icon.screenshot.length);
63
+
64
+ // You could save this to a file:
65
+ // const fs = require('fs');
66
+ // fs.writeFileSync('element.png', Buffer.from(icon.screenshot, 'base64'));
67
+ }
68
+
69
+ // Example 5: Full API response
70
+ console.log("\n=== Example 5: Full API Response ===");
71
+ const widget = await client.find("main content area");
72
+
73
+ if (widget.found()) {
74
+ const fullResponse = widget.getResponse();
75
+ console.log("Full API response:", JSON.stringify(fullResponse, null, 2));
76
+
77
+ // Log all available properties
78
+ if (fullResponse) {
79
+ console.log("\nAll available properties:");
80
+ Object.keys(fullResponse).forEach((key) => {
81
+ const value = fullResponse[key];
82
+ const preview =
83
+ typeof value === "string" && value.length > 50
84
+ ? value.substring(0, 50) + "..."
85
+ : value;
86
+ console.log(` ${key}:`, preview);
87
+ });
88
+ }
89
+ }
90
+
91
+ // Example 6: Property-based validation
92
+ console.log("\n=== Example 6: Property-based Validation ===");
93
+ const message = await client.find("error message");
94
+
95
+ if (message.found()) {
96
+ // Check position
97
+ if (message.centerY < 200) {
98
+ console.log("✓ Error message is at top of screen");
99
+ }
100
+
101
+ // Check confidence
102
+ if (message.confidence && message.confidence > 0.9) {
103
+ console.log("✓ High confidence match (", message.confidence, ")");
104
+ }
105
+
106
+ // Check text content
107
+ if (message.text) {
108
+ console.log("✓ Message text:", message.text);
109
+ }
110
+ }
111
+
112
+ // Example 7: Position-based logic
113
+ console.log("\n=== Example 7: Position-based Logic ===");
114
+ const menu = await client.find("dropdown menu");
115
+
116
+ if (menu.found()) {
117
+ // Calculate positions
118
+ const offsetX = menu.x + 10;
119
+ const offsetY = menu.y + 20;
120
+ console.log("Menu position:", { x: menu.x, y: menu.y });
121
+ console.log("Offset position:", { x: offsetX, y: offsetY });
122
+
123
+ // Check if element is in viewport
124
+ const viewportHeight = 768;
125
+ if (menu.y > 0 && menu.y < viewportHeight) {
126
+ console.log("✓ Element is visible in viewport");
127
+ }
128
+ }
129
+
130
+ // Example 8: Conditional actions based on properties
131
+ console.log("\n=== Example 8: Conditional Actions ===");
132
+ const notification = await client.find("notification popup");
133
+
134
+ if (notification.found()) {
135
+ // Only interact if confidence is high
136
+ if (notification.confidence && notification.confidence > 0.8) {
137
+ console.log("High confidence, clicking notification");
138
+ await notification.click();
139
+ } else {
140
+ console.log("Low confidence, skipping interaction");
141
+ console.log("Debug info:", {
142
+ coordinates: notification.getCoordinates(),
143
+ confidence: notification.confidence,
144
+ text: notification.text,
145
+ });
146
+ }
147
+ }
148
+
149
+ await client.disconnect();
150
+ } catch (error) {
151
+ console.error("Test failed:", error);
152
+ await client.disconnect();
153
+ process.exit(1);
154
+ }
155
+ })();
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * TestDriver SDK - Simple Example with AWESOME Logs 🎨
5
+ *
6
+ * A straightforward example showing the beautiful logging in action.
7
+ *
8
+ * Run: TD_API_KEY=your_key node examples/sdk-simple-example.js
9
+ */
10
+
11
+ const TestDriver = require("../sdk.js");
12
+
13
+ (async () => {
14
+ try {
15
+ // Create client with logging enabled (default)
16
+ const client = new TestDriver(process.env.TD_API_KEY, {
17
+ os: "windows",
18
+ logging: true, // This enables the awesome logs!
19
+ });
20
+
21
+ console.log("\n🚀 Starting TestDriver SDK Example...\n");
22
+
23
+ // Connect to sandbox - you'll see: 🔌 Connected
24
+ await client.connect({ headless: true });
25
+
26
+ // Navigate to a test page
27
+ await client.focusApplication("Google Chrome");
28
+ await client.type("https://example.com");
29
+ await client.pressKeys(["enter"]);
30
+
31
+ // Wait for page load
32
+ await new Promise((resolve) => setTimeout(resolve, 3000));
33
+
34
+ // Find an element - you'll see: 🔍 Found "heading..." · 📍 (x, y) · ⏱️ XXXms · ⚡ cached
35
+ const heading = await client.find("heading that says Example Domain");
36
+
37
+ if (heading.found()) {
38
+ // Click the element - you'll see: 👆 Click "heading..."
39
+ await heading.click();
40
+ }
41
+
42
+ // Find another element
43
+ const link = await client.find("More information link");
44
+
45
+ if (link.found()) {
46
+ // Hover over it - you'll see: 👉 Hover "More information link"
47
+ await link.hover();
48
+ }
49
+
50
+ // Scroll down - you'll see: 📜 Scroll
51
+ await client.scroll("down", 300);
52
+
53
+ // Take a screenshot - you'll see: 📸 Screenshot
54
+ const screenshot = await client.screenshot();
55
+ console.log(`\n📸 Screenshot captured (${screenshot.length} bytes)\n`);
56
+
57
+ // Disconnect - you'll see: 🔌 Disconnected
58
+ await client.disconnect();
59
+
60
+ console.log("\n✅ Example completed successfully!\n");
61
+ } catch (error) {
62
+ console.error(`\n❌ Error: ${error.message}\n`);
63
+ process.exit(1);
64
+ }
65
+ })();
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Example Vitest test file demonstrating TestDriver test recording
3
+ *
4
+ * This example shows how to:
5
+ * 1. Use TestDriver SDK in tests
6
+ * 2. Associate dashcam recordings with tests
7
+ * 3. Record custom test metadata
8
+ *
9
+ * Run with: npx vitest run examples/test-recording-example.test.js
10
+ */
11
+
12
+ import { afterAll, beforeAll, describe, test } from "vitest";
13
+ import TestDriverSDK from "../sdk.js";
14
+
15
+ // Initialize TestDriver client
16
+ let client;
17
+ let runId;
18
+
19
+ beforeAll(async () => {
20
+ // Connect to TestDriver
21
+ client = new TestDriverSDK({
22
+ apiKey: process.env.TD_API_KEY || "your-api-key",
23
+ });
24
+
25
+ await client.connect();
26
+
27
+ // Create a test run (usually done by the Vitest reporter, but shown here for demo)
28
+ runId = `example-${Date.now()}`;
29
+
30
+ const testRun = await client.createTestRun({
31
+ runId,
32
+ suiteName: "Example Test Suite",
33
+ platform: "windows",
34
+ git: {
35
+ repo: "testdriverai/cli",
36
+ branch: "main",
37
+ commit: "abc123",
38
+ },
39
+ });
40
+
41
+ console.log("Test run created:", testRun.runId);
42
+ });
43
+
44
+ afterAll(async () => {
45
+ // Complete the test run
46
+ await client.completeTestRun({
47
+ runId,
48
+ status: "passed",
49
+ totalTests: 3,
50
+ passedTests: 3,
51
+ failedTests: 0,
52
+ });
53
+
54
+ await client.disconnect();
55
+ });
56
+
57
+ describe("Login Tests", () => {
58
+ test("should display login page", async () => {
59
+ const testStart = Date.now();
60
+
61
+ try {
62
+ // Your test logic here
63
+ await client.click("Login");
64
+
65
+ // Record the test result
66
+ await client.recordTestCase({
67
+ runId,
68
+ testName: "should display login page",
69
+ testFile: "examples/test-recording-example.test.js",
70
+ suiteName: "Login Tests",
71
+ status: "passed",
72
+ startTime: testStart,
73
+ endTime: Date.now(),
74
+ duration: Date.now() - testStart,
75
+ });
76
+ } catch (error) {
77
+ // Record failure
78
+ await client.recordTestCase({
79
+ runId,
80
+ testName: "should display login page",
81
+ testFile: "examples/test-recording-example.test.js",
82
+ status: "failed",
83
+ errorMessage: error.message,
84
+ errorStack: error.stack,
85
+ });
86
+ throw error;
87
+ }
88
+ });
89
+
90
+ test("should login with valid credentials", async () => {
91
+ const testStart = Date.now();
92
+
93
+ try {
94
+ // Test logic
95
+ await client.type("username", "testuser");
96
+ await client.type("password", "password123");
97
+ await client.click("Submit");
98
+
99
+ // Wait for dashboard
100
+ await client.waitForText("Dashboard");
101
+
102
+ // Record success
103
+ await client.recordTestCase({
104
+ runId,
105
+ testName: "should login with valid credentials",
106
+ testFile: "examples/test-recording-example.test.js",
107
+ suiteName: "Login Tests",
108
+ status: "passed",
109
+ startTime: testStart,
110
+ endTime: Date.now(),
111
+ duration: Date.now() - testStart,
112
+ // Associate with dashcam replay (if you have the URL)
113
+ replayUrl: process.env.DASHCAM_REPLAY_URL,
114
+ });
115
+ } catch (error) {
116
+ await client.recordTestCase({
117
+ runId,
118
+ testName: "should login with valid credentials",
119
+ testFile: "examples/test-recording-example.test.js",
120
+ status: "failed",
121
+ errorMessage: error.message,
122
+ errorStack: error.stack,
123
+ });
124
+ throw error;
125
+ }
126
+ });
127
+
128
+ test("should show error with invalid credentials", async () => {
129
+ const testStart = Date.now();
130
+
131
+ try {
132
+ await client.type("username", "wrong");
133
+ await client.type("password", "wrong");
134
+ await client.click("Submit");
135
+
136
+ await client.waitForText("Invalid credentials");
137
+
138
+ await client.recordTestCase({
139
+ runId,
140
+ testName: "should show error with invalid credentials",
141
+ testFile: "examples/test-recording-example.test.js",
142
+ suiteName: "Login Tests",
143
+ status: "passed",
144
+ startTime: testStart,
145
+ endTime: Date.now(),
146
+ duration: Date.now() - testStart,
147
+ steps: [
148
+ { action: "type", target: "username", value: "wrong" },
149
+ { action: "type", target: "password", value: "wrong" },
150
+ { action: "click", target: "Submit" },
151
+ { action: "waitForText", target: "Invalid credentials" },
152
+ ],
153
+ });
154
+ } catch (error) {
155
+ await client.recordTestCase({
156
+ runId,
157
+ testName: "should show error with invalid credentials",
158
+ testFile: "examples/test-recording-example.test.js",
159
+ status: "failed",
160
+ errorMessage: error.message,
161
+ errorStack: error.stack,
162
+ });
163
+ throw error;
164
+ }
165
+ });
166
+ });