@testdriverai/agent 7.11.229-canary → 7.11.232-test

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 (100) hide show
  1. package/docs/_data/examples-manifest.json +16 -16
  2. package/docs/_scripts/generate-examples.js +38 -45
  3. package/docs/agent.mdx +174 -93
  4. package/docs/assert.mdx +73 -269
  5. package/docs/aws-setup.mdx +196 -314
  6. package/docs/bring-your-own-machine.mdx +139 -206
  7. package/docs/cache.mdx +144 -151
  8. package/docs/caching.mdx +99 -89
  9. package/docs/captcha.mdx +126 -111
  10. package/docs/ci-cd.mdx +154 -543
  11. package/docs/click.mdx +74 -229
  12. package/docs/client.mdx +177 -231
  13. package/docs/copilot/auto-healing.mdx +86 -370
  14. package/docs/copilot/running-tests.mdx +121 -930
  15. package/docs/customizing-devices.mdx +74 -251
  16. package/docs/dashcam.mdx +72 -405
  17. package/docs/debugging-with-screenshots.mdx +105 -371
  18. package/docs/docs.json +79 -22
  19. package/docs/double-click.mdx +48 -68
  20. package/docs/errors.mdx +102 -176
  21. package/docs/events.mdx +170 -327
  22. package/docs/examples/{hover-text-with-description.mdx → add-to-cart.mdx} +30 -35
  23. package/docs/examples/assert.mdx +28 -41
  24. package/docs/examples/click-button.mdx +71 -0
  25. package/docs/examples/{hover-image.mdx → click-icon.mdx} +32 -28
  26. package/docs/examples/element-not-found.mdx +27 -26
  27. package/docs/examples/findall-coffee-icons.mdx +28 -32
  28. package/docs/examples/installer.mdx +61 -25
  29. package/docs/examples/launch-vscode-linux.mdx +28 -51
  30. package/docs/examples/navigate-and-scroll.mdx +82 -0
  31. package/docs/examples/parse.mdx +24 -28
  32. package/docs/examples/press-keys.mdx +28 -25
  33. package/docs/examples/scroll.mdx +25 -27
  34. package/docs/examples/type.mdx +26 -21
  35. package/docs/exec.mdx +92 -256
  36. package/docs/extract.mdx +69 -170
  37. package/docs/find.mdx +140 -736
  38. package/docs/focus-application.mdx +69 -246
  39. package/docs/generating-tests.mdx +103 -137
  40. package/docs/guide/best-practices-polling.mdx +65 -141
  41. package/docs/hosted.mdx +80 -144
  42. package/docs/hover.mdx +62 -235
  43. package/docs/locating-elements.mdx +74 -369
  44. package/docs/making-assertions.mdx +116 -74
  45. package/docs/mcp-setup.mdx +80 -63
  46. package/docs/mouse-down.mdx +48 -125
  47. package/docs/mouse-up.mdx +47 -129
  48. package/docs/options.mdx +75 -48
  49. package/docs/parse.mdx +95 -184
  50. package/docs/performing-actions.mdx +104 -94
  51. package/docs/press-keys.mdx +59 -299
  52. package/docs/provision.mdx +137 -182
  53. package/docs/quickstart-claude.mdx +85 -0
  54. package/docs/quickstart-github.mdx +62 -32
  55. package/docs/quickstart-manual.mdx +60 -33
  56. package/docs/quickstart-vscode.mdx +97 -0
  57. package/docs/quickstart.mdx +26 -9
  58. package/docs/redraw.mdx +101 -165
  59. package/docs/reusable-code.mdx +97 -200
  60. package/docs/right-click.mdx +47 -89
  61. package/docs/screenshot.mdx +47 -201
  62. package/docs/screenshots.mdx +87 -137
  63. package/docs/scroll.mdx +71 -154
  64. package/docs/secrets.mdx +96 -91
  65. package/docs/self-hosted.mdx +83 -142
  66. package/docs/snippets/enterprise.mdx +15 -0
  67. package/docs/styles.css +68 -0
  68. package/docs/test-results-json.mdx +167 -204
  69. package/docs/type.mdx +56 -304
  70. package/docs/variables.mdx +121 -81
  71. package/docs/wait.mdx +33 -31
  72. package/docs/what-is-testdriver.mdx +80 -32
  73. package/examples/{hover-text-with-description.test.mjs → add-to-cart.test.mjs} +4 -5
  74. package/examples/assert.test.mjs +3 -20
  75. package/examples/{hover-text.test.mjs → click-button.test.mjs} +3 -4
  76. package/examples/{hover-image.test.mjs → click-icon.test.mjs} +5 -6
  77. package/examples/element-not-found.test.mjs +3 -5
  78. package/examples/findall-coffee-icons.test.mjs +3 -3
  79. package/examples/installer.test.mjs +1 -1
  80. package/examples/launch-vscode-linux.test.mjs +6 -33
  81. package/examples/{scroll-keyboard.test.mjs → navigate-and-scroll.test.mjs} +4 -5
  82. package/examples/parse.test.mjs +1 -2
  83. package/examples/press-keys.test.mjs +4 -4
  84. package/examples/scroll.test.mjs +3 -6
  85. package/examples/type.test.mjs +5 -2
  86. package/lib/provision.js +6 -2
  87. package/package.json +1 -1
  88. package/sdk.d.ts +4 -2
  89. package/sdk.js +1 -1
  90. package/docs/claude-mcp-plugin.mdx +0 -244
  91. package/docs/elements.mdx +0 -606
  92. package/docs/examples/ai.mdx +0 -78
  93. package/docs/examples/captcha-api.mdx +0 -92
  94. package/docs/examples/chrome-extension.mdx +0 -156
  95. package/docs/examples/drag-and-drop.mdx +0 -100
  96. package/docs/examples/formatted-logging.mdx +0 -74
  97. package/docs/examples/hover-text.mdx +0 -70
  98. package/docs/examples/match-image.mdx +0 -97
  99. package/docs/examples/scroll-keyboard.mdx +0 -80
  100. package/docs/examples/scroll-until-text.mdx +0 -109
