testdriverai 7.3.11 → 7.3.13

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 (133) hide show
  1. package/.github/skills/testdriver:ai/SKILL.md +204 -0
  2. package/.github/skills/testdriver:assert/SKILL.md +284 -0
  3. package/.github/skills/testdriver:aws-setup/SKILL.md +515 -0
  4. package/.github/skills/testdriver:caching/SKILL.md +124 -0
  5. package/.github/skills/testdriver:captcha/SKILL.md +159 -0
  6. package/.github/skills/testdriver:ci-cd/SKILL.md +602 -0
  7. package/.github/skills/testdriver:click/SKILL.md +286 -0
  8. package/.github/skills/testdriver:client/SKILL.md +339 -0
  9. package/.github/skills/testdriver:cloud/SKILL.md +119 -0
  10. package/.github/skills/testdriver:customizing-devices/SKILL.md +153 -0
  11. package/.github/skills/testdriver:dashcam/SKILL.md +418 -0
  12. package/.github/skills/testdriver:debugging-with-screenshots/SKILL.md +271 -0
  13. package/.github/skills/testdriver:device-config/SKILL.md +317 -0
  14. package/.github/skills/testdriver:double-click/SKILL.md +102 -0
  15. package/.github/skills/testdriver:elements/SKILL.md +605 -0
  16. package/.github/skills/testdriver:enterprise/SKILL.md +114 -0
  17. package/.github/skills/testdriver:examples/SKILL.md +7 -0
  18. package/.github/skills/testdriver:exec/SKILL.md +345 -0
  19. package/.github/skills/testdriver:find/SKILL.md +721 -0
  20. package/.github/skills/testdriver:focus-application/SKILL.md +293 -0
  21. package/.github/skills/testdriver:generating-tests/SKILL.md +36 -0
  22. package/.github/skills/testdriver:hover/SKILL.md +278 -0
  23. package/.github/skills/testdriver:locating-elements/SKILL.md +71 -0
  24. package/.github/skills/testdriver:making-assertions/SKILL.md +32 -0
  25. package/.github/skills/testdriver:mcp-workflow/SKILL.md +410 -0
  26. package/.github/skills/testdriver:mouse-down/SKILL.md +161 -0
  27. package/.github/skills/testdriver:mouse-up/SKILL.md +164 -0
  28. package/.github/skills/testdriver:performing-actions/SKILL.md +51 -0
  29. package/.github/skills/testdriver:press-keys/SKILL.md +348 -0
  30. package/.github/skills/testdriver:quickstart/SKILL.md +161 -0
  31. package/.github/skills/testdriver:reusable-code/SKILL.md +240 -0
  32. package/.github/skills/testdriver:right-click/SKILL.md +123 -0
  33. package/.github/skills/testdriver:running-tests/SKILL.md +181 -0
  34. package/.github/skills/testdriver:screenshot/SKILL.md +167 -0
  35. package/.github/skills/testdriver:scroll/SKILL.md +299 -0
  36. package/.github/skills/testdriver:secrets/SKILL.md +115 -0
  37. package/.github/skills/testdriver:self-hosted/SKILL.md +65 -0
  38. package/.github/skills/testdriver:test-writer/SKILL.md +451 -0
  39. package/.github/skills/testdriver:testdriver/SKILL.md +523 -0
  40. package/.github/skills/testdriver:testdriver-mechanic/SKILL.md +165 -0
  41. package/.github/skills/testdriver:type/SKILL.md +357 -0
  42. package/.github/skills/testdriver:variables/SKILL.md +111 -0
  43. package/.github/skills/testdriver:waiting-for-elements/SKILL.md +66 -0
  44. package/.github/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
  45. package/.github/workflows/acceptance-windows-scheduled.yaml +6 -1
  46. package/.github/workflows/acceptance.yaml +0 -36
  47. package/.github/workflows/update-examples.yaml +53 -0
  48. package/CHANGELOG.md +8 -0
  49. package/agent/events.js +1 -0
  50. package/agent/index.js +8 -0
  51. package/agent/lib/commands.js +48 -29
  52. package/agent/lib/redraw.js +3 -1
  53. package/agent/lib/sandbox.js +166 -14
  54. package/agent/lib/sdk.js +142 -3
  55. package/agent/lib/system.js +4 -6
  56. package/ai/skills/testdriver:ai/SKILL.md +204 -0
  57. package/ai/skills/testdriver:assert/SKILL.md +315 -0
  58. package/ai/skills/testdriver:aws-setup/SKILL.md +448 -0
  59. package/ai/skills/testdriver:caching/SKILL.md +124 -0
  60. package/ai/skills/testdriver:captcha/SKILL.md +159 -0
  61. package/ai/skills/testdriver:ci-cd/SKILL.md +602 -0
  62. package/ai/skills/testdriver:click/SKILL.md +286 -0
  63. package/ai/skills/testdriver:client/SKILL.md +372 -0
  64. package/ai/skills/testdriver:cloud/SKILL.md +119 -0
  65. package/ai/skills/testdriver:customizing-devices/SKILL.md +153 -0
  66. package/ai/skills/testdriver:dashcam/SKILL.md +418 -0
  67. package/ai/skills/testdriver:debugging-with-screenshots/SKILL.md +401 -0
  68. package/ai/skills/testdriver:device-config/SKILL.md +317 -0
  69. package/ai/skills/testdriver:double-click/SKILL.md +102 -0
  70. package/ai/skills/testdriver:elements/SKILL.md +605 -0
  71. package/ai/skills/testdriver:enterprise/SKILL.md +114 -0
  72. package/ai/skills/testdriver:examples/SKILL.md +7 -0
  73. package/ai/skills/testdriver:exec/SKILL.md +345 -0
  74. package/ai/skills/testdriver:find/SKILL.md +745 -0
  75. package/ai/skills/testdriver:focus-application/SKILL.md +293 -0
  76. package/ai/skills/testdriver:generating-tests/SKILL.md +36 -0
  77. package/ai/skills/testdriver:hover/SKILL.md +278 -0
  78. package/ai/skills/testdriver:locating-elements/SKILL.md +71 -0
  79. package/ai/skills/testdriver:making-assertions/SKILL.md +32 -0
  80. package/ai/skills/testdriver:mcp-workflow/SKILL.md +410 -0
  81. package/ai/skills/testdriver:mouse-down/SKILL.md +161 -0
  82. package/ai/skills/testdriver:mouse-up/SKILL.md +164 -0
  83. package/ai/skills/testdriver:ocr/SKILL.md +235 -0
  84. package/ai/skills/testdriver:performing-actions/SKILL.md +51 -0
  85. package/ai/skills/testdriver:press-keys/SKILL.md +348 -0
  86. package/ai/skills/testdriver:quickstart/SKILL.md +146 -0
  87. package/ai/skills/testdriver:reusable-code/SKILL.md +240 -0
  88. package/ai/skills/testdriver:right-click/SKILL.md +123 -0
  89. package/ai/skills/testdriver:running-tests/SKILL.md +185 -0
  90. package/ai/skills/testdriver:screenshot/SKILL.md +248 -0
  91. package/ai/skills/testdriver:scroll/SKILL.md +335 -0
  92. package/ai/skills/testdriver:secrets/SKILL.md +115 -0
  93. package/ai/skills/testdriver:self-hosted/SKILL.md +65 -0
  94. package/ai/skills/testdriver:test-writer/SKILL.md +451 -0
  95. package/ai/skills/testdriver:testdriver/SKILL.md +631 -0
  96. package/ai/skills/testdriver:testdriver-mechanic/SKILL.md +165 -0
  97. package/ai/skills/testdriver:type/SKILL.md +357 -0
  98. package/ai/skills/testdriver:variables/SKILL.md +111 -0
  99. package/ai/skills/testdriver:waiting-for-elements/SKILL.md +66 -0
  100. package/ai/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
  101. package/debugger/index.html +12 -2
  102. package/docs/v7/examples/scroll-keyboard.mdx +1 -1
  103. package/docs/v7/find.mdx +1 -0
  104. package/examples/config.mjs +1 -1
  105. package/examples/findall-coffee-icons.test.mjs +42 -0
  106. package/examples/flake-diffthreshold-001.test.mjs +9 -0
  107. package/examples/flake-diffthreshold-01.test.mjs +9 -0
  108. package/examples/flake-diffthreshold-05.test.mjs +9 -0
  109. package/examples/{z_flake-noredraw-cache.test.mjs → flake-noredraw-cache.test.mjs} +2 -2
  110. package/examples/{z_flake-noredraw-nocache.test.mjs → flake-noredraw-nocache.test.mjs} +2 -2
  111. package/examples/{z_flake-redraw-cache.test.mjs → flake-redraw-cache.test.mjs} +2 -2
  112. package/examples/{z_flake-redraw-nocache.test.mjs → flake-redraw-nocache.test.mjs} +2 -2
  113. package/examples/flake-rocket-match.test.mjs +30 -0
  114. package/examples/{z_flake-shared.mjs → flake-shared.mjs} +2 -2
  115. package/examples/parse.test.mjs +19 -0
  116. package/examples/scroll-keyboard.test.mjs +1 -1
  117. package/interfaces/cli/lib/base.js +6 -0
  118. package/interfaces/logger.js +51 -13
  119. package/interfaces/vitest-plugin.mjs +137 -0
  120. package/lib/core/index.d.ts +22 -0
  121. package/lib/init-project.js +105 -6
  122. package/lib/vitest/hooks.mjs +2 -5
  123. package/lib/vitest/setup-disable-defender.mjs +52 -0
  124. package/package.json +2 -1
  125. package/sdk-log-formatter.js +90 -0
  126. package/sdk.d.ts +88 -51
  127. package/sdk.js +128 -21
  128. package/setup/aws/disable-defender.sh +42 -0
  129. package/vitest.config.mjs +1 -3
  130. package/examples/z_flake-diffthreshold-001.test.mjs +0 -9
  131. package/examples/z_flake-diffthreshold-01.test.mjs +0 -9
  132. package/examples/z_flake-diffthreshold-05.test.mjs +0 -9
  133. /package/{examples → manual}/captcha-api.test.mjs +0 -0
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: testdriver:cloud
3
+ description: The fastest way to get started with TestDriver. Just set your API key and start testing.
4
+ ---
5
+ <!-- Generated from cloud.mdx. DO NOT EDIT. -->
6
+
7
+ Cloud pricing is based on **device-seconds**: the amount of time your tests run on **our infrastructure**.
8
+
9
+ - **Zero Setup** — Start testing immediately. No DevOps required.
10
+ - **Free Tier** — Get started with a limited preview at no cost.
11
+ - **Pay As You Go** — Only pay for the device-seconds you use.
12
+
13
+ ## Get Started
14
+ Cloud is the default when you follow the Quickstart guide.
15
+ <Card
16
+ title="Try the Quickstart"
17
+ icon="play"
18
+ href="/v7/quickstart"
19
+ >
20
+ Set your API key and start testing in minutes.
21
+ </Card>
22
+
23
+ ## Parallel Testing Limits
24
+
25
+ Your account has a set number of **license slots** that determine how many devices can run simultaneously. You can view your available slots in the [TestDriver Dashboard](https://console.testdriver.ai).
26
+
27
+ <Info>
28
+ **When is a slot in use?** A license slot is occupied when a test client is connected. As soon as your device is destroyed the slot becomes available immediately.
29
+ </Info>
30
+
31
+ ## Avoiding Slot Conflicts
32
+
33
+ To prevent tests from failing due to exceeding your license slot limit, we recommend two key configurations:
34
+
35
+ <AccordionGroup>
36
+ <Accordion title="Set Maximum Concurrency in Vitest">
37
+ Limit concurrent tests to match your available license slots:
38
+
39
+ ```javascript vitest.config.mjs
40
+ import { defineConfig } from 'vitest/config';
41
+ import { TestDriver } from 'testdriverai/vitest';
42
+
43
+ export default defineConfig({
44
+ test: {
45
+ testTimeout: 900000,
46
+ hookTimeout: 900000,
47
+ maxConcurrency: 5, // Set to your license slot limit
48
+ reporters: ['default', TestDriver()],
49
+ setupFiles: ['testdriverai/vitest/setup'],
50
+ },
51
+ });
52
+ ```
53
+
54
+ <Tip>
55
+ Check your slot count at [console.testdriver.ai](https://console.testdriver.ai) and set `maxConcurrency` to that number or lower.
56
+ </Tip>
57
+ </Accordion>
58
+
59
+ <Accordion title="Use GitHub Concurrency Keys">
60
+ Prevent multiple workflow runs from competing for the same slots by using [GitHub's concurrency controls](https://docs.github.com/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs):
61
+
62
+ ```yaml .github/workflows/test.yml
63
+ name: Tests
64
+
65
+ on:
66
+ push:
67
+ branches: [main]
68
+ pull_request:
69
+
70
+ # Prevent concurrent runs from competing for license slots
71
+ concurrency:
72
+ group: ${{ github.workflow }}-${{ github.ref }}
73
+ cancel-in-progress: true
74
+
75
+ jobs:
76
+ test:
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - uses: actions/checkout@v4
80
+
81
+ - name: Setup Node.js
82
+ uses: actions/setup-node@v4
83
+ with:
84
+ node-version: '20'
85
+
86
+ - name: Install dependencies
87
+ run: npm install
88
+
89
+ - name: Run tests
90
+ run: vitest run
91
+ env:
92
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
93
+ ```
94
+
95
+ The `concurrency` block ensures:
96
+ - Only one workflow run per branch runs at a time
97
+ - New pushes cancel in-progress runs on the same branch
98
+ - Different branches/PRs can run in parallel (up to your slot limit)
99
+ </Accordion>
100
+ </AccordionGroup>
101
+
102
+ ## When to Consider Self-Hosted
103
+
104
+ Cloud is perfect for getting started and for teams that want zero infrastructure management. However, you might consider [Self-Hosted](/v7/self-hosted) if you:
105
+
106
+ - Want to escape per-second billing with a flat license fee
107
+ - Require greater concurrency than offered in Cloud plans
108
+ - Need full control over your infrastructure and privacy
109
+ - Want to use your own AI API keys
110
+ - Require custom hardware configurations
111
+ - Have high test volumes that make self-hosting more economical
112
+
113
+ <Card
114
+ title="Explore Self-Hosted"
115
+ icon="server"
116
+ href="/v7/self-hosted"
117
+ >
118
+ Learn about self-hosting for unlimited test execution at a flat rate.
119
+ </Card>
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: testdriver:customizing-devices
3
+ description: Configure TestDriver sandbox options and environment settings
4
+ ---
5
+ <!-- Generated from customizing-devices.mdx. DO NOT EDIT. -->
6
+
7
+ ## TestDriver Options
8
+
9
+ Configure TestDriver behavior with options passed to the `TestDriver()` function:
10
+
11
+ ```javascript
12
+ const testdriver = TestDriver(context, {
13
+ reconnect: false,
14
+ });
15
+ ```
16
+
17
+ ### Preview Mode
18
+
19
+ Control how test execution is visualized. The `preview` option determines where the live debugger view opens:
20
+
21
+ ```javascript
22
+ const testdriver = TestDriver(context, {
23
+ preview: "browser", // Opens in default browser (default)
24
+ });
25
+ ```
26
+
27
+ | Value | Description |
28
+ |-------|-------------|
29
+ | `"browser"` | Opens debugger in default browser (default) |
30
+ | `"ide"` | Opens preview in IDE panel (VSCode, Cursor - requires TestDriver extension) |
31
+ | `"none"` | Headless mode, no visual preview |
32
+
33
+ **IDE Preview**
34
+
35
+ For the best development experience, use `preview: "ide"` with the TestDriver extension for VSCode or Cursor:
36
+
37
+ ```javascript
38
+ const testdriver = TestDriver(context, {
39
+ preview: "ide", // Opens preview in IDE panel
40
+ });
41
+ ```
42
+
43
+ **Headless Mode**
44
+
45
+ Run tests without any visual preview. Useful for CI/CD pipelines:
46
+
47
+ ```javascript
48
+ const testdriver = TestDriver(context, {
49
+ preview: "none", // No visual preview (headless)
50
+ });
51
+ ```
52
+
53
+ <Note>
54
+ The legacy `headless: true` option still works for backward compatibility and maps to `preview: "none"`.
55
+ </Note>
56
+
57
+ ### IP Target
58
+
59
+ If self-hosting TestDriver, use `ip` to specify the device IP. See [Self-Hosting TestDriver](../self-hosting.md) for details.
60
+
61
+ ```javascript
62
+ const testdriver = TestDriver(context, {
63
+ ip: "203.0.113.42", // Your allowlisted IP
64
+ });
65
+ ```
66
+
67
+ ### Operating System
68
+
69
+ Set the `os` property to run tests on a specific operating system. Available options are `linux` (default) and `windows`.
70
+
71
+ ```javascript
72
+ const testdriver = TestDriver(context, {
73
+ os: "windows", // Run on Windows sandbox
74
+ });
75
+ ```
76
+
77
+ #### Using Environment Variables
78
+
79
+ You can make the operating system configurable via environment variables. This requires adding code to read from `process.env` in your test:
80
+
81
+ ```javascript
82
+ const testdriver = TestDriver(context, {
83
+ os: process.env.TD_OS || "linux", // Read from env, default to Linux
84
+ });
85
+ ```
86
+
87
+ Then pass the variable when running tests:
88
+
89
+ ```bash
90
+ # Run tests on Windows
91
+ TD_OS=windows vitest run
92
+
93
+ # Run tests on Linux (default)
94
+ TD_OS=linux vitest run
95
+ ```
96
+
97
+ This pattern is useful for running the same test suite across multiple operating systems in CI/CD:
98
+
99
+ ```yaml
100
+ # Example GitHub Actions matrix
101
+ strategy:
102
+ matrix:
103
+ os: [linux, windows]
104
+ steps:
105
+ - run: TD_OS=${{ matrix.os }} vitest run
106
+ ```
107
+
108
+ ## Keepalive
109
+
110
+ By default, sandboxes terminate immediately when the test finishes. Set this value to keep the sandbox alive for reconnection.
111
+
112
+ The `keepAlive` param enables you to keep the sandbox running after the test completes for debugging or reconnection. This will allow you to use the debugger to inspect the state of the device after the test has finished.
113
+
114
+ ```javascript
115
+ const testdriver = TestDriver(context, {
116
+ keepAlive: 300000, // Keep sandbox alive for 5 minutes after test
117
+ });
118
+ ```
119
+
120
+ ### Reconnecting to Existing Sandbox
121
+
122
+ Speed up test development by reconnecting to an existing sandbox instead of starting fresh each time. This lets you iterate quickly on failing steps without re-running the entire test from the beginning.
123
+
124
+ Split your test into two files: one for known-good steps that set up the desired state, and another for work-in-progress steps you want to debug.
125
+
126
+ ```javascript known-good.test.mjs
127
+ const testdriver = TestDriver(context, {
128
+ keepAlive: 60000, // Keep sandbox alive for 60 seconds after test
129
+ });
130
+ ```
131
+
132
+ ```javascript work-in-progress.test.mjs
133
+ // Second test file: experiment.test.mjs (run within keepAlive window)
134
+ const testdriver = TestDriver(context, {
135
+ reconnect: true, // Reconnect to existing sandbox
136
+ });
137
+ ```
138
+
139
+ Then, you can run both tests in sequence:
140
+
141
+ ```bash
142
+ vitest run -t known-good.test.mjs -t work-in-progress.test.mjs
143
+ ```
144
+
145
+ And as you make changes to `work-in-progress.test.mjs`, you can re-run just that file to quickly iterate on the failing steps.
146
+
147
+ ```bash
148
+ vitest run work-in-progress.test.mjs
149
+ ```
150
+
151
+ <Warning>
152
+ Reconnect only works if run within the `keepAlive` window of the previous test.
153
+ </Warning>
@@ -0,0 +1,418 @@
1
+ ---
2
+ name: testdriver:dashcam
3
+ description: Record test execution with video and logs
4
+ ---
5
+ <!-- Generated from dashcam.mdx. DO NOT EDIT. -->
6
+
7
+ ## Overview
8
+
9
+ Dashcam provides automatic video recording and log aggregation for your tests. It captures screen recordings, application logs, and test execution details that can be reviewed later.
10
+
11
+ ## Basic Usage
12
+
13
+ ### With Presets
14
+
15
+ Most presets automatically include Dashcam:
16
+
17
+ ```javascript
18
+ import { test } from 'vitest';
19
+ import { chrome } from 'testdriverai/presets';
20
+
21
+ test('my test', async (context) => {
22
+ const { testdriver, dashcam } = await chrome(context, {
23
+ url: 'https://example.com'
24
+ });
25
+
26
+ // Test executes with recording automatically
27
+ await testdriver.find('login button').then(el => el.click());
28
+
29
+ // Dashcam URL available after test
30
+ console.log('Replay:', dashcam.url);
31
+ });
32
+ ```
33
+
34
+ ### Manual Setup
35
+
36
+ For more control, create a Dashcam instance directly:
37
+
38
+ ```javascript
39
+ import TestDriver from 'testdriverai';
40
+ import Dashcam from 'testdriverai/lib/core/Dashcam.js';
41
+
42
+ const client = await TestDriver.create({ os: 'linux' });
43
+ const dashcam = new Dashcam(client, {
44
+ apiKey: process.env.DASHCAM_API_KEY
45
+ });
46
+
47
+ await dashcam.auth();
48
+ await dashcam.start();
49
+
50
+ // Run your tests
51
+
52
+ const url = await dashcam.stop();
53
+ console.log('Replay URL:', url);
54
+ ```
55
+
56
+ ## Constructor
57
+
58
+ Create a new Dashcam instance:
59
+
60
+ ```javascript
61
+ new Dashcam(client, options)
62
+ ```
63
+
64
+ ### Parameters
65
+
66
+ <ParamField path="client" type="TestDriver" required>
67
+ TestDriver client instance
68
+ </ParamField>
69
+
70
+ <ParamField path="options" type="object">
71
+ Configuration options
72
+
73
+ <Expandable title="options properties">
74
+ <ParamField path="apiKey" type="string" default="4e93d8bf-3886-4d26-a144-116c4063522d">
75
+ Dashcam API key for authentication
76
+ </ParamField>
77
+
78
+ <ParamField path="autoStart" type="boolean" default={false}>
79
+ Automatically start recording after authentication
80
+ </ParamField>
81
+
82
+ <ParamField path="logs" type="array" default={[]}>
83
+ Log configurations to add automatically
84
+ </ParamField>
85
+ </Expandable>
86
+ </ParamField>
87
+
88
+ ## Methods
89
+
90
+ ### auth()
91
+
92
+ Authenticate with Dashcam service:
93
+
94
+ ```javascript
95
+ await dashcam.auth(apiKey)
96
+ ```
97
+
98
+ <ParamField path="apiKey" type="string" optional>
99
+ Override the API key set in constructor
100
+ </ParamField>
101
+
102
+ **Returns:** `Promise<void>`
103
+
104
+ **Example:**
105
+ ```javascript
106
+ await dashcam.auth('your-api-key');
107
+ ```
108
+
109
+ ### start()
110
+
111
+ Start recording:
112
+
113
+ ```javascript
114
+ await dashcam.start()
115
+ ```
116
+
117
+ **Returns:** `Promise<void>`
118
+
119
+ **Example:**
120
+ ```javascript
121
+ await dashcam.start();
122
+ console.log('Recording started');
123
+ ```
124
+
125
+ ### stop()
126
+
127
+ Stop recording and retrieve replay URL:
128
+
129
+ ```javascript
130
+ await dashcam.stop()
131
+ ```
132
+
133
+ **Returns:** `Promise<string|null>` - Replay URL if available
134
+
135
+ **Example:**
136
+ ```javascript
137
+ const url = await dashcam.stop();
138
+ if (url) {
139
+ console.log('Watch replay:', url);
140
+ } else {
141
+ console.log('No replay URL available');
142
+ }
143
+ ```
144
+
145
+ ### addFileLog()
146
+
147
+ Track a log file in the recording:
148
+
149
+ ```javascript
150
+ await dashcam.addFileLog(path, name)
151
+ ```
152
+
153
+ <ParamField path="path" type="string" required>
154
+ Path to the log file
155
+ </ParamField>
156
+
157
+ <ParamField path="name" type="string" required>
158
+ Display name for the log in Dashcam
159
+ </ParamField>
160
+
161
+ **Returns:** `Promise<void>`
162
+
163
+ **Example:**
164
+ ```javascript
165
+ // Linux/Mac
166
+ await dashcam.addFileLog('/tmp/app.log', 'Application Log');
167
+
168
+ // Windows
169
+ await dashcam.addFileLog('C:\\logs\\app.log', 'Application Log');
170
+ ```
171
+
172
+ ### addApplicationLog()
173
+
174
+ Track application-specific logs:
175
+
176
+ ```javascript
177
+ await dashcam.addApplicationLog(application, name)
178
+ ```
179
+
180
+ <ParamField path="application" type="string" required>
181
+ Application name to track
182
+ </ParamField>
183
+
184
+ <ParamField path="name" type="string" required>
185
+ Display name for the log
186
+ </ParamField>
187
+
188
+ **Returns:** `Promise<void>`
189
+
190
+ **Example:**
191
+ ```javascript
192
+ await dashcam.addApplicationLog('Google Chrome', 'Browser Logs');
193
+ ```
194
+
195
+ ### addLog()
196
+
197
+ Generic method to add any type of log:
198
+
199
+ ```javascript
200
+ await dashcam.addLog(config)
201
+ ```
202
+
203
+ <ParamField path="config" type="object" required>
204
+ Log configuration
205
+
206
+ <Expandable title="config properties">
207
+ <ParamField path="name" type="string" required>
208
+ Display name for the log
209
+ </ParamField>
210
+
211
+ <ParamField path="type" type="string" required>
212
+ Log type: `'file'`, `'stdout'`, or `'application'`
213
+ </ParamField>
214
+
215
+ <ParamField path="path" type="string">
216
+ File path (required for type='file')
217
+ </ParamField>
218
+
219
+ <ParamField path="application" type="string">
220
+ Application name (required for type='application')
221
+ </ParamField>
222
+ </Expandable>
223
+ </ParamField>
224
+
225
+ **Returns:** `Promise<void>`
226
+
227
+ **Example:**
228
+ ```javascript
229
+ await dashcam.addLog({
230
+ name: 'Test Output',
231
+ type: 'file',
232
+ path: '/tmp/test.log'
233
+ });
234
+
235
+ await dashcam.addLog({
236
+ name: 'Chrome Logs',
237
+ type: 'application',
238
+ application: 'Google Chrome'
239
+ });
240
+ ```
241
+
242
+ ### isRecording()
243
+
244
+ Check if currently recording:
245
+
246
+ ```javascript
247
+ await dashcam.isRecording()
248
+ ```
249
+
250
+ **Returns:** `Promise<boolean>` - True if recording is active
251
+
252
+ **Example:**
253
+ ```javascript
254
+ if (await dashcam.isRecording()) {
255
+ console.log('Recording in progress');
256
+ }
257
+ ```
258
+
259
+ ## Properties
260
+
261
+ ### recording
262
+
263
+ Current recording state:
264
+
265
+ ```javascript
266
+ dashcam.recording // boolean
267
+ ```
268
+
269
+ ### apiKey
270
+
271
+ Configured API key:
272
+
273
+ ```javascript
274
+ dashcam.apiKey // string
275
+ ```
276
+
277
+ ### client
278
+
279
+ Associated TestDriver client:
280
+
281
+ ```javascript
282
+ dashcam.client // TestDriver instance
283
+ ```
284
+
285
+ ## Complete Examples
286
+
287
+ ### Basic Recording
288
+
289
+ ```javascript
290
+ import { test } from 'vitest';
291
+ import TestDriver from 'testdriverai';
292
+ import Dashcam from 'testdriverai/lib/core/Dashcam.js';
293
+
294
+ test('record test execution', async () => {
295
+ const client = await TestDriver.create({ os: 'linux' });
296
+ const dashcam = new Dashcam(client);
297
+
298
+ await dashcam.auth();
299
+ await dashcam.start();
300
+
301
+ // Run your test
302
+ await client.find('button').then(el => el.click());
303
+
304
+ const url = await dashcam.stop();
305
+ console.log('Replay:', url);
306
+
307
+ await client.cleanup();
308
+ });
309
+ ```
310
+
311
+ ### With Log Tracking
312
+
313
+ ```javascript
314
+ test('record with logs', async () => {
315
+ const client = await TestDriver.create({ os: 'linux' });
316
+ const dashcam = new Dashcam(client);
317
+
318
+ await dashcam.auth();
319
+
320
+ // Add log files before starting
321
+ await dashcam.addFileLog('/tmp/testdriver.log', 'TestDriver Log');
322
+ await dashcam.addFileLog('/tmp/app.log', 'Application Log');
323
+
324
+ await dashcam.start();
325
+
326
+ // Test execution
327
+ await client.find('login button').then(el => el.click());
328
+
329
+ const url = await dashcam.stop();
330
+ console.log('Replay with logs:', url);
331
+
332
+ await client.cleanup();
333
+ });
334
+ ```
335
+
336
+ ### Auto-start Configuration
337
+
338
+ ```javascript
339
+ test('auto-start recording', async () => {
340
+ const client = await TestDriver.create({ os: 'linux' });
341
+ const dashcam = new Dashcam(client, {
342
+ autoStart: true,
343
+ logs: [
344
+ {
345
+ name: 'App Log',
346
+ type: 'file',
347
+ path: '/tmp/app.log'
348
+ }
349
+ ]
350
+ });
351
+
352
+ await dashcam.auth(); // Automatically starts recording
353
+
354
+ // Test execution
355
+ await client.find('submit button').then(el => el.click());
356
+
357
+ const url = await dashcam.stop();
358
+ console.log('Replay:', url);
359
+
360
+ await client.cleanup();
361
+ });
362
+ ```
363
+
364
+ ### Using with Presets
365
+
366
+ ```javascript
367
+ import { chrome } from 'testdriverai/presets';
368
+
369
+ test('preset with dashcam', async (context) => {
370
+ const { testdriver, dashcam } = await chrome(context, {
371
+ url: 'https://example.com',
372
+ dashcam: true // Enabled by default
373
+ });
374
+
375
+ // Test runs with automatic recording
376
+ await testdriver.find('button').then(el => el.click());
377
+
378
+ // URL automatically available
379
+ console.log('Replay:', dashcam.url);
380
+ });
381
+ ```
382
+
383
+ ### Disabling Dashcam in Presets
384
+
385
+ ```javascript
386
+ test('without dashcam', async (context) => {
387
+ const { testdriver } = await chrome(context, {
388
+ url: 'https://example.com',
389
+ dashcam: false // Disable recording
390
+ });
391
+
392
+ // Test runs without recording (faster)
393
+ await testdriver.find('button').then(el => el.click());
394
+ });
395
+ ```
396
+
397
+ ## Platform Differences
398
+
399
+ ### Windows
400
+
401
+ On Windows, Dashcam uses PowerShell commands and installs via npm:
402
+
403
+ ```javascript
404
+ // Windows-specific paths
405
+ await dashcam.addFileLog(
406
+ 'C:\\Users\\testdriver\\Documents\\testdriver.log',
407
+ 'TestDriver Log'
408
+ );
409
+ ```
410
+
411
+ ### Linux/Mac
412
+
413
+ On Linux/Mac, Dashcam uses shell commands:
414
+
415
+ ```javascript
416
+ // Unix-specific paths
417
+ await dashcam.addFileLog('/tmp/testdriver.log', 'TestDriver Log');
418
+ ```