testdriverai 7.5.25 → 7.6.0-canary.0

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 (41) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +1 -0
  3. package/agent/index.js +5 -3
  4. package/agent/lib/config.js +3 -1
  5. package/agent/lib/sandbox.js +8 -6
  6. package/ai/agents/testdriver.md +0 -3
  7. package/ai/skills/testdriver-aws-setup/SKILL.md +1 -1
  8. package/ai/skills/testdriver-exec/SKILL.md +23 -40
  9. package/ai/skills/testdriver-test-writer/SKILL.md +0 -3
  10. package/ai/skills/testdriver-testdriver/SKILL.md +0 -3
  11. package/ai/skills/testdriver-wait/SKILL.md +50 -0
  12. package/ai/skills/testdriver-waiting-for-elements/SKILL.md +3 -1
  13. package/debugger/index.html +20 -3
  14. package/docs/docs.json +1 -1
  15. package/docs/images/content/parse/output.png +0 -0
  16. package/docs/v6/commands/exec.mdx +15 -21
  17. package/docs/v7/_drafts/agents.mdx +4 -13
  18. package/docs/v7/_drafts/commands/exec.mdx +15 -21
  19. package/docs/v7/aws-setup.mdx +1 -1
  20. package/docs/v7/exec.mdx +36 -64
  21. package/docs/v7/quickstart.mdx +1 -1
  22. package/examples/config.mjs +1 -1
  23. package/examples/no-provision.test.mjs +18 -11
  24. package/interfaces/cli/commands/init.js +2 -1
  25. package/interfaces/cli/lib/base.js +2 -10
  26. package/interfaces/vitest-plugin.mjs +23 -2
  27. package/lib/core/Dashcam.js +29 -2
  28. package/lib/init-project.js +68 -27
  29. package/lib/resolve-channel.js +36 -0
  30. package/lib/vitest/hooks.mjs +2 -1
  31. package/mcp-server/README.md +12 -2
  32. package/mcp-server/dist/codegen.js +1 -1
  33. package/mcp-server/dist/server.mjs +65 -5
  34. package/mcp-server/package-lock.json +12 -3
  35. package/mcp-server/package.json +2 -0
  36. package/mcp-server/src/codegen.ts +1 -1
  37. package/mcp-server/src/server.ts +58 -5
  38. package/package.json +8 -3
  39. package/sdk.d.ts +2 -2
  40. package/sdk.js +55 -17
  41. package/vitest.config.mjs +56 -12