@@ -1,14 +1,14 @@
1
1
  ---
2
- title: "Assert Test Example"
2
+ title: "Assert that a page loaded"
3
3
  sidebarTitle: "Assert"
4
- description: "Example test that uses assert to verify a page loads."
4
+ description: "Open a login page in Chrome and use assert() to check that it loaded."
5
5
  icon: "check-circle"
6
6
  mode: "wide"
7
7
  ---
8
8
 
9
- ## Demo Test Run
9
+ This test opens a login page in Chrome, saves a screenshot, and asserts that the page loaded.
10
10
 
11
- Watch this test execute in a real sandbox environment:
11
+ ## Watch it run
12
12
 
13
13
  {/* assert.test.mjs output */}
14
14
  <iframe
@@ -19,28 +19,21 @@ Watch this test execute in a real sandbox environment:
19
19
  allow="fullscreen"
20
20
  />
21
21
 
22
- ## Source Code
23
-
24
- ```javascript title="assert.test.mjs" {22-24}
25
- /**
26
- * TestDriver SDK - Assert Test (Vitest)
27
- * Converted from: testdriver/acceptance/assert.yaml
28
- */
22
+ ## The test
29
23
 
24
+ ```javascript title="assert.test.mjs"
30
25
  import { describe, expect, it } from "vitest";
31
26
  import { TestDriver } from "testdriverai/vitest/hooks";
32
27
 
