@testdriverai/agent 7.9.0 → 7.9.1-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 (38) hide show
  1. package/agent/lib/sandbox.js +55 -6
  2. package/agent/lib/sdk.js +4 -4
  3. package/ai/skills/testdriver-enterprise/SKILL.md +2 -109
  4. package/ai/skills/testdriver-hosted/SKILL.md +156 -0
  5. package/ai/skills/testdriver-mcp/SKILL.md +2 -2
  6. package/ai/skills/testdriver-quickstart/SKILL.md +30 -2
  7. package/ai/skills/testdriver-self-hosted/SKILL.md +125 -43
  8. package/ai/skills/testdriver-test-results-json/SKILL.md +257 -0
  9. package/docs/_scripts/generate-examples.js +127 -60
  10. package/docs/docs.json +27 -28
  11. package/docs/v7/examples/ai.mdx +4 -3
  12. package/docs/v7/examples/assert.mdx +19 -4
  13. package/docs/v7/examples/chrome-extension.mdx +36 -29
  14. package/docs/v7/examples/element-not-found.mdx +2 -1
  15. package/docs/v7/examples/exec-output.mdx +3 -4
  16. package/docs/v7/examples/exec-pwsh.mdx +3 -4
  17. package/docs/v7/examples/findall-coffee-icons.mdx +88 -0
  18. package/docs/v7/examples/focus-window.mdx +3 -4
  19. package/docs/v7/examples/hover-image.mdx +4 -3
  20. package/docs/v7/examples/hover-text-with-description.mdx +104 -0
  21. package/docs/v7/examples/hover-text.mdx +4 -3
  22. package/docs/v7/examples/installer.mdx +5 -4
  23. package/docs/v7/examples/launch-vscode-linux.mdx +3 -7
  24. package/docs/v7/examples/match-image.mdx +3 -2
  25. package/docs/v7/examples/parse.mdx +66 -0
  26. package/docs/v7/examples/press-keys.mdx +8 -14
  27. package/docs/v7/examples/scroll-keyboard.mdx +4 -3
  28. package/docs/v7/examples/scroll-until-image.mdx +3 -2
  29. package/docs/v7/examples/scroll.mdx +6 -14
  30. package/docs/v7/examples/type.mdx +1 -5
  31. package/docs/v7/examples/windows-installer.mdx +10 -4
  32. package/interfaces/vitest-plugin.mjs +2 -2
  33. package/lib/core/Dashcam.js +4 -1
  34. package/lib/sentry.js +5 -1
  35. package/package.json +1 -1
  36. package/setup/aws/install-dev-runner.sh +7 -2
  37. package/setup/aws/spawn-runner.sh +12 -0
  38. package/vitest.config.mjs +1 -1
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: "FindAll Coffee Icons"
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"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ TestDriver SDK - FindAll Coffee Icons Test Loads a random icon grid and uses findAll() to locate and click all 4 coffee cup icons
11
+
12
+ Review the source code below to understand the implementation details and patterns used.
13
+
14
+ ## Live Test Run
15
+
16
+ Watch this test execute in a real sandbox environment:
17
+
18
+ {/* findall-coffee-icons.test.mjs output */}
19
+ <iframe
20
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d03ae8a04db4b705cbf0/replay"
21
+ width="100%"
22
+ height="600"
23
+ style={{ border: "1px solid #333", borderRadius: "8px" }}
24
+ allow="fullscreen"
25
+ />
26
+
27
+ ## Source Code
28
+
29
+ ```javascript title="findall-coffee-icons.test.mjs"
30
+ /**
31
+ * TestDriver SDK - FindAll Coffee Icons Test
32
+ * Loads a random icon grid and uses findAll() to locate and click all 4 coffee cup icons
33
+ */
34
+
35
+ import { describe, expect, it } from "vitest";
36
+ import { TestDriver } from "testdriverai/vitest/hooks";
37
+
38
+ describe("FindAll Coffee Icons", () => {
39
+ it("should find and click all 4 coffee cup icons", async (context) => {
40
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP,
41
+ headless: true,
42
+ });
43
+
44
+ await testdriver.provision.chrome({
45
+ url: "https://v0-random-icon-grid.vercel.app/",
46
+ });
47
+
48
+ // Use findAll to locate all coffee cup icons on the page
49
+ const coffeeIcons = await testdriver.findAll("coffee cup icon, there are exactly 4 on the page");
50
+
51
+ // Log each icon's coordinates
52
+ console.log(`Found ${coffeeIcons.length} coffee icons:`);
53
+ coffeeIcons.forEach((icon, i) => {
54
+ console.log(` Icon ${i + 1}: (${icon.x}, ${icon.y}) center=(${icon.centerX}, ${icon.centerY})`);
55
+ });
56
+
57
+ // Verify we found 3 or 4 coffee icons
58
+ expect(coffeeIcons.length).toBeGreaterThanOrEqual(3);
59
+ expect(coffeeIcons.length).toBeLessThanOrEqual(4);
60
+
61
+ // Click each coffee cup icon
62
+ for (const icon of coffeeIcons) {
63
+ await icon.click();
64
+ }
65
+
66
+ // Verify the selection count is displayed
67
+ await testdriver.assert("the page says 'Selected: 3 / 4' or 'Matched 4 of a kind!'");
68
+ });
69
+ });
70
+ ```
71
+
72
+ ## Running This Example
73
+
74
+ ```bash
75
+ # Clone the TestDriver repository
76
+ git clone https://github.com/testdriverai/testdriverai
77
+
78
+ # Install dependencies
79
+ cd testdriverai
80
+ npm install
81
+
82
+ # Run this specific example
83
+ npx vitest run examples/findall-coffee-icons.test.mjs
84
+ ```
85
+
86
+ <Note>
87
+ Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
88
+ </Note>
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* focus-window.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d042e8a04db4b705cbf2/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d042e8a04db4b705cbf2/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -28,14 +28,13 @@ Watch this test execute in a real sandbox environment:
28
28
  */