package/CHANGELOG.md CHANGED
@@ -1,3 +1,89 @@
1
+ ## 7.6.0-canary.0 (2026-03-13)
2
+
3
+ ## 🔧 Maintenance
4
+
5
+ - Improve workflow reliability for package promotion between test, canary, and stable channels (358bb702)
6
+
7
+ ## 7.6.0-test.7 (2026-03-13)
8
+
9
+ ## 🔧 Maintenance
10
+
11
+ - Eliminate CI race conditions in promotion pipeline and streamline release workflows [CI] (9d83f886)
12
+ - Improve VNC URL display in CI environments [API] (9d83f886)
13
+ - Add dynamic channel resolution system for SDK configuration [SDK] (9d83f886)
14
+ - Update MCP server dependencies and enhance error handling [SDK] (9d83f886)
15
+
16
+ ## 7.6.0-test.6 (2026-03-13)
17
+
18
+ ## 🔧 Maintenance
19
+
20
+ - Improve CI/CD pipeline reliability by eliminating race conditions in release promotion workflows [c21f708d]
21
+ - Fix VNC URL display in continuous integration environment [API] [c21f708d]
22
+
23
+ ## 7.6.0-test.5 (2026-03-12)
24
+
25
+ ## 🔧 Maintenance
26
+
27
+ - Update SDK channel configuration [SDK] (274fff79)
28
+
29
+ ## 7.6.0-test.4 (2026-03-12)
30
+
31
+ ## 🔧 Maintenance
32
+
33
+ - Improve release workflow and deployment configuration [SDK] (eeea7649)
34
+ - Add enhanced web analytics tracking for better user insights [SDK] (eeea7649)
35
+
36
+ ## 7.6.0-test.3 (2026-03-12)
37
+
38
+ ## 🔧 Maintenance
39
+
40
+ - Improve release workflow automation and package promotion process [bb6be95]
41
+
42
+ ## 7.6.0-test.2 (2026-03-12)
43
+
44
+ ## 🔧 Maintenance
45
+
46
+ - Add automated publishing workflows for stable and canary releases [SDK] (2972b3be)
47
+ - Update CI workflows to improve testing efficiency and reliability [SDK] (2972b3be)
48
+
49
+ ## 7.6.0-test.1 (2026-03-12)
50
+
51
+ 🔧 Maintenance
52
+
53
+ - Improve CI/CD workflow reliability and testing coverage [SDK] (eb86a515)
54
+ - Update MCP server implementation for better stability [SDK] (eb86a515)
55
+
56
+ 📝 Documentation
57
+
58
+ - Add new visual documentation for content parsing functionality [SDK] (eb86a515)
59
+
60
+ ## 7.6.0-test.0 (2026-03-12)
61
+
62
+ ## ✨ Features
63
+
64
+ - Add stable/canary deployment channels with separate environments for production and development branches [API] (64542a8d)
65
+ - Add /version API endpoint returning deployment channel information [API] (64542a8d)
66
+ - Implement user limits and team member invitation controls [API] (6381290a)
67
+ - Add comprehensive GitHub Copilot skills and agent documentation for AI-assisted test development [SDK] (5ff15796)
68
+ - Add testimonials section with customer logos and quotes to marketing site [Web] (6381290a)
69
+ - Add contact and demo pages to marketing site [Web] (6381290a)
70
+ - Improve test environment management with better configuration and deployment workflows [Runner] (5c96e056)
71
+
72
+ ## 🐛 Bug Fixes
73
+
74
+ - Fix environment configuration and Tailscale connectivity issues [Runner] (5c96e056)
75
+ - Resolve Redis URL configuration problems across environments [API] (eca334be)
76
+ - Fix Vite API endpoint configuration for proper environment targeting [Web] (bf7fdf54)
77
+
78
+ ## 🔧 Maintenance
79
+
80
+ - Update pricing configuration and plans structure [API] (6381290a)
81
+ - Improve deployment workflows with promotion pipelines between test, canary, and stable branches [CI/CD] (1994d769)
82
+ - Add toast notification system for better user feedback [Web] (multiple commits)
83
+ - Rename TestAnalytics to TestMetrics for clarity [Web] (multiple commits)
84
+ - Remove outdated marketing articles and legal pages [Web] (6381290a)
85
+ - Update terms of service with new date [Web] (6381290a)
86
+
1
87
  ## 7.5.25 (2026-03-09)
2
88
 
3
89
  ## 🐛 Bug Fixes
package/README.md CHANGED
@@ -63,6 +63,7 @@ This will:
63
63
  - Create a project folder
64
64
  - Install dependencies (Vitest + TestDriver)
65
65
  - Set up your API key
66
+ - Configure MCP for your AI assistant (VS Code, Cursor, Claude Desktop, etc.)
66
67
  - Generate an example test
67
68
 
68
69
  ### Step 3: Run Your First Test
package/agent/index.js CHANGED
@@ -1918,12 +1918,12 @@ ${regression}
1918
1918
  const encodedData = Buffer.from(JSON.stringify(data)).toString("base64");
1919
1919
 
1920
1920
  // Build debugger URL — hosted on S3 (v7-vnc bucket)
1921
- const debuggerBase = process.env.TD_DEBUGGER_BASE_URL || "https://v7-vnc.s3.us-east-2.amazonaws.com";
1922
- const urlToOpen = `${debuggerBase}/index.html?data=${encodedData}`;
1921
+ const debuggerBase = process.env.TD_DEBUGGER_BASE_URL || "http://v7-vnc.s3.us-east-2.amazonaws.com";
1922
+ // URL-encode the base64 data to handle +, /, = characters safely
1923
+ const urlToOpen = `${debuggerBase}/index.html?data=${encodeURIComponent(encodedData)}`;
1923
1924
 