33
28
  describe("Assert Test", () => {
34
29
  it("should assert the testdriver login page shows", async (context) => {
35
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP,
36
- });
37
-
38
- // provision.chrome() automatically calls ready() and starts dashcam
30
+ const testdriver = TestDriver(context);
31
+
39
32
  await testdriver.provision.chrome({
40
33
  url: 'http://testdriver-sandbox.vercel.app/login',
41
34
  });
42
35
 
43
- // Take a screenshot
36
+ // Save a screenshot to .testdriver/screenshots for debugging
44
37
  await testdriver.screenshot();
45
38
 
46
39
  // Assert the TestDriver.ai Sandbox login page is displayed
@@ -50,38 +43,32 @@ describe("Assert Test", () => {
50
43
 
51
44
  expect(result).toBeTruthy();
52
45
  });
53
- // it("should assert the testdriver login page shows 2", async (context) => {
54
- // const testdriver = TestDriver(context);
55
-
56
- // // provision.chrome() automatically calls ready() and starts dashcam
57
- // await testdriver.provision.chrome({
58
- // url: 'http://testdriver-sandbox.vercel.app/login',
59
- // });
60
-
61
- // // Assert the TestDriver.ai Sandbox login page is displayed
62
- // const result = await testdriver.assert(
63
- // "the TestDriver.ai Sandbox login page is displayed",
64
- // );
65
-
66
- // expect(result).toBeTruthy();
67
- // });
68
46
  });
69
47
  ```
70
48
 
71
- ## Running This Example
49
+ ## How it works
50
+
51
+ - `provision.chrome({ url })` starts Chrome in the sandbox and opens the URL.
52
+ - `screenshot()` saves the screen to `.testdriver/screenshots/` and returns the file path. Use it to debug failures later.
53
+ - `assert()` asks the AI whether a statement about the screen is true.
54
+ - `assert()` throws when the statement is false, so the test fails at that line.
55
+ - The `expect()` after it makes the check explicit in the test.
56
+
57
+ ## Run it
58
+
59
+ The test is in the [TestDriver SDK repository](https://github.com/testdriverai/testdriverai/tree/main/examples). Clone it, install dependencies, and run the file:
72
60
 
73
61
  ```bash
74
- # Clone the TestDriver repository
75
62
  git clone https://github.com/testdriverai/testdriverai
76
-
77
- # Install dependencies
78
63
  cd testdriverai
79
64
  npm install
