testdriverai 7.3.4 → 7.3.6

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 (60) hide show
  1. package/.github/workflows/acceptance-linux-scheduled.yaml +1 -1
  2. package/.github/workflows/acceptance.yaml +38 -1
  3. package/.github/workflows/windows-self-hosted.yaml +9 -1
  4. package/CHANGELOG.md +8 -0
  5. package/docs/_data/examples-manifest.json +105 -0
  6. package/docs/_data/examples-manifest.schema.json +41 -0
  7. package/docs/_scripts/extract-example-urls.js +165 -0
  8. package/docs/_scripts/generate-examples.js +534 -0
  9. package/docs/docs.json +242 -212
  10. package/docs/v7/aws-setup.mdx +1 -1
  11. package/docs/v7/examples/ai.mdx +72 -0
  12. package/docs/v7/examples/assert.mdx +72 -0
  13. package/docs/v7/examples/captcha-api.mdx +92 -0
  14. package/docs/v7/examples/chrome-extension.mdx +132 -0
  15. package/docs/v7/examples/drag-and-drop.mdx +100 -0
  16. package/docs/v7/examples/element-not-found.mdx +67 -0
  17. package/docs/v7/examples/hover-image.mdx +94 -0
  18. package/docs/v7/examples/hover-text.mdx +69 -0
  19. package/docs/v7/examples/installer.mdx +91 -0
  20. package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
  21. package/docs/v7/examples/match-image.mdx +96 -0
  22. package/docs/v7/examples/press-keys.mdx +92 -0
  23. package/docs/v7/examples/scroll-keyboard.mdx +79 -0
  24. package/docs/v7/examples/scroll-until-image.mdx +81 -0
  25. package/docs/v7/examples/scroll-until-text.mdx +109 -0
  26. package/docs/v7/examples/scroll.mdx +81 -0
  27. package/docs/v7/examples/type.mdx +92 -0
  28. package/docs/v7/examples/windows-installer.mdx +89 -0
  29. package/examples/ai.test.mjs +2 -1
  30. package/examples/assert.test.mjs +2 -2
  31. package/examples/captcha-api.test.mjs +3 -2
  32. package/examples/chrome-extension.test.mjs +3 -2
  33. package/examples/config.mjs +5 -0
  34. package/examples/drag-and-drop.test.mjs +2 -1
  35. package/examples/element-not-found.test.mjs +2 -1
  36. package/examples/exec-output.test.mjs +2 -1
  37. package/examples/exec-pwsh.test.mjs +2 -1
  38. package/examples/focus-window.test.mjs +2 -1
  39. package/examples/formatted-logging.test.mjs +2 -1
  40. package/examples/hover-image.test.mjs +2 -1
  41. package/examples/hover-text-with-description.test.mjs +2 -1
  42. package/examples/hover-text.test.mjs +2 -1
  43. package/examples/installer.test.mjs +3 -2
  44. package/examples/launch-vscode-linux.test.mjs +3 -2
  45. package/examples/match-image.test.mjs +2 -1
  46. package/examples/no-provision.test.mjs +2 -3
  47. package/examples/press-keys.test.mjs +7 -13
  48. package/examples/prompt.test.mjs +2 -1
  49. package/examples/scroll-keyboard.test.mjs +2 -1
  50. package/examples/scroll-until-image.test.mjs +2 -1
  51. package/examples/scroll-until-text.test.mjs +2 -1
  52. package/examples/scroll.test.mjs +2 -1
  53. package/examples/type.test.mjs +3 -2
  54. package/examples/windows-installer.test.mjs +2 -1
  55. package/interfaces/vitest-plugin.mjs +50 -18
  56. package/package.json +3 -1
  57. package/sdk.js +49 -38
  58. package/vitest.config.mjs +1 -1
  59. package/docs/v7/examples.mdx +0 -5
  60. package/jsconfig.json +0 -26