29
29
 
30
30
  import { describe, expect, it } from "vitest";
31
- import { TestDriver } from "../lib/vitest/hooks.mjs";
32
- import { getDefaults } from "./config.mjs";
31
+ import { TestDriver } from "testdriverai/vitest/hooks";
33
32
 
34
33
  describe("Focus Window Test", () => {
35
34
  it.skip(
36
35
  "should click Microsoft Edge icon and focus Google Chrome",
37
36
  async (context) => {
38
- const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
37
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
39
38
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
40
39
 
41
40
  //
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* hover-image.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d0300201196437256cd3/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d0300201196437256cd3/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="hover-image.test.mjs" {40-42,47}
25
25
  /**
26
- * TestDriver SDK - Hover Image Test
26
+ * TestDriver SDK - Hover Image Test (Vitest)
27
+ * Converted from: testdriver/acceptance/hover-image.yaml
27
28
  */
28
29
 
29
30
  import { describe, expect, it } from "vitest";
@@ -50,7 +51,7 @@ async function performLogin(client, username = "standard_user") {
50
51
 
51
52
  describe("Hover Image Test", () => {
52
53
  it("should click on shopping cart icon and verify empty cart", async (context) => {
53
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, redraw: false });
54
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
54
55
 
55
56
  // provision.chrome() automatically calls ready() and starts dashcam
56
57
  await testdriver.provision.chrome({
@@ -0,0 +1,104 @@
1
+ ---
2
+ title: "Hover Text With Description Test"
3
+ sidebarTitle: "Hover Text With Description"
4
+ description: "TestDriver SDK - Hover Text With Description Test (Vitest) Converted from: testdriver/acceptance/hover-text-with-description.yaml."
5
+ icon: "hand-pointer"
6
+ mode: "wide"
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ TestDriver SDK - Hover Text With Description Test (Vitest) Converted from: testdriver/acceptance/hover-text-with-description.yaml
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:
18
+
19
+ {/* hover-text-with-description.test.mjs output */}
20
+ <iframe
21
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d029c2e6e94933886764/replay"
22
+ width="100%"
23
+ height="600"
24
+ style={{ border: "1px solid #333", borderRadius: "8px" }}
25
+ allow="fullscreen"
26
+ />
27
+
28
+ ## Source Code
29
+
30
+ ```javascript title="hover-text-with-description.test.mjs"
31
+ /**
32
+ * TestDriver SDK - Hover Text With Description Test (Vitest)
33
+ * Converted from: testdriver/acceptance/hover-text-with-description.yaml
34
+ */
35
+
36
+ import { describe, expect, it } from "vitest";
37
+ import { TestDriver } from "testdriverai/vitest/hooks";
38
+
39
+ /**
40
+ * Perform login flow for SauceLabs demo app
41
+ * @param {TestDriver} client - TestDriver client
42
+ * @param {string} username - Username (default: 'standard_user')
43
+ */
44
+ async function performLogin(client, username = "standard_user") {
45
+ await client.focusApplication("Google Chrome");
46
+ const password = await client.extract("the password");
47
+ const usernameField = await client.find("username input");
48
+ await usernameField.click();
49
+ await client.type(username);
50
+ await client.pressKeys(["tab"]);
51
+ await client.type(password, { secret: true });
52
+ await client.pressKeys(["tab"]);
53
+ await client.pressKeys(["enter"]);
54
+ }
55
+
56
+ describe("Hover Text With Description Test", () => {
57
+ it("should add TestDriver Hat to cart and verify", async (context) => {
58
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP,
59
+ headless: true,
60
+ });
61
+ await testdriver.provision.chrome({
62
+ url: "http://testdriver-sandbox.vercel.app/login",
63
+ });
64
+
65
+ //
66
+ // Perform login first
67
+ await performLogin(testdriver);
68
+
69
+ // Click on "Add to Cart" under TestDriver Hat
70
+ const addToCartButton = await testdriver.find(
71
+ "Add to Cart, add to cart button under TestDriver Hat",
72
+ );
73
+ await addToCartButton.click();
74
+
75
+ // Click on the cart
76
+ const cartButton = await testdriver.find(
77
+ "Cart, cart button in the top right corner",
78
+ );
79
+ await cartButton.click();
80
+
81
+ // Assert the TestDriver Hat is in the cart
82
+ const result = await testdriver.assert("There is an item in the cart");
83
+ expect(result).toBeTruthy();
84
+ });
85
+ });
86
+ ```
87
+
88
+ ## Running This Example
89
+
90
+ ```bash
91
+ # Clone the TestDriver repository
92
+ git clone https://github.com/testdriverai/testdriverai
93
+
94
+ # Install dependencies
95
+ cd testdriverai
96
+ npm install
97
+
98
+ # Run this specific example
99
+ npx vitest run examples/hover-text-with-description.test.mjs
100
+ ```
101
+
102
+ <Note>
103
+ Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
104
+ </Note>
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* hover-text.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d04b0201196437256ce6/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d04b0201196437256ce6/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="hover-text.test.mjs" {13-15,18-20}
25
25
  /**
26
- * TestDriver SDK - Hover Text Test
26
+ * TestDriver SDK - Hover Text Test (Vitest)
27
+ * Converted from: testdriver/acceptance/hover-text.yaml
27
28
  */
28
29
 
29
30
  import { describe, expect, it } from "vitest";
@@ -31,7 +32,7 @@ import { TestDriver } from "testdriverai/vitest/hooks";
31
32
 
32
33
  describe("Hover Text Test", () => {
33
34
  it("should click Sign In and verify error message", async (context) => {
34
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
35
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
35
36
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
36
37
 
37
38
  // Click on Sign In button using new find() API
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* installer.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d032c2e6e94933886769/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d032c2e6e94933886769/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="installer.test.mjs" {16-18}
25
25
  /**
26
- * TestDriver SDK - Installer Test
26
+ * TestDriver SDK - Installer Test (Vitest)
27
+ * Tests the provision.installer() method for downloading and installing apps
27
28
  */
28
29
 
29
30
  import { describe, expect, it } from "vitest";
@@ -35,7 +36,7 @@ describe("Provision Installer", () => {
35
36
  it.skipIf(!isLinux)(
36
37
  "should download and install a .deb package on Linux",
37
38
  async (context) => {
38
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
39
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
39
40
 
40
41
  // Install bat (a cat clone with syntax highlighting) using provision.installer
41
42
  const filePath = await testdriver.provision.installer({
@@ -53,7 +54,7 @@ describe("Provision Installer", () => {
53
54
  it.skipIf(!isLinux)(
54
55
  "should download a shell script and verify it exists",
55
56
  async (context) => {
56
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
57
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
57
58
 
58
59
  // Download a shell script (nvm installer)
59
60
  const filePath = await testdriver.provision.installer({
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* launch-vscode-linux.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d02be8a04db4b705cbe5/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d02be8a04db4b705cbe5/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -22,10 +22,6 @@ Watch this test execute in a real sandbox environment:
22
22
  ## Source Code
23
23
 
24
24
  ```javascript title="launch-vscode-linux.test.mjs" {13,27-29}
25
- /**
26
- * TestDriver SDK - Launch VS Code Test
27
- */
28
-
29
25
  import { describe, expect, it } from "vitest";
30
26
  import { TestDriver } from "testdriverai/vitest/hooks";
31
27
 
@@ -35,7 +31,7 @@ describe("Launch VS Code on Linux", () => {
35
31
  it.skipIf(!isLinux)(
36
32
  "should launch VS Code on Debian/Ubuntu",
37
33
  async (context) => {
38
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
34
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
39
35
 
40
36
  // provision.vscode() automatically calls ready() and starts dashcam
41
37
  await testdriver.provision.vscode();
@@ -52,7 +48,7 @@ describe("Launch VS Code on Linux", () => {
52
48
  it.skipIf(!isLinux)(
53
49
  "should install and use a VS Code extension",
54
50
  async (context) => {
55
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
51
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
56
52
 
57
53
  // Launch VS Code with the Prettier extension installed
58
54
  await testdriver.provision.vscode({
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* match-image.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d0270201196437256ccf/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d0270201196437256ccf/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="match-image.test.mjs" {42}
25
25
  /**
26
- * TestDriver SDK - Match Image Test
26
+ * TestDriver SDK - Match Image Test (Vitest)
27
+ * Converted from: testdriver/acceptance/match-image.yaml
27
28
  */
28
29
 
29
30
  import path, { dirname } from "path";
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: "Parse Test"
3
+ sidebarTitle: "Parse"
4
+ description: "TestDriver SDK - Parse Test (Vitest) Opens Airbnb and runs the .parse() SDK command to analyze the screen."
5
+ icon: "play"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ TestDriver SDK - Parse Test (Vitest) Opens Airbnb and runs the .parse() SDK command to analyze the screen.
11
+
12
+ Review the source code below to understand the implementation details and patterns used.
13
+
14
+ ## Live Test Run
15
+
16
+ Watch this test execute in a real sandbox environment:
17
+
18
+ {/* parse.test.mjs output */}
19
+ <iframe
20
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d04d0201196437256ce7/replay"
21
+ width="100%"
22
+ height="600"
23
+ style={{ border: "1px solid #333", borderRadius: "8px" }}
24
+ allow="fullscreen"
25
+ />
26
+
27
+ ## Source Code
28
+
29
+ ```javascript title="parse.test.mjs"
30
+ /**
31
+ * TestDriver SDK - Parse Test (Vitest)
32
+ * Opens Airbnb and runs the .parse() SDK command to analyze the screen.
33
+ */
34
+
35
+ import { describe, it } from "vitest";
36
+ import { TestDriver } from "testdriverai/vitest/hooks";
37
+
38
+ describe("Parse Test", () => {
39
+ it("should open Airbnb and parse the screen", async (context) => {
40
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP});
41
+ await testdriver.provision.chrome({ url: "https://www.airbnb.com" });
42
+
43
+ // The SDK automatically outputs elements as a formatted table
44
+ const result = await testdriver.parse();
45
+ console.log(`Found ${result.elements?.length || 0} elements`);
46
+ });
47
+ });
48
+ ```
49
+
50
+ ## Running This Example
51
+
52
+ ```bash
53
+ # Clone the TestDriver repository
54
+ git clone https://github.com/testdriverai/testdriverai
55
+
56
+ # Install dependencies
57
+ cd testdriverai
58
+ npm install
59
+
60
+ # Run this specific example
61
+ npx vitest run examples/parse.test.mjs
62
+ ```
63
+
64
+ <Note>
65
+ Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
66
+ </Note>
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* press-keys.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d036058ffe89003c6ada/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d036058ffe89003c6ada/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="press-keys.test.mjs" {17,24,36}
25
25
  /**
26
- * TestDriver SDK - Press Keys Test
26
+ * TestDriver SDK - Press Keys Test (Vitest)
27
+ * Converted from: testdriver/acceptance/press-keys.yaml
27
28
  */
28
29
 
29
30
  import { describe, expect, it } from "vitest";
@@ -43,23 +44,16 @@ describe("Press Keys Test", () => {
43
44
  await testdriver.pressKeys(["ctrl", "t"]);
44
45
 
45
46
  // Poll for "Learn more" to appear
46
- let learnMore = await testdriver.find("Learn more");
47
- for (let i = 0; i < 10; i++) {
48
- learnMore = await learnMore.find();
49
- if (learnMore.found()) break;
50
- await new Promise((resolve) => setTimeout(resolve, 500));
51
- }
47
+ let imagesLink = await testdriver.find("Images", {timeout: 5000});
48
+
49
+ expect(imagesLink.found()).toBeTruthy();
52
50
 
53
51
  // Open DevTools
54
52
  await testdriver.pressKeys(["ctrl", "shift", "i"]);
55
53
 
56
54
  // Poll for "Elements" to appear
57
- let elements = await testdriver.find("Elements");
58
- for (let i = 0; i < 10; i++) {
59
- elements = await elements.find();
60
- if (elements.found()) break;
61
- await new Promise((resolve) => setTimeout(resolve, 500));
62
- }
55
+ let elements = await testdriver.find("Elements", {timeout: 5000});
56
+ expect(elements.found()).toBeTruthy();
63
57
 
64
58
  // Open another tab and navigate
65
59
  await testdriver.pressKeys(["ctrl", "t"]);
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* scroll-keyboard.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d03da0a3ef8239de474f/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d03da0a3ef8239de474f/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="scroll-keyboard.test.mjs" {26}
25
25
  /**
26
- * TestDriver SDK - Scroll Keyboard Test
26
+ * TestDriver SDK - Scroll Keyboard Test (Vitest)
27
+ * Converted from: testdriver/acceptance/scroll-keyboard.yaml
27
28
  */
28
29
 
29
30
  import { describe, expect, it } from "vitest";
@@ -38,7 +39,7 @@ describe("Scroll Keyboard Test", () => {
38
39
  // Navigate to https://www.webhamster.com/
39
40
  await testdriver.focusApplication("Google Chrome");
40
41
  const urlBar = await testdriver.find(
41
- "testdriver-sandbox.vercel.app/login, the URL in the omnibox showing the current page", {zoom: true}
42
+ "the URL in the omnibox", {zoom: true}
42
43
  );
43
44
  await urlBar.click();
44
45
  await testdriver.pressKeys(["ctrl", "a"]);
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* scroll-until-image.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d03f0201196437256cda/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d03f0201196437256cda/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,8 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="scroll-until-image.test.mjs" {26}
25
25
  /**
26
- * TestDriver SDK - Scroll Until Image Test
26
+ * TestDriver SDK - Scroll Until Image Test (Vitest)
27
+ * Converted from: testdriver/acceptance/scroll-until-image.yaml
27
28
  */
28
29
 
29
30
  import { describe, expect, it } from "vitest";
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* scroll.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d043058ffe89003c6ae0/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d043058ffe89003c6ae0/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,10 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="scroll.test.mjs" {29}
25
25
  /**
26
- * TestDriver SDK - Scroll Test
26
+ * TestDriver SDK - Scroll Test (Vitest)
27
+ * Converted from: testdriver/acceptance/scroll.yaml
28
+ *
29
+ * UPDATED: Now using chrome preset for automatic setup
27
30
  */
28
31
 
29
32
  import { describe, expect, it } from "vitest";
@@ -32,19 +35,8 @@ import { TestDriver } from "testdriverai/vitest/hooks";
32
35
  describe("Scroll Test", () => {
33
36
  it("should navigate and scroll down the page", async (context) => {
34
37
  const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
35
- await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
38
+ await testdriver.provision.chrome({ url: 'https://www.webhamster.com/' });
36
39
 
37
- // Give Chrome a moment to fully render the UI
38
- await new Promise(resolve => setTimeout(resolve, 2000));
39
-
40
- // Navigate to webhamster.com - just look for the domain, not the full path
41
- const urlBar = await testdriver.find(
42
- "testdriver-sandbox.vercel.app, the URL in the address bar",
43
- );
44
- await urlBar.click();
45
- await testdriver.pressKeys(["ctrl", "a"]);
46
- await testdriver.type("https://www.webhamster.com/");
47
- await testdriver.pressKeys(["enter"]);
48
40
 
49
41
  // Wait for page to load and click heading
50
42
  const heading = await testdriver.find(
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* type.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d034c2e6e9493388676c/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d034c2e6e9493388676c/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -22,10 +22,6 @@ Watch this test execute in a real sandbox environment:
22
22
  ## Source Code
23
23
 
24
24
  ```javascript title="type.test.mjs" {13}
25
- /**
26
- * TestDriver SDK - Type Test
27
- */
28
-
29
25
  import { describe, expect, it } from "vitest";
30
26
  import { TestDriver } from "testdriverai/vitest/hooks";
31
27
 
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
12
12
 
13
13
  {/* windows-installer.test.mjs output */}
14
14
  <iframe
15
- src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/69c5d02ce8a04db4b705cbe9/replay"
15
+ src="https://api.testdriver.ai/api/v1/testdriver/testcase/69c5d02ce8a04db4b705cbe9/replay"
16
16
  width="100%"
17
17
  height="390"
18
18
  style={{ border: "1px solid #333", borderRadius: "8px" }}
@@ -23,7 +23,14 @@ Watch this test execute in a real sandbox environment:
23
23
 
24
24
  ```javascript title="windows-installer.test.mjs" {22-25}
25
25
  /**
26
- * TestDriver SDK - Windows Installer Example
26
+ * TestDriver SDK - Windows Installer Example (Vitest)
27
+ *
28
+ * This example demonstrates how to download and install a Windows application
29
+ * using PowerShell commands, then launch and interact with it.
30
+ *
31
+ * Based on the v6 GitButler provisioning workflow.
32
+ *
33
+ * Run: TD_OS=windows vitest run examples/windows-installer.test.mjs
27
34
  */
28
35
 
29
36
  import { describe, it } from "vitest";
@@ -35,8 +42,7 @@ describe("Windows App Installation", () => {
35
42
 
36
43
  it.skipIf(isLinux)("should download, install, and launch GitButler on Windows", async (context) => {
37
44
  // Alternative approach using provision.installer helper
38
- const testdriver = TestDriver(context, {
39
- ip: context.ip || process.env.TD_IP,
45
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP,
40
46
  os: 'windows'
41
47
  });
42
48
 
@@ -412,9 +412,9 @@ export async function authenticateWithApiKey(apiKey, apiRoot) {
412
412
  if (response.status >= 500) {
413
413
  const serverError = new Error(
414
414
  data.message ||
415
- `TestDriver API is currently unavailable (HTTP ${response.status}). Please try again later.`,
415
+ `An error occurred on the TestDriver server (HTTP ${response.status}). Please try again later.`,
416
416
  );
417
- serverError.code = data.error || "API_UNAVAILABLE";
417
+ serverError.code = data.error || "SERVER_ERROR";
418
418
  serverError.isServerError = true;
419
419
  throw serverError;
420
420
  }
@@ -369,6 +369,7 @@ class Dashcam {
369
369
  } else {
370
370
  // Linux/Mac with TD_API_ROOT
371
371
  this._log("debug", "Starting dashcam recording on Linux/Mac...");
372
+ const dashcamPath = await this._getDashcamPath();
372
373
  const titleArg = this.title
373
374
  ? ` --title="${this.title.replace(/"/g, '"')}"`
374
375
  : "";
@@ -376,10 +377,12 @@ class Dashcam {
376
377
  this.startTime = Date.now();
377
378
  await this.client.exec(
378
379
  shell,
379
- `TD_API_ROOT="${apiRoot}" dashcam record${titleArg} >/dev/null 2>&1 &`,
380
+ `TD_API_ROOT="${apiRoot}" "${dashcamPath}" record${titleArg} >/dev/null 2>&1 &`,
380
381
  10000,
381
382
  process.env.TD_DEBUG == "true" ? false : true,
382
383
  );
384
+ // Give dashcam time to initialize and create its status file before marking as recording
385
+ await new Promise((resolve) => setTimeout(resolve, 3000));
383
386
  this._log("debug", "Dashcam recording started");
384
387
  }
385
388