80
-
81
- # Run this specific example
82
- vitest run examples/assert.test.mjs
65
+ npx vitest run examples/assert.test.mjs
83
66
  ```
84
67
 
85
- <Note>
86
- Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
87
- </Note>
68
+ The test reads your API key from `TD_API_KEY`. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). Then set it in your environment or a `.env` file.
69
+
70
+ ## Related
71
+
72
+ - [assert()](/assert)
73
+ - [screenshot()](/screenshot)
74
+ - [Make assertions](/making-assertions)
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: "Click a button by its label"
3
+ sidebarTitle: "Click a button"
4
+ description: "Click Sign In on an empty login form and assert that a validation error appears."
5
+ icon: "hand-pointer"
6
+ mode: "wide"
7
+ ---
8
+
9
+ This test clicks **Sign In** on an empty login form and asserts that a "fields required" error appears.
10
+
11
+ ## Watch it run
12
+
13
+ {/* click-button.test.mjs output */}
14
+ <iframe
15
+ src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6ad6b60a022b6043aeec2bf1/replay"
16
+ width="100%"
17
+ height="390"
18
+ style={{ border: "1px solid #333", borderRadius: "8px" }}
19
+ allow="fullscreen"
20
+ />
21
+
22
+ ## The test
23
+
24
+ ```javascript title="click-button.test.mjs"
25
+ import { describe, expect, it } from "vitest";
26
+ import { TestDriver } from "testdriverai/vitest/hooks";
27
+
28
+ describe("Hover Text Test", () => {
29
+ it("should click Sign In and verify error message", async (context) => {
30
+ const testdriver = TestDriver(context);
31
+ await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
32
+
33
+ // Submit the login form without filling it in
34
+ const signInButton = await testdriver.find(
35
+ "Sign In, black button below the password field",
36
+ );
37
+ await signInButton.click();
38
+
39
+ // Assert that an error shows that fields are required
40
+ const result = await testdriver.assert(
41
+ "an error shows that fields are required",
42
+ );
43
+ expect(result).toBeTruthy();
44
+ });
45
+ });
46
+ ```
47
+
48
+ ## How it works
49
+
50
+ - The `find()` description gives the button's label, look, and position ("black button below the password field").
51
+ - `click()` clicks the returned element. It throws if `find()` didn't locate it.
52
+ - `assert()` describes the error in plain language, so the test doesn't depend on exact wording or markup.
53
+
54
+ ## Run it
55
+
56
+ The test is in the [TestDriver SDK repository](https://github.com/testdriverai/testdriverai/tree/main/examples). Clone it, install dependencies, and run the file:
57
+
58
+ ```bash
59
+ git clone https://github.com/testdriverai/testdriverai
60
+ cd testdriverai
61
+ npm install
62
+ npx vitest run examples/click-button.test.mjs
63
+ ```
64
+
65
+ The test reads your API key from `TD_API_KEY`. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). Then set it in your environment or a `.env` file.
66
+
67
+ ## Related
68
+
69
+ - [find()](/find)
70
+ - [click()](/click)
71
+ - [assert()](/assert)
@@ -1,16 +1,16 @@
1
1
  ---
2
- title: "Clicking Image Example"
3
- sidebarTitle: "Clicking on an Image"
4
- description: "Example test that finds and clicks on an image element using AI-powered visual recognition."
2
+ title: "Click an icon"
3
+ sidebarTitle: "Click an icon"
4
+ description: "Log in to a demo store, click the cart icon, and assert that the cart is empty."
5
5
  icon: "hand-pointer"
6
6
  mode: "wide"
7
7
  ---
8
8
 
9
- ## Demo Test Run
9
+ This test logs in to a demo store, clicks the shopping cart icon, and asserts that the cart is empty.
10
10
 
11
- Watch this test execute in a real sandbox environment:
11
+ ## Watch it run
12
12
 
13
- {/* hover-image.test.mjs output */}
13
+ {/* click-icon.test.mjs output */}
14
14
  <iframe
15
15
  src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6ad6b5f59af2067e32da0686/replay"
16
16
  width="100%"
@@ -19,20 +19,15 @@ Watch this test execute in a real sandbox environment:
19
19
  allow="fullscreen"
20
20
  />
21
21
 
22
- ## Source Code
23
-
24
- ```javascript title="hover-image.test.mjs" {40-42,47}
25
- /**
26
- * TestDriver SDK - Hover Image Test (Vitest)
27
- * Converted from: testdriver/acceptance/hover-image.yaml
28
- */
22
+ ## The test
29
23
 
24
+ ```javascript title="click-icon.test.mjs"
30
25
  import { describe, expect, it } from "vitest";
31
26
  import { TestDriver } from "testdriverai/vitest/hooks";
32
27
 
33
28
  /**
34
- * Perform login flow for SauceLabs demo app
35
- * @param {import('../../sdk.js').default} client - TestDriver client instance
29
+ * Log in to the TestDriver sandbox demo store.
30
+ * @param {object} client - TestDriver instance
36
31
  * @param {string} username - Username (default: 'standard_user')
37
32
  */
38
33
  async function performLogin(client, username = "standard_user") {
@@ -51,9 +46,8 @@ async function performLogin(client, username = "standard_user") {
51
46
 
52
47
  describe("Hover Image Test", () => {
53
48
  it("should click on shopping cart icon and verify empty cart", async (context) => {
54
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
55
-
56
- // provision.chrome() automatically calls ready() and starts dashcam
49
+ const testdriver = TestDriver(context);
50
+
57
51
  await testdriver.provision.chrome({
58
52
  url: 'http://testdriver-sandbox.vercel.app/login'
59
53
  });
@@ -76,20 +70,30 @@ describe("Hover Image Test", () => {
76
70
  });
77
71
  ```