@@ -0,0 +1,92 @@
1
+ ---
2
+ title: "Typing Test Example"
3
+ sidebarTitle: "Typing"
4
+ description: "Example test demonstrating how to type text into input fields and verify the content."
5
+ icon: "keyboard"
6
+ mode: "wide"
7
+ ---
8
+
9
+ ## Demo Test Run
10
+
11
+ Watch this test execute in a real sandbox environment:
12
+
13
+ {/* type.test.mjs output */}
14
+ <iframe
15
+ src="https://testdriver-api.onrender.com/api/v1/testdriver/testcase/698b7d364f24dc8fa701f5e7/replay"
16
+ width="100%"
17
+ height="390"
18
+ style={{ border: "1px solid #333", borderRadius: "8px" }}
19
+ allow="fullscreen"
20
+ />
21
+
22
+ ## Source Code
23
+
24
+ ```javascript title="type.test.mjs" {13}
25
+ /**
26
+ * TestDriver SDK - Type Test
27
+ */
28
+
29
+ import { describe, expect, it } from "vitest";
30
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
31
+
32
+ describe("Type Test", () => {
33
+ it("should enter standard_user in username field", async (context) => {
34
+ 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' });
36
+
37
+ //
38
+ const usernameField = await testdriver.find(
39
+ "Username, input field for username",
40
+ );
41
+ await usernameField.click();
42
+ await testdriver.type("standard_user");
43
+
44
+ const result = await testdriver.assert(
45
+ 'the username field contains "standard_user"',
46
+ );
47
+ expect(result).toBeTruthy();
48
+ });
49
+
50
+ it("should show validation message when clicking Sign In without password", async (context) => {
51
+ const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
52
+ await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
53
+
54
+ // First fill in username
55
+ const usernameField = await testdriver.find(
56
+ "Username, input field for username",
57
+ );
58
+ await usernameField.click();
59
+ await testdriver.type("standard_user");
60
+
61
+ //
62
+ const signInButton = await testdriver.find(
63
+ "Sign in, black button below the password field",
64
+ );
65
+ await signInButton.click();
66
+
67
+ await testdriver.focusApplication("Google Chrome");
68
+ const result = await testdriver.assert(
69
+ "Please fill out this field is visible near the password field",
70
+ );
71
+ expect(result).toBeTruthy();
72
+ });
73
+ });
74
+ ```
75
+
76
+ ## Running This Example
77
+
78
+ ```bash
79
+ # Clone the TestDriver repository
80
+ git clone https://github.com/testdriverai/testdriverai
81
+
82
+ # Install dependencies
83
+ cd testdriverai
84
+ npm install
85
+
86
+ # Run this specific example
87
+ npx vitest run examples/type.test.mjs
88
+ ```
89
+
90
+ <Note>
91
+ Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
92
+ </Note>
@@ -0,0 +1,89 @@
1
+ ---
2
+ title: "Windows App Installation"
3
+ sidebarTitle: "Windows Installer"
4
+ description: "Example test showing how to download and install Windows applications using MSI installers."
5
+ icon: "download"
6
+ mode: "wide"
7
+ ---
8
+
9
+ ## Demo Test Run
10
+
11
+ Watch this test execute in a real sandbox environment:
12
+
13
+ {/* windows-installer.test.mjs output */}
14
+ <iframe
15
+ src="https://testdriver-api.onrender.com/api/v1/testdriver/testcase/698b7c4f4f24dc8fa701f5bb/replay"
16
+ width="100%"
17
+ height="390"
18
+ style={{ border: "1px solid #333", borderRadius: "8px" }}
19
+ allow="fullscreen"
20
+ />
21
+
22
+ ## Source Code
23
+
24
+ ```javascript title="windows-installer.test.mjs" {22-25}
25
+ /**
26
+ * TestDriver SDK - Windows Installer Example
27
+ */
28
+
29
+ import { describe, it } from "vitest";
30
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
31
+
32
+ const isLinux = (process.env.TD_OS || "linux") === "linux";
33
+
34
+ describe("Windows App Installation", () => {
35
+
36
+ it.skipIf(isLinux)("should download, install, and launch GitButler on Windows", async (context) => {
37
+ // Alternative approach using provision.installer helper
38
+ const testdriver = TestDriver(context, {
39
+ ip: context.ip || process.env.TD_IP,
40
+ os: 'windows'
41
+ });
42
+
43
+ // Download the MSI installer
44
+ const installerPath = await testdriver.provision.installer({
45
+ url: 'https://app.gitbutler.com/downloads/release/windows/x86_64/msi',
46
+ launch: false, // Don't auto-launch, we'll install manually
47
+ });
48
+
49
+ console.log('Installer downloaded to:', installerPath);
50
+
51
+ // Install the MSI silently (the file might not have an extension, so we try MSI first)
52
+ await testdriver.exec('pwsh',
53
+ `Start-Process msiexec.exe -ArgumentList "/i \`"${installerPath}\`" /qn /norestart" -Wait`,
54
+ 120000
55
+ );
56
+
57
+ // Verify installation by checking if executable exists
58
+ const verifyScript = `
59
+ $exePath = "C:\\Program Files\\GitButler\\gitbutler-tauri.exe"
60
+ if (Test-Path $exePath) {
61
+ Write-Host "GitButler installed successfully at $exePath"
62
+ } else {
63
+ Write-Error "GitButler not found"
64
+ exit 1
65
+ }
66
+ `;
67
+
68
+ await testdriver.exec('pwsh', verifyScript, 5000);
69
+ });
70
+ });
71
+ ```
72
+
73
+ ## Running This Example
74
+
75
+ ```bash
76
+ # Clone the TestDriver repository
77
+ git clone https://github.com/testdriverai/testdriverai
78
+
79
+ # Install dependencies
80
+ cd testdriverai
81
+ npm install
82
+
83
+ # Run this specific example
84
+ npx vitest run examples/windows-installer.test.mjs
85
+ ```
86
+
87
+ <Note>
88
+ Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
89
+ </Note>
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("AI Test", () => {
10
11
  it("should use ai to search for testdriver on Google", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
12
13
 
13
14
  // provision.chrome() automatically calls ready() and starts dashcam
14
15
  await testdriver.provision.chrome({
@@ -5,12 +5,12 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Assert Test", () => {
10
11
  it("should assert the testdriver login page shows", async (context) => {
11
12
  const testdriver = TestDriver(context, {
12
- preview: 'ide',
13
- ip: context.ip || process.env.TD_IP,
13
+ ...getDefaults(context),
14
14
  });
15
15
 
16
16
  // provision.chrome() automatically calls ready() and starts dashcam
@@ -4,12 +4,13 @@
4
4
  */
5
5
  import { describe, expect, it } from "vitest";
6
6
  import { TestDriver } from "../lib/vitest/hooks.mjs";
7
+ import { getDefaults } from "./config.mjs";
7
8
 
8
9
  console.log("DEBUG: process.env.TD_OS:", process.env.TD_OS);
9
10
 
10
11
  describe("testdriver.captcha() API", () => {
11
12
  it("should solve reCAPTCHA v3 with auto-detect", async (context) => {
12
- const testdriver = TestDriver(context);
13
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
13
14
 
14
15
  // Launch Chrome (remote debugging is enabled automatically on Linux)
15
16
  await testdriver.provision.chrome({
@@ -30,7 +31,7 @@ describe("testdriver.captcha() API", () => {
30
31
  }, 180000);
31
32
 
32
33
  it("should solve Cloudflare Turnstile", async (context) => {
33
- const testdriver = TestDriver(context);
34
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
34
35
 
35
36
  await testdriver.provision.chrome({
36
37
  url: "https://2captcha.com/demo/cloudflare-turnstile",
@@ -9,13 +9,14 @@
9
9
 
10
10
  import { describe, expect, it } from "vitest";
11
11
  import { TestDriver } from "../lib/vitest/hooks.mjs";
12
+ import { getDefaults } from "./config.mjs";
12
13
 
13
14
  describe("Chrome Extension Test", () => {
14
15
  it("should load hello-world Chrome extension from local path", async (context) => {
15
16
 
16
17
  console.log('connecting to', process.env.TD_IP)
17
18
 
18
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, cacheKey: new Date().getTime().toString() });
19
+ const testdriver = TestDriver(context, { ...getDefaults(context), cacheKey: new Date().getTime().toString() });
19
20
 
20
21
  // Determine OS-specific paths and commands
21
22
  const shell = testdriver.os === 'windows' ? 'pwsh' : 'sh';
@@ -65,7 +66,7 @@ describe("Chrome Extension Test", () => {
65
66
  });
66
67
 
67
68
  it("should load Loom from Chrome Web Store by extensionId", async (context) => {
68
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
69
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
69
70
 
70
71
  // Launch Chrome with Loom loaded by its Chrome Web Store ID
71
72
  // Loom ID: liecbddmkiiihnedobmlmillhodjkdmb
@@ -0,0 +1,5 @@
1
+ export const getDefaults = (context) => ({
2
+ ip: context.ip || process.env.TD_IP,
3
+ redraw: false,
4
+ preview: 'ide',
5
+ });
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  const isLinux = (process.env.TD_OS || "linux") === "linux";
10
11
 
@@ -12,7 +13,7 @@ describe("Drag and Drop Test", () => {
12
13
  it.skipIf(isLinux)(
13
14
  'should drag "New Text Document" to "Recycle Bin"',
14
15
  async (context) => {
15
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
16
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
16
17
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
17
18
 
18
19
  //
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Element Not Found Test", () => {
10
11
  it("should handle non-existent element gracefully without timing out", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  //
@@ -5,12 +5,13 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe.skip("Exec Output Test", () => {
10
11
  it(
11
12
  "should set date using PowerShell and navigate to calendar",
12
13
  async (context) => {
13
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
14
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
14
15
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
15
16
 
16
17
  //
@@ -5,12 +5,13 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe.skip("Exec PowerShell Test", () => {
10
11
  it(
11
12
  "should generate random email using PowerShell and enter it",
12
13
  async (context) => {
13
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
14
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
14
15
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
15
16
 
16
17
  //
@@ -5,12 +5,13 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Focus Window Test", () => {
10
11
  it.skip(
11
12
  "should click Microsoft Edge icon and focus Google Chrome",
12
13
  async (context) => {
13
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
14
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
14
15
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
15
16
 
16
17
  //
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Formatted Logging Test", () => {
10
11
  it("should demonstrate formatted logs in dashcam replay", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  // Find and click - logs will be nicely formatted
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  /**
10
11
  * Perform login flow for SauceLabs demo app
@@ -27,7 +28,7 @@ async function performLogin(client, username = "standard_user") {
27
28
 
28
29
  describe("Hover Image Test", () => {
29
30
  it("should click on shopping cart icon and verify empty cart", async (context) => {
30
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, redraw: false });
31
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
31
32
 
32
33
  // provision.chrome() automatically calls ready() and starts dashcam
33
34
  await testdriver.provision.chrome({
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  /**
10
11
  * Perform login flow for SauceLabs demo app
@@ -26,7 +27,7 @@ async function performLogin(client, username = "standard_user") {
26
27
  describe("Hover Text With Description Test", () => {
27
28
  it("should add TestDriver Hat to cart and verify", async (context) => {
28
29
  const testdriver = TestDriver(context, {
29
- ip: context.ip || process.env.TD_IP,
30
+ ...getDefaults(context),
30
31
  headless: true,
31
32
  });
32
33
  await testdriver.provision.chrome({
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Hover Text Test", () => {
10
11
  it("should click Sign In and verify error message", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  // Click on Sign In button using new find() API
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  const isLinux = (process.env.TD_OS || "linux") === "linux";
10
11
 
@@ -12,7 +13,7 @@ describe("Provision Installer", () => {
12
13
  it.skipIf(!isLinux)(
13
14
  "should download and install a .deb package on Linux",
14
15
  async (context) => {
15
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
16
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
16
17
 
17
18
  // Install bat (a cat clone with syntax highlighting) using provision.installer
18
19
  const filePath = await testdriver.provision.installer({
@@ -30,7 +31,7 @@ describe("Provision Installer", () => {
30
31
  it.skipIf(!isLinux)(
31
32
  "should download a shell script and verify it exists",
32
33
  async (context) => {
33
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
34
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
34
35
 
35
36
  // Download a shell script (nvm installer)
36
37
  const filePath = await testdriver.provision.installer({
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { TestDriver } from "../lib/vitest/hooks.mjs";
3
+ import { getDefaults } from "./config.mjs";
3
4
 
4
5
  const isLinux = (process.env.TD_OS || "linux") === "linux";
5
6
 
@@ -7,7 +8,7 @@ describe("Launch VS Code on Linux", () => {
7
8
  it.skipIf(!isLinux)(
8
9
  "should launch VS Code on Debian/Ubuntu",
9
10
  async (context) => {
10
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
11
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
11
12
 
12
13
  // provision.vscode() automatically calls ready() and starts dashcam
13
14
  await testdriver.provision.vscode();
@@ -24,7 +25,7 @@ describe("Launch VS Code on Linux", () => {
24
25
  it.skipIf(!isLinux)(
25
26
  "should install and use a VS Code extension",
26
27
  async (context) => {
27
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP });
28
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
28
29
 
29
30
  // Launch VS Code with the Prettier extension installed
30
31
  await testdriver.provision.vscode({
@@ -7,6 +7,7 @@ import path, { dirname } from "path";
7
7
  import { fileURLToPath } from "url";
8
8
  import { describe, expect, it } from "vitest";
9
9
  import { TestDriver } from "../lib/vitest/hooks.mjs";
10
+ import { getDefaults } from "./config.mjs";
10
11
 
11
12
  /**
12
13
  * Perform login flow for SauceLabs demo app
@@ -33,7 +34,7 @@ const __dirname = dirname(__filename);
33
34
 
34
35
  describe("Match Image Test", () => {
35
36
  it.skip("should match shopping cart image and verify empty cart", async (context) => {
36
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
37
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
37
38
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
38
39
 
39
40
  //
@@ -5,12 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Assert Test", () => {
10
11
  it("should assert the testdriver login page shows", async (context) => {
11
- const testdriver = TestDriver(context, {
12
- ip: context.ip || process.env.TD_IP,
13
- });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
14
13
 
15
14
  // Assert the TestDriver.ai Sandbox login page is displayed
16
15
  const result = await testdriver.assert(
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Press Keys Test", () => {
10
11
  it("should create tabs and navigate using keyboard shortcuts", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  const signInButton = await testdriver.find(
@@ -20,23 +21,16 @@ describe("Press Keys Test", () => {
20
21
  await testdriver.pressKeys(["ctrl", "t"]);
21
22
 
22
23
  // Poll for "Learn more" to appear
23
- let learnMore = await testdriver.find("Learn more");
24
- for (let i = 0; i < 10; i++) {
25
- learnMore = await learnMore.find();
26
- if (learnMore.found()) break;
27
- await new Promise((resolve) => setTimeout(resolve, 500));
28
- }
24
+ let imagesLink = await testdriver.find("Images", {timeout: 5000});
25
+
26
+ expect(imagesLink.found()).toBeTruthy();
29
27
 
30
28
  // Open DevTools
31
29
  await testdriver.pressKeys(["ctrl", "shift", "i"]);
32
30
 
33
31
  // Poll for "Elements" to appear
34
- let elements = await testdriver.find("Elements");
35
- for (let i = 0; i < 10; i++) {
36
- elements = await elements.find();
37
- if (elements.found()) break;
38
- await new Promise((resolve) => setTimeout(resolve, 500));
39
- }
32
+ let elements = await testdriver.find("Elements", {timeout: 5000});
33
+ expect(elements.found()).toBeTruthy();
40
34
 
41
35
  // Open another tab and navigate
42
36
  await testdriver.pressKeys(["ctrl", "t"]);
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe.skip("Prompt Test", () => {
10
11
  it("should execute AI-driven prompts", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  //
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Scroll Keyboard Test", () => {
10
11
  it("should navigate to webhamster.com and scroll with keyboard", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  //
@@ -5,10 +5,11 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  describe("Scroll Until Image Test", () => {
10
11
  it.skip("should scroll until brown colored house image appears", async (context) => {
11
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
12
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
12
13
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
13
14
 
14
15
  //
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { describe, expect, it } from "vitest";
7
7
  import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
8
9
 
9
10
  /**
10
11
  * Perform login flow for SauceLabs demo app
@@ -27,7 +28,7 @@ async function performLogin(client, username = "standard_user") {
27
28
 
28
29
  describe("Scroll Until Text Test", () => {
29
30
  it('should scroll until "testdriver socks" appears', async (context) => {
30
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
31
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
31
32
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
32
33
 
33
34
  //
@@ -7,10 +7,11 @@
7
7
 
8
8
  import { describe, expect, it } from "vitest";
9
9
  import { TestDriver } from "../lib/vitest/hooks.mjs";
10
+ import { getDefaults } from "./config.mjs";
10
11
 
11
12
  describe("Scroll Test", () => {
12
13
  it("should navigate and scroll down the page", async (context) => {
13
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
14
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
14
15
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
15
16
 
16
17
  // Give Chrome a moment to fully render the UI
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { TestDriver } from "../lib/vitest/hooks.mjs";
3
+ import { getDefaults } from "./config.mjs";
3
4
 
4
5
  describe("Type Test", () => {
5
6
  it("should enter standard_user in username field", async (context) => {
6
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
7
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
7
8
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
8
9
 
9
10
  //
@@ -20,7 +21,7 @@ describe("Type Test", () => {
20
21
  });
21
22
 
22
23
  it("should show validation message when clicking Sign In without password", async (context) => {
23
- const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
24
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
24
25
  await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
25
26
 
26
27
  // First fill in username
@@ -11,6 +11,7 @@
11
11
 
12
12
  import { describe, it } from "vitest";
13
13
  import { TestDriver } from "../lib/vitest/hooks.mjs";
14
+ import { getDefaults } from "./config.mjs";
14
15
 
15
16
  const isLinux = (process.env.TD_OS || "linux") === "linux";
16
17
 
@@ -19,7 +20,7 @@ describe("Windows App Installation", () => {
19
20
  it.skipIf(isLinux)("should download, install, and launch GitButler on Windows", async (context) => {
20
21
  // Alternative approach using provision.installer helper
21
22
  const testdriver = TestDriver(context, {
22
- ip: context.ip || process.env.TD_IP,
23
+ ...getDefaults(context),
23
24
  os: 'windows'
24
25
  });
25
26