1924
1925
  // Check preview mode from CLI options (SDK passes it directly)
1925
1926
  const previewMode = (this.cliArgs.options && this.cliArgs.options.preview) || this.config.TD_PREVIEW || "browser";
1926
- console.log("[DEBUG renderSandbox] preview:", previewMode);
1927
1927
 
1928
1928
  if (previewMode === "ide") {
1929
1929
  // Send session to VS Code extension via HTTP
@@ -1944,6 +1944,8 @@ ${regression}
1944
1944
  const mapping = {
1945
1945
  "https://api.testdriver.ai": "https://console.testdriver.ai",
1946
1946
  "https://v6.testdriver.ai": "https://console.testdriver.ai",
1947
+ "https://api.canary.testdriver.ai": "https://console.canary.testdriver.ai",
1948
+ "https://api.test.testdriver.ai": "https://console.test.testdriver.ai",
1947
1949
  };
1948
1950
  if (mapping[apiRoot]) return mapping[apiRoot];
1949
1951
  // Local dev: API on localhost:1337 -> Web on localhost:3001
@@ -16,12 +16,14 @@ function parseValue(value) {
16
16
  return value;
17
17
  }
18
18
 
19
+ const channelConfig = require("../../lib/resolve-channel.js");
20
+
19
21
  // Factory function that creates a config instance
20
22
  const createConfig = (environment = {}) => {
21
23
  // Start with defaults
22
24
  const config = {
23
25
  TD_ANALYTICS: true,
24
- TD_API_ROOT: "https://v6.testdriver.ai",
26
+ TD_API_ROOT: channelConfig.channels[channelConfig.active],
25
27
  TD_API_KEY: null,
26
28
  TD_PROFILE: false,
27
29
  TD_RESOLUTION: [1366, 768],
@@ -511,7 +511,7 @@ const createSandbox = function (emitter, analytics, sessionInstance) {
511
511
  url = runnerVncUrl;
512
512
  logger.log(`Using runner-provided vncUrl: ${url}`);
513
513
  } else if (runnerIp && noVncPort) {
514
- url = `http://${runnerIp}:${noVncPort}/vnc_lite.html`;
514
+ url = `http://${runnerIp}:${noVncPort}/vnc_lite.html?token=V3b8wG9`;
515
515
  logger.log(`noVNC URL constructed from runner ip+port: ${url}`);
516
516
  } else if (runnerIp) {
517
517
  url = "http://" + runnerIp;
@@ -619,7 +619,7 @@ const createSandbox = function (emitter, analytics, sessionInstance) {
619
619
  }
620
620
 
621
621
  // Construct VNC URL — use port 8080 (nginx noVNC proxy) for Windows instances
622
- var directUrl = message.ip ? "http://" + message.ip + ":8080/vnc_lite.html" : undefined;
622
+ var directUrl = message.ip ? "http://" + message.ip + ":8080/vnc_lite.html?token=V3b8wG9" : undefined;
623
623
 
624
624
  return {
625
625
  success: true,
@@ -915,10 +915,12 @@ const createSandbox = function (emitter, analytics, sessionInstance) {
915
915
  }
916
916
 
917
917
  try {
918
- if (this._cmdChannel) this._cmdChannel.detach().catch(() => {});
919
- if (this._respChannel) this._respChannel.detach().catch(() => {});
920
- if (this._ctrlChannel) this._ctrlChannel.detach().catch(() => {});
921
- if (this._filesChannel) this._filesChannel.detach().catch(() => {});
918
+ await Promise.allSettled([
919
+ this._cmdChannel?.detach(),
920
+ this._respChannel?.detach(),
921
+ this._ctrlChannel?.detach(),
922
+ this._filesChannel?.detach(),
923
+ ].filter(Boolean));
922
924
  } catch (e) {
923
925
  /* ignore */
924
926
  }
@@ -578,9 +578,6 @@ await testdriver.pressKeys(["pagedown"]);
578
578
  ### Executing Code in Sandbox
579
579
 
580
580
  ```javascript
581
- // JavaScript
582
- const result = await testdriver.exec("js", "return document.title", 5000);
583
-
584
581
  // Shell (Linux)
585
582
  const output = await testdriver.exec("sh", "ls -la", 5000);
586
583
 
@@ -369,7 +369,7 @@ You can customize the AMI to include additional software or configurations:
369
369
  <Step title="Connect via RDP">
370
370
  Use the default credentials:
371
371
  - **Username**: `testdriver`
372
- - **Password**: `changemeABC123`
372
+ - **Password**: `wwv9uJ0sqlulbN3`
373
373
  </Step>
374
374
 
375
375
  <Step title="Change the Password">
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: testdriver:exec
3
- description: Execute code or shell commands in the sandbox
3
+ description: Execute shell or PowerShell commands in the sandbox
4
4
  ---
5
5
  <!-- Generated from exec.mdx. DO NOT EDIT. -->
6
6
 
7
7
  ## Overview
8
8
 
9
- Execute JavaScript code in the browser or PowerShell commands in the Windows sandbox environment.
9
+ Execute shell commands (Linux) or PowerShell commands (Windows) in the sandbox environment.
10
10
 
11
11
  ## Syntax
12
12
 
@@ -17,7 +17,7 @@ await testdriver.exec(language, code, timeout, silent)
17
17
  ## Parameters
18
18
 
19
19
  <ParamField path="language" type="string" required>
20
- Language to execute: `'js'` (JavaScript) or `'pwsh'` (PowerShell)
20
+ Language to execute: `'sh'` (Shell/Linux) or `'pwsh'` (PowerShell/Windows)
21
21
  </ParamField>
22
22
 
23
23
  <ParamField path="code" type="string" required>
@@ -36,57 +36,40 @@ await testdriver.exec(language, code, timeout, silent)
36
36
 
37
37
  `Promise<string>` - Command output
38
38
 
39
- ## JavaScript Execution
39
+ ## Shell Execution (Linux)
40
40
 
41
- Execute JavaScript in the browser context (Windows sandbox only).
41
+ Execute shell commands in the Linux sandbox.
42
42
 
43
- ### DOM Manipulation
43
+ ### Basic Commands
44
44
 
45
45
  ```javascript
46
- // Click an element via JavaScript
47
- await testdriver.exec('js', `
48
- document.querySelector('#submit-button').click();
49
- `, 5000);
46
+ // List files
47
+ const files = await testdriver.exec('sh', 'ls -la', 5000);
50
48
 
51
- // Fill a form
52
- await testdriver.exec('js', `
53
- document.querySelector('#username').value = 'testuser';
54
- document.querySelector('#password').value = 'password123';
55
- document.querySelector('#login-form').submit();
56
- `, 5000);
49
+ // Check current directory
50
+ const pwd = await testdriver.exec('sh', 'pwd', 5000);
57
51
 
58
- // Scroll to element
59
- await testdriver.exec('js', `
60
- document.querySelector('#footer').scrollIntoView();
61
- `, 5000);
52
+ // Run a script
53
+ await testdriver.exec('sh', './setup.sh', 60000);
62
54
  ```
63
55
 
64
- ### Reading Page Data
56
+ ### File Operations
65
57
 
66
58
  ```javascript
67
- // Get page title
68
- const title = await testdriver.exec('js', 'document.title', 5000);
69
- console.log('Page title:', title);
70
-
71
- // Get all links
72
- const links = await testdriver.exec('js', `
73
- Array.from(document.querySelectorAll('a'))
74
- .map(a => a.href)
75
- .join('\\n')
76
- `, 5000);
59
+ // Create a file
60
+ await testdriver.exec('sh', 'echo "Hello World" > test.txt', 5000);
77
61
 
78
- // Check if element exists
79
- const exists = await testdriver.exec('js', `
80
- document.querySelector('.error-message') !== null
81
- `, 5000);
62
+ // Read a file
63
+ const content = await testdriver.exec('sh', 'cat test.txt', 5000);
82
64
 
83
- // Get element text
84
- const text = await testdriver.exec('js', `
85
- document.querySelector('.notification').textContent
86
- `, 5000);
65
+ // Copy files
66
+ await testdriver.exec('sh', 'cp source.txt dest.txt', 5000);
67
+
68
+ // Delete files
69
+ await testdriver.exec('sh', 'rm test.txt', 5000);
87
70
  ```
88
71
 
89
- ## PowerShell Execution
72
+ ## PowerShell Execution (Windows)
90
73
 
91
74
  Execute PowerShell commands in the Windows sandbox.
92
75
 
@@ -399,9 +399,6 @@ await testdriver.scrollUntilImage("Product image at bottom");
399
399
  ### Executing Code in Sandbox
400
400
 
401
401
  ```javascript
402
- // JavaScript
403
- const result = await testdriver.exec("js", "return document.title", 5000);
404
-
405
402
  // Shell (Linux)
406
403
  const output = await testdriver.exec("sh", "ls -la", 5000);
407
404
 
@@ -568,9 +568,6 @@ await testdriver.pressKeys(["pagedown"]);
568
568
  ### Executing Code in Sandbox
569
569
 
570
570
  ```javascript
571
- // JavaScript
572
- const result = await testdriver.exec("js", "return document.title", 5000);
573
-
574
571
  // Shell (Linux)
575
572
  const output = await testdriver.exec("sh", "ls -la", 5000);
576
573
 
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: testdriver:wait
3
+ description: Pause the execution of the script for a specified duration.
4
+ ---
5
+ <!-- Generated from wait.mdx. DO NOT EDIT. -->
6
+
7
+ ## Description
8
+
9
+ The `wait` method pauses test execution for a specified number of milliseconds before continuing. This is useful for adding delays between actions, waiting for animations to complete, or pausing for state changes to settle.
10
+
11
+ ## Syntax
12
+
13
+ ```javascript
14
+ await testdriver.wait(timeout);
15
+ ```
16
+
17
+ ## Arguments
18
+
19
+ | Argument | Type | Default | Description |
20
+ | --------- | -------- | ------- | ------------------------------------- |
21
+ | `timeout` | `number` | `3000` | The duration in milliseconds to wait. |
22
+
23
+ ## Examples
24
+
25
+ ```javascript
26
+ // Wait 2 seconds for an animation to complete
27
+ await testdriver.find('submit button').click();
28
+ await testdriver.wait(2000);
29
+
30
+ // Wait 5 seconds
31
+ await testdriver.wait(5000);
32
+
33
+ // Wait with default timeout (3 seconds)
34
+ await testdriver.wait();
35
+ ```
36
+
37
+ ## Best Practices
38
+
39
+ - **Use for simple delays** — waiting for animations, transitions, or state changes after an action.
40
+ - **Avoid for element waiting** — if you're waiting for a specific element to appear, use `find()` with a `timeout` option instead:
41
+ ```javascript
42
+ // ✅ Better for waiting for elements
43
+ const element = await testdriver.find('success message', { timeout: 30000 });
44
+
45
+ // ❌ Don't do this for element waiting
46
+ await testdriver.wait(5000);
47
+ const element = await testdriver.find('success message');
48
+ ```
49
+ - Avoid excessively long timeouts to keep tests efficient.
50
+ - Use sparingly — TestDriver's [redraw detection](/v7/waiting-for-elements) automatically waits for screen and network stability after each action.
@@ -85,4 +85,6 @@ await testdriver.find('next page button').click();
85
85
  await testdriver.wait(1000);
86
86
  ```
87
87
 
88
- For waiting for specific **elements** to appear, prefer `find()` with a `timeout` option. Use `wait()` only for simple time-based pauses.
88
+ <Note>
89
+ For waiting for specific **elements** to appear, prefer `find()` with a `timeout` option. Use `wait()` only for simple time-based pauses.
90
+ </Note>
@@ -354,8 +354,21 @@
354
354
  console.error("Error parsing data:", e);
355
355
  }
356
356
  }
357
+ // Demo mode: use mock data if no data param provided (for local dev)
357
358
  if (!parsedData || !parsedData.url) {
358
- alert("Missing or invalid data parameter.");
359
+ const isLocalDev = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1";
360
+ if (isLocalDev) {
361
+ console.log("[Debugger] No data param — using demo mode");
362
+ parsedData = {
363
+ url: "about:blank",
364
+ resolution: [1366, 768],
365
+ testFile: "demo-test.mjs",
366
+ os: "linux",
367
+ token: null,
368
+ };
369
+ } else {
370
+ alert("Missing or invalid data parameter.");
371
+ }
359
372
  }
360
373
 
361
374
  // Elements
@@ -402,9 +415,13 @@
402
415
  : "TestDriver";
403
416
  document.title = `${testFileName} - Debugger`;
404
417
 
405
- // Embed the VNC URL in the iframe
418
+ // Embed the VNC URL in the iframe with token
406
419
  iframe.style.display = "block";
407
- iframe.src = parsedData.url;
420
+ const vncUrl = new URL(parsedData.url);
421
+ if (parsedData.token) {
422
+ vncUrl.searchParams.set("token", parsedData.token);
423
+ }
424
+ iframe.src = vncUrl.toString();
408
425
 
409
426
  // Hide loading screen once iframe loads
410
427
  iframe.addEventListener("load", () => {
package/docs/docs.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://mintlify.com/docs.json",
3
- "theme": "aspen",
3
+ "theme": "willow",
4
4
  "name": "TestDriver",
5
5
  "colors": {
6
6
  "primary": "#b3d334",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "exec"
3
3
  sidebarTitle: "exec"
4
- description: "Execute custom shell or Node.js scripts within your tests."
4
+ description: "Execute custom shell or PowerShell scripts within your tests."
5
5
  icon: "code"
6
6
  mode: "wide"
7
7
  ---
@@ -14,49 +14,43 @@ import Example from "/snippets/tests/exec-shell-yaml.mdx";
14
14
 
15
15
  ## Description
16
16
 
17
- The `exec` command allows you to execute custom Node.js scripts within your TestDriver tests. This is useful for tasks like generating dynamic data, interacting with APIs, or performing custom logic during a test. The output of the script can be stored in a variable for use in subsequent steps. It's important to note that the output from `exec` must be a `string`.
17
+ The `exec` command allows you to execute shell commands (Linux) or PowerShell commands (Windows) within your TestDriver tests. This is useful for launching applications, file operations, or performing system commands during a test.
18
18
 
19
19
  ## Arguments
20
20
 
21
21
  | Argument | Type | Description |
22
22
  | :------: | :------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
- | `lang` | `string` | The language of the script to execute. Supported values are `pwsh` and `js`. |
23
+ | `lang` | `string` | The language of the script to execute. Supported values are `sh` (Shell/Linux) or `pwsh` (PowerShell/Windows). |
24
24
  | `output` | `string` | The variable name to store the result of the script. This variable can be accessed as `${OUTPUT.<var>}` in future steps. |
25
- | `code` | `string` | The script to execute on Windows systems. For `js`, the script must define the output as `result`. |
25
+ | `code` | `string` | The script to execute. |
26
26
  | `silent` | `string` | Defaults to `false`. The command will print the output of the script. This is useful for suppressing unnecessary or private output in the test logs and it's useful for debugging. |
27
27
 
28
28
  ## Example usage
29
29
 
30
- This example demonstrates how to use the `exec` command to generate a TOTP (Time-based One-Time Password) using the `totp-generator` library.
30
+ This example demonstrates how to use the `exec` command to launch a calculator application.
31
31
 
32
- ```yaml otp-generator.yaml
32
+ ```yaml calculator.yaml
33
33
  version: 6.0.0
34
34
  steps:
35
35
  - commands:
36
36
  - command: exec
37
37
  lang: pwsh
38
38
  code: |
39
- npm install totp-generator
40
- - command: exec
41
- lang: js
42
- output: totp
43
- code: |
44
- const { TOTP } = require("totp-generator");
45
- let otp = TOTP.generate("JBSWY3DPEB3W64TMMQQQ").otp;
46
- console.log(otp);
47
- result = otp;
48
- - command: type
49
- text: ${OUTPUT.totp}
39
+ start /B calc.exe
40
+ timeout /t 5
41
+ - command: wait-for-text
42
+ text: "calculator"
43
+ timeout: 30000
50
44
  ```
51
45
 
52
46
  ## Additional details
53
47
 
54
- - Supported `lang` values are `js` or `pwsh`:
55
- - `js` code is executed in a Node.js [VM](https://nodejs.org/api/vm.html) internally on the host machine (for example the machine where your CI/CD runs, or your computer if using the local agent).
56
- - `pwsh` code is executed in the shell on target runner (which can be the cloud runner, local sandbox, or local machine, depending on where you run your tests).
48
+ - Supported `lang` values are `sh` or `pwsh`:
49
+ - `sh` code is executed in the shell on Linux sandboxes.
50
+ - `pwsh` code is executed in PowerShell on Windows sandboxes.
57
51
  - **Note:** You can also use `pwsh` in [lifecycle](/guide/lifecycle) scripts to install npm packages if you need them.
58
52
  - Otherwise, the `pwsh` code can be used within test steps to launch applications or perform simple commands (like writing text to a file on the machine to perform a simple file upload).
59
- - The `output`argument is assigned automatically by setting `result = somestringvalue` in the script you run.
53
+ - The `output` argument captures stdout from your script.
60
54
 
61
55
  ## Protips
62
56
 
@@ -372,20 +372,11 @@ await testdriver.scrollUntilText('Footer', 'down', 5000);
372
372
 
373
373
  ### exec(language, code, timeout, silent) - Execute Code
374
374
 
375
- Execute JavaScript or PowerShell in the sandbox.
375
+ Execute shell or PowerShell in the sandbox.
376
376
 
377
377
  ```javascript
378
- // JavaScript execution (in browser)
379
- const title = await testdriver.exec('js', 'document.title', 5000);
380
-
381
- await testdriver.exec('js', `
382
- document.querySelector('#username').value = 'testuser';
383
- `, 5000);
384
-
385
- // Get element text
386
- const text = await testdriver.exec('js', `
387
- document.querySelector('.notification').textContent
388
- `, 5000);
378
+ // Shell execution (Linux sandbox)
379
+ const output = await testdriver.exec('sh', 'ls -la', 5000);
389
380
 
390
381
  // PowerShell execution (Windows sandbox)
391
382
  await testdriver.exec('pwsh', 'npm install -g http-server', 30000);
@@ -843,7 +834,7 @@ Using explicit sandboxes provides:
843
834
  | `assert(text)` | Verify state | `await testdriver.assert('button is visible')` |
844
835
  | `pressKeys(keys)` | Keyboard shortcuts | `await testdriver.pressKeys(['ctrl', 'c'])` |
845
836
  | `scroll(dir, amt)` | Scroll page | `await testdriver.scroll('down', 500)` |
846
- | `exec(lang, code)` | Execute code | `await testdriver.exec('js', 'document.title', 5000)` |
837
+ | `exec(lang, code)` | Execute code | `await testdriver.exec('sh', 'ls -la', 5000)` |
847
838
  | `connect(opts)` | Connect to sandbox | `await testdriver.connect({ sandboxId: 'i-123' })` |
848
839
  | `disconnect()` | Close connection | `await testdriver.disconnect()` |
849
840
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "exec"
3
3
  sidebarTitle: "exec"
4
- description: "Execute custom shell or Node.js scripts within your tests."
4
+ description: "Execute custom shell or PowerShell scripts within your tests."
5
5
  icon: "code"
6
6
  mode: "wide"
7
7
  ---
@@ -14,49 +14,43 @@ import Example from "/snippets/tests/exec-shell-yaml.mdx";
14
14
 
15
15
  ## Description
16
16
 
17
- The `exec` command allows you to execute custom Node.js scripts within your TestDriver tests. This is useful for tasks like generating dynamic data, interacting with APIs, or performing custom logic during a test. The output of the script can be stored in a variable for use in subsequent steps. It's important to note that the output from `exec` must be a `string`.
17
+ The `exec` command allows you to execute shell commands (Linux) or PowerShell commands (Windows) within your TestDriver tests. This is useful for launching applications, file operations, or performing system commands during a test.
18
18
 
19
19
  ## Arguments
20
20
 
21
21
  | Argument | Type | Description |
22
22
  | :------: | :------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
- | `lang` | `string` | The language of the script to execute. Supported values are `pwsh` and `js`. |
23
+ | `lang` | `string` | The language of the script to execute. Supported values are `sh` (Shell/Linux) or `pwsh` (PowerShell/Windows). |
24
24
  | `output` | `string` | The variable name to store the result of the script. This variable can be accessed as `${OUTPUT.<var>}` in future steps. |
25
- | `code` | `string` | The script to execute on Windows systems. For `js`, the script must define the output as `result`. |
25
+ | `code` | `string` | The script to execute. |
26
26
  | `silent` | `string` | Defaults to `false`. The command will print the output of the script. This is useful for suppressing unnecessary or private output in the test logs and it's useful for debugging. |
27
27
 
28
28
  ## Example usage
29
29
 
30
- This example demonstrates how to use the `exec` command to generate a TOTP (Time-based One-Time Password) using the `totp-generator` library.
30
+ This example demonstrates how to use the `exec` command to launch a calculator application.
31
31
 
32
- ```yaml otp-generator.yaml
32
+ ```yaml calculator.yaml
33
33
  version: 6.0.0
34
34
  steps:
35
35
  - commands:
36
36
  - command: exec
37
37
  lang: pwsh
38
38
  code: |
39
- npm install totp-generator
40
- - command: exec
41
- lang: js
42
- output: totp
43
- code: |
44
- const { TOTP } = require("totp-generator");
45
- let otp = TOTP.generate("JBSWY3DPEB3W64TMMQQQ").otp;
46
- console.log(otp);
47
- result = otp;
48
- - command: type
49
- text: ${OUTPUT.totp}
39
+ start /B calc.exe
40
+ timeout /t 5
41
+ - command: wait-for-text
42
+ text: "calculator"
43
+ timeout: 30000
50
44
  ```
51
45
 
52
46
  ## Additional details
53
47
 
54
- - Supported `lang` values are `js` or `pwsh`:
55
- - `js` code is executed in a Node.js [VM](https://nodejs.org/api/vm.html) internally on the host machine (for example the machine where your CI/CD runs, or your computer if using the local agent).
56
- - `pwsh` code is executed in the shell on target runner (which can be the cloud runner, local sandbox, or local machine, depending on where you run your tests).
48
+ - Supported `lang` values are `sh` or `pwsh`:
49
+ - `sh` code is executed in the shell on Linux sandboxes.
50
+ - `pwsh` code is executed in PowerShell on Windows sandboxes.
57
51
  - **Note:** You can also use `pwsh` in [lifecycle](/guide/lifecycle) scripts to install npm packages if you need them.
58
52
  - Otherwise, the `pwsh` code can be used within test steps to launch applications or perform simple commands (like writing text to a file on the machine to perform a simple file upload).
59
- - The `output`argument is assigned automatically by setting `result = somestringvalue` in the script you run.
53
+ - The `output` argument captures stdout from your script.
60
54
 
61
55
  ## Protips
62
56
 
@@ -370,7 +370,7 @@ You can customize the AMI to include additional software or configurations:
370
370
  <Step title="Connect via RDP">
371
371
  Use the default credentials:
372
372
  - **Username**: `testdriver`
373
- - **Password**: `changemeABC123`
373
+ - **Password**: `wwv9uJ0sqlulbN3`
374
374
  </Step>
375
375
 
376
376
  <Step title="Change the Password">