78
72
 
79
- ## Running This Example
73
+ ## How it works
74
+
75
+ - `performLogin()` is a plain function that takes the TestDriver instance, so any test can reuse it.
76
+ - The demo store shows its password on screen, so `extract()` reads it.
77
+ - `type(password, { secret: true })` keeps the password out of logs.
78
+ - `focusApplication('Google Chrome')` brings Chrome to the front before the test uses it.
79
+ - The `find()` description names the icon and its position ("next to the Cart text in the top right corner"). This helps the AI pick the right one.
80
+
81
+ ## Run it
82
+
83
+ The test is in the [TestDriver SDK repository](https://github.com/testdriverai/testdriverai/tree/main/examples). Clone it, install dependencies, and run the file:
80
84
 
81
85
  ```bash
82
- # Clone the TestDriver repository
83
86
  git clone https://github.com/testdriverai/testdriverai
84
-
85
- # Install dependencies
86
87
  cd testdriverai
87
88
  npm install
88
-
89
- # Run this specific example
90
- vitest run examples/hover-image.test.mjs
89
+ npx vitest run examples/click-icon.test.mjs
91
90
  ```
92
91
 
93
- <Note>
94
- Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
95
- </Note>
92
+ The test reads your API key from `TD_API_KEY`. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). Then set it in your environment or a `.env` file.
93
+
94
+ ## Related
95
+
96
+ - [find()](/find)
97
+ - [extract()](/extract)
98
+ - [Reuse code across tests](/reusable-code)
99
+ - [Secrets](/secrets)
@@ -1,14 +1,14 @@
1
1
  ---
2
- title: "Element Not Found Test"
3
- sidebarTitle: "Element Not Found"
4
- description: "Example test showing how to gracefully handle elements that don't exist on the page."
2
+ title: "Handle an element that isn't found"
3
+ sidebarTitle: "Element not found"
4
+ description: "See how find() returns an unfound element instead of throwing when nothing matches."
5
5
  icon: "crosshairs"
6
6
  mode: "wide"
7
7
  ---
8
8
 
9
- ## Demo Test Run
9
+ This test looks for an element that isn't on the page. Use this pattern when an element may not appear.
10
10
 
11
- Watch this test execute in a real sandbox environment:
11
+ ## Watch it run
12
12
 
13
13
  {/* element-not-found.test.mjs output */}
14
14
  <iframe
@@ -19,24 +19,17 @@ Watch this test execute in a real sandbox environment:
19
19
  allow="fullscreen"
20
20
  />
21
21
 
22
- ## Source Code
23
-
24
- ```javascript title="element-not-found.test.mjs" {16-18}
25
- /**
26
- * TestDriver SDK - Element Not Found Test
27
- * Tests that finding a non-existent element returns properly without timing out
28
- */
22
+ ## The test
29
23
 
24
+ ```javascript title="element-not-found.test.mjs"
30
25
  import { describe, expect, it } from "vitest";
31
26
  import { TestDriver } from "testdriverai/vitest/hooks";
32
27
 
33
28
  describe("Element Not Found Test", () => {
34
29
  it("should handle non-existent element gracefully without timing out", async (context) => {
35
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
30
+ const testdriver = TestDriver(context);
36
31
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
37
32
 
38
- //
39
-
40
33
  // Try to find an element that definitely doesn't exist
41
34
  const element = await testdriver.find(
42
35
  "a purple unicorn dancing on the moon",
@@ -45,24 +38,32 @@ describe("Element Not Found Test", () => {
45
38
  // Should return an element that is not found
46
39
  expect(element.found()).toBe(false);
47
40
  expect(element.coordinates).toBeNull();
48
- }); // 90 second timeout for the test (should complete much faster)
41
+ });
49
42
  });
50
43
  ```
51
44
 
52
- ## Running This Example
45
+ ## How it works
46
+
47
+ - By default, `find()` checks the screen every 5 seconds for up to 10 seconds.
48
+ - When nothing matches, `find()` doesn't throw.
49
+ - Instead, it returns an element whose `found()` is `false` and whose `coordinates` are `null`.
50
+ - Calling `click()` on an unfound element throws an `ElementNotFoundError`.
51
+
52
+ ## Run it
53
+
54
+ The test is in the [TestDriver SDK repository](https://github.com/testdriverai/testdriverai/tree/main/examples). Clone it, install dependencies, and run the file:
53
55
 
54
56
  ```bash
55
- # Clone the TestDriver repository
56
57
  git clone https://github.com/testdriverai/testdriverai
57
-
58
- # Install dependencies
59
58
  cd testdriverai
60
59
  npm install
61
-
62
- # Run this specific example
63
- vitest run examples/element-not-found.test.mjs
60
+ npx vitest run examples/element-not-found.test.mjs
64
61
  ```
65
62
 
66
- <Note>
67
- Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
68
- </Note>
63
+ The test reads your API key from `TD_API_KEY`. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). Then set it in your environment or a `.env` file.
64
+
65
+ ## Related
66
+
67
+ - [find()](/find)
68
+ - [Locate elements](/locating-elements)
69
+ - [Errors](/errors)
@@ -1,20 +1,14 @@
1
1
  ---
2
- title: "FindAll Test Example"
3
- sidebarTitle: "Findall Coffee Icons"
4
- description: "TestDriver SDK - FindAll Coffee Icons Test Loads a random icon grid and uses findAll() to locate and click all 4 coffee cup icons."
5
- icon: "play"
2
+ title: "Find and click every matching element"
3
+ sidebarTitle: "Find all"
4
+ description: "Use findAll() to locate every coffee cup icon in a grid and click each one."
5
+ icon: "crosshairs"
6
6
  mode: "wide"
7
7
  ---
8
8
 
9
- ## Overview
9
+ This test uses `findAll()` to find every coffee cup in an icon grid, clicks each one, and asserts on the result.
10
10
 
11
- TestDriver SDK - FindAll Coffee Icons Test Loads a random icon grid and uses findAll() to locate and click all 4 coffee cup icons
12
-
13
- Review the source code below to understand the implementation details and patterns used.
14
-
15
- ## Live Test Run
16
-
17
- Watch this test execute in a real sandbox environment:
11
+ ## Watch it run
18
12
 
19
13
  {/* findall-coffee-icons.test.mjs output */}
20
14
  <iframe
@@ -25,22 +19,15 @@ Watch this test execute in a real sandbox environment:
25
19
  allow="fullscreen"
26
20
  />
27
21
 
28
- ## Source Code
22
+ ## The test
29
23
 
30
24
  ```javascript title="findall-coffee-icons.test.mjs"
31
- /**
32
- * TestDriver SDK - FindAll Coffee Icons Test
33
- * Loads a random icon grid and uses findAll() to locate and click all 4 coffee cup icons
34
- */
35
-
36
25
  import { describe, expect, it } from "vitest";
37
26
  import { TestDriver } from "testdriverai/vitest/hooks";
38
27
 
39
28
  describe("FindAll Coffee Icons", () => {
40
29
  it("should find and click all 4 coffee cup icons", async (context) => {
41
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP,
42
- headless: true,
43
- });
30
+ const testdriver = TestDriver(context);
44
31
 
45
32
  await testdriver.provision.chrome({
46
33
  url: "https://v0-random-icon-grid.vercel.app/",
@@ -55,7 +42,7 @@ describe("FindAll Coffee Icons", () => {
55
42
  console.log(` Icon ${i + 1}: (${icon.x}, ${icon.y}) center=(${icon.centerX}, ${icon.centerY})`);
56
43
  });
57
44
 
58
- // Verify we found 3 or 4 coffee icons
45
+ // The grid has 4 coffee cups; allow one miss, matching the assertion below
59
46
  expect(coffeeIcons.length).toBeGreaterThanOrEqual(3);
60
47
  expect(coffeeIcons.length).toBeLessThanOrEqual(4);
61
48
 
@@ -70,20 +57,29 @@ describe("FindAll Coffee Icons", () => {
70
57
  });
71
58
  ```
72
59
 
73
- ## Running This Example
60
+ ## How it works
61
+
62
+ - `findAll()` returns an array with one element per match.
63
+ - The description states how many to expect ("there are exactly 4 on the page").
64
+ - Each element has its position in `x`, `y`, `centerX`, and `centerY`.
65
+ - Each element has its own `click()`, so a `for...of` loop clicks them in turn.
66
+ - The test and assertion accept 3 or 4 matches, so one missed icon doesn't fail the run.
67
+
68
+ ## Run it
69
+
70
+ The test is in the [TestDriver SDK repository](https://github.com/testdriverai/testdriverai/tree/main/examples). Clone it, install dependencies, and run the file:
74
71
 
75
72
  ```bash
76
- # Clone the TestDriver repository
77
73
  git clone https://github.com/testdriverai/testdriverai
78
-
79
- # Install dependencies
80
74
  cd testdriverai
81
75
  npm install
82
-
83
- # Run this specific example
84
- vitest run examples/findall-coffee-icons.test.mjs
76
+ npx vitest run examples/findall-coffee-icons.test.mjs
85
77
  ```
86
78
 
87
- <Note>
88
- Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
89
- </Note>
79
+ The test reads your API key from `TD_API_KEY`. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). Then set it in your environment or a `.env` file.
80
+
81
+ ## Related
82
+
83
+ - [find()](/find)
84
+ - [click()](/click)
85
+ - [assert()](/assert)
@@ -1,14 +1,18 @@
1
1
  ---
2
- title: "Linux App Installation Test Example"
3
- sidebarTitle: "Linux Installer"
4
- description: "Example test demonstrating how to download and install .deb packages and shell scripts on Linux."
2
+ title: "Install a Linux package"
3
+ sidebarTitle: "Linux installer"
4
+ description: "Use provision.installer() to install command-line and desktop apps, and download a script, on Linux."
5
5
  icon: "download"
6
6
  mode: "wide"
7
7
  ---
8
8
 
9
- ## Demo Test Run
9
+ This file has three `provision.installer()` tests in a Linux sandbox:
10
10
 
11
- Watch this test execute in a real sandbox environment:
11
+ - One installs a command-line tool from a `.deb` and runs it.
12
+ - One installs a desktop app from a `.deb` and checks that its window opens.
13
+ - One downloads a shell script without running it and checks that it exists.
14
+
15
+ ## Watch it run
12
16
 
13
17
  {/* installer.test.mjs output */}
14
18
  <iframe
@@ -19,14 +23,9 @@ Watch this test execute in a real sandbox environment:
19
23
  allow="fullscreen"
20
24
  />
21
25
 
22
- ## Source Code
23
-
24
- ```javascript title="installer.test.mjs" {16-18}
25
- /**
26
- * TestDriver SDK - Installer Test (Vitest)
27
- * Tests the provision.installer() method for downloading and installing apps
28
- */
26
+ ## The test
29
27
 
28
+ ```javascript title="installer.test.mjs"
30
29
  import { describe, expect, it } from "vitest";
31
30
  import { TestDriver } from "testdriverai/vitest/hooks";
32
31
 
@@ -36,7 +35,7 @@ describe("Provision Installer", () => {
36
35
  it.skipIf(!isLinux)(
37
36
  "should download and install a .deb package on Linux",
38
37
  async (context) => {
39
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
38
+ const testdriver = TestDriver(context);
40
39
 
41
40
  // Install bat (a cat clone with syntax highlighting) using provision.installer
42
41
  const filePath = await testdriver.provision.installer({
@@ -51,15 +50,41 @@ describe("Provision Installer", () => {
51
50
  },
52
51
  );
53
52
 
53
+ it.skipIf(!isLinux)(
54
+ "should install a .deb with missing dependencies and launch its window",
55
+ async (context) => {
56
+ const testdriver = TestDriver(context);
57
+
58
+ // Yaak is a Tauri app. Its .deb depends on WebKitGTK and libsoup,
59
+ // which aren't preinstalled, so dpkg alone leaves it unconfigured.
60
+ await testdriver.provision.installer({
61
+ url: 'https://github.com/mountain-loop/yaak/releases/download/v2026.9.0/yaak_2026.9.0_amd64.deb',
62
+ appName: 'Yaak',
63
+ });
64
+
65
+ // The package and its dependencies are fully installed
66
+ const status = await testdriver.exec(
67
+ 'sh',
68
+ "dpkg-query -W -f='${Status}' yaak",
69
+ 10000,
70
+ );
71
+ expect(status).toBe('install ok installed');
72
+
73
+ // launch: true (the default) started the app, so its window is on screen
74
+ const result = await testdriver.assert('The Yaak app window is open');
75
+ expect(result).toBeTruthy();
76
+ },
77
+ );
78
+
54
79
  it.skipIf(!isLinux)(
55
80
  "should download a shell script and verify it exists",
56
81
  async (context) => {
57
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
82
+ const testdriver = TestDriver(context);
58
83
 
59
84
  // Download a shell script (nvm installer)
60
85
  const filePath = await testdriver.provision.installer({
61
86
  url: 'https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh',
62
- launch: false, // Don't auto-run the script
87
+ launch: false, // Download the script without running it
63
88
  });
64
89
 
65
90
  // Verify the file was downloaded
@@ -73,20 +98,31 @@ describe("Provision Installer", () => {
73
98
  });
74
99
  ```
75
100
 
76
- ## Running This Example
101
+ ## How it works
102
+
103
+ - `provision.installer({ url })` downloads the file, installs it by extension, and returns its path.
104
+ - On Linux, a `.deb` is installed with `dpkg`, and missing dependencies are installed with `apt-get`. The step fails if the package still isn't fully installed.
105
+ - With `launch: true` (the default), a `.deb` app is started from its `.desktop` entry, then `appName` is focused. That's how the Yaak window opens.
106
+ - A `.sh` script is made executable and run.
107
+ - `launch: false` makes a `.sh` script executable without running it. It also skips focusing the app when you pass `appName`.
108
+ - With `launch: false`, packages such as `.deb` files are still installed.
109
+ - `exec('sh', command, timeout)` runs a shell command and returns its output. The test uses it to check that `bat` is installed.
110
+ - `it.skipIf(!isLinux)` skips every test when `TD_OS` is set to `windows`.
111
+
112
+ ## Run it
113
+
114
+ The test is in the [TestDriver SDK repository](https://github.com/testdriverai/testdriverai/tree/main/examples). Clone it, install dependencies, and run the file:
77
115
 
78
116
  ```bash
79
- # Clone the TestDriver repository
80
117
  git clone https://github.com/testdriverai/testdriverai
81
-
82
- # Install dependencies
83
118
  cd testdriverai
84
119
  npm install
85
-
86
- # Run this specific example
87
- vitest run examples/installer.test.mjs
120
+ npx vitest run examples/installer.test.mjs
88
121
  ```
89
122
 
90
- <Note>
91
- Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
92
- </Note>
123
+ The test reads your API key from `TD_API_KEY`. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). Then set it in your environment or a `.env` file.
124
+
125
+ ## Related
126
+
127
+ - [Launch apps](/provision)
128
+ - [exec()](/exec)