testdriverai 7.0.0 → 7.1.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.
- package/AGENTS.md +550 -0
- package/CODEOWNERS +0 -1
- package/README.md +126 -0
- package/agent/index.js +43 -18
- package/agent/lib/commands.js +794 -135
- package/agent/lib/redraw.js +124 -39
- package/agent/lib/sandbox.js +10 -1
- package/agent/lib/sdk.js +21 -0
- package/docs/MIGRATION.md +425 -0
- package/docs/PRESETS.md +210 -0
- package/docs/docs.json +91 -37
- package/docs/guide/best-practices-polling.mdx +154 -0
- package/docs/v7/api/dashcam.mdx +497 -0
- package/docs/v7/api/doubleClick.mdx +102 -0
- package/docs/v7/api/mouseDown.mdx +161 -0
- package/docs/v7/api/mouseUp.mdx +164 -0
- package/docs/v7/api/rightClick.mdx +123 -0
- package/docs/v7/getting-started/configuration.mdx +380 -0
- package/docs/v7/getting-started/quickstart.mdx +273 -140
- package/docs/v7/guides/best-practices.mdx +486 -0
- package/docs/v7/guides/caching-ai.mdx +215 -0
- package/docs/v7/guides/caching-selectors.mdx +292 -0
- package/docs/v7/guides/caching.mdx +366 -0
- package/docs/v7/guides/ci-cd/azure.mdx +587 -0
- package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
- package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
- package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
- package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
- package/docs/v7/guides/ci-cd/travis.mdx +438 -0
- package/docs/v7/guides/debugging.mdx +349 -0
- package/docs/v7/guides/faq.mdx +393 -0
- package/docs/v7/guides/performance.mdx +517 -0
- package/docs/v7/guides/troubleshooting.mdx +526 -0
- package/docs/v7/guides/vitest-plugin.mdx +477 -0
- package/docs/v7/guides/vitest.mdx +535 -0
- package/docs/v7/platforms/linux.mdx +308 -0
- package/docs/v7/platforms/macos.mdx +433 -0
- package/docs/v7/platforms/windows.mdx +430 -0
- package/docs/v7/presets/chrome-extension.mdx +223 -0
- package/docs/v7/presets/chrome.mdx +287 -0
- package/docs/v7/presets/electron.mdx +435 -0
- package/docs/v7/presets/vscode.mdx +398 -0
- package/docs/v7/presets/webapp.mdx +396 -0
- package/docs/v7/progressive-apis/CORE.md +459 -0
- package/docs/v7/progressive-apis/HOOKS.md +360 -0
- package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
- package/docs/v7/progressive-apis/PROVISION.md +266 -0
- package/interfaces/vitest-plugin.mjs +186 -100
- package/package.json +12 -1
- package/sdk.d.ts +335 -42
- package/sdk.js +756 -95
- package/src/core/Dashcam.js +469 -0
- package/src/core/index.d.ts +150 -0
- package/src/core/index.js +12 -0
- package/src/presets/index.mjs +331 -0
- package/src/vitest/extended.mjs +108 -0
- package/src/vitest/hooks.d.ts +119 -0
- package/src/vitest/hooks.mjs +298 -0
- package/src/vitest/index.mjs +64 -0
- package/src/vitest/lifecycle.mjs +277 -0
- package/src/vitest/utils.mjs +150 -0
- package/test/dashcam.test.js +137 -0
- package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
- package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
- package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
- package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
- package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
- package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
- package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
- package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
- package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
- package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
- package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
- package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
- package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
- package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
- package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
- package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
- package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
- package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
- package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
- package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
- package/testdriver/acceptance-sdk/type.test.mjs +19 -58
- package/vitest.config.mjs +1 -0
- package/.vscode/mcp.json +0 -9
- package/MIGRATION.md +0 -389
- package/PLUGIN_MIGRATION.md +0 -222
- package/PROMPT_CACHE.md +0 -200
- package/SDK_LOGGING.md +0 -222
- package/SDK_MIGRATION.md +0 -474
- package/SDK_README.md +0 -1122
- package/debug-screenshot-1763401388589.png +0 -0
- package/examples/run-tests-with-recording.sh +0 -70
- package/examples/screenshot-example.js +0 -63
- package/examples/sdk-awesome-logs-demo.js +0 -177
- package/examples/sdk-cache-thresholds.js +0 -96
- package/examples/sdk-element-properties.js +0 -155
- package/examples/sdk-simple-example.js +0 -65
- package/examples/test-recording-example.test.js +0 -166
- package/mcp-server/AI_GUIDELINES.md +0 -57
- package/test-find-api.js +0 -73
- package/test-prompt-cache.js +0 -96
- package/test-sandbox-render.js +0 -28
- package/test-sdk-methods.js +0 -15
- package/test-sdk-refactor.js +0 -53
- package/test-stack-trace.mjs +0 -57
- package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
package/MIGRATION.md
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
# Migrating from CLI to SDK
|
|
2
|
-
|
|
3
|
-
This guide helps you migrate from using TestDriver as a CLI tool to using it as an SDK in your JavaScript/Node.js applications.
|
|
4
|
-
|
|
5
|
-
## Key Differences
|
|
6
|
-
|
|
7
|
-
### CLI Approach (Old)
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# YAML-based test files
|
|
11
|
-
testdriverai run testdriver/my-test.yaml
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
```yaml
|
|
15
|
-
# testdriver/my-test.yaml
|
|
16
|
-
version: 6.1.10
|
|
17
|
-
steps:
|
|
18
|
-
- prompt: "Login to the application"
|
|
19
|
-
commands:
|
|
20
|
-
- command: hover-text
|
|
21
|
-
text: "Email"
|
|
22
|
-
- command: type
|
|
23
|
-
string: "user@example.com"
|
|
24
|
-
- command: hover-text
|
|
25
|
-
text: "Submit"
|
|
26
|
-
- command: wait-for-text
|
|
27
|
-
text: "Dashboard"
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### SDK Approach (New)
|
|
31
|
-
|
|
32
|
-
```javascript
|
|
33
|
-
// JavaScript-based tests
|
|
34
|
-
const TestDriver = require("testdriverai");
|
|
35
|
-
|
|
36
|
-
async function testLogin() {
|
|
37
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
38
|
-
await client.auth();
|
|
39
|
-
await client.connect();
|
|
40
|
-
|
|
41
|
-
await client.hoverText("Email");
|
|
42
|
-
await client.type("user@example.com");
|
|
43
|
-
await client.hoverText("Submit");
|
|
44
|
-
await client.waitForText("Dashboard");
|
|
45
|
-
|
|
46
|
-
await client.disconnect();
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Command Mapping
|
|
51
|
-
|
|
52
|
-
Here's how CLI commands map to SDK methods:
|
|
53
|
-
|
|
54
|
-
| YAML Command | SDK Method | Example |
|
|
55
|
-
| -------------------- | -------------------- | ----------------------------------------- |
|
|
56
|
-
| `hover-text` | `hoverText()` | `await client.hoverText('Submit')` |
|
|
57
|
-
| `hover-image` | `hoverImage()` | `await client.hoverImage('red button')` |
|
|
58
|
-
| `match-image` | `matchImage()` | `await client.matchImage('./button.png')` |
|
|
59
|
-
| `type` | `type()` | `await client.type('hello')` |
|
|
60
|
-
| `press-keys` | `pressKeys()` | `await client.pressKeys(['enter'])` |
|
|
61
|
-
| `click` | `click()` | `await client.click(100, 200)` |
|
|
62
|
-
| `scroll` | `scroll()` | `await client.scroll('down', 500)` |
|
|
63
|
-
| `wait` | `wait()` | `await client.wait(3000)` |
|
|
64
|
-
| `wait-for-text` | `waitForText()` | `await client.waitForText('Success')` |
|
|
65
|
-
| `wait-for-image` | `waitForImage()` | `await client.waitForImage('logo')` |
|
|
66
|
-
| `scroll-until-text` | `scrollUntilText()` | `await client.scrollUntilText('Footer')` |
|
|
67
|
-
| `scroll-until-image` | `scrollUntilImage()` | `await client.scrollUntilImage('banner')` |
|
|
68
|
-
| `focus-application` | `focusApplication()` | `await client.focusApplication('Chrome')` |
|
|
69
|
-
| `remember` | `remember()` | `await client.remember('user name')` |
|
|
70
|
-
| `assert` | `assert()` | `await client.assert('form is visible')` |
|
|
71
|
-
| `exec` | `exec()` | `await client.exec('js', code, 5000)` |
|
|
72
|
-
|
|
73
|
-
## Converting YAML to SDK
|
|
74
|
-
|
|
75
|
-
### Example 1: Simple Form Interaction
|
|
76
|
-
|
|
77
|
-
**YAML (CLI):**
|
|
78
|
-
|
|
79
|
-
```yaml
|
|
80
|
-
version: 6.1.10
|
|
81
|
-
steps:
|
|
82
|
-
- prompt: "Fill out contact form"
|
|
83
|
-
commands:
|
|
84
|
-
- command: hover-text
|
|
85
|
-
text: "Name"
|
|
86
|
-
- command: type
|
|
87
|
-
string: "John Doe"
|
|
88
|
-
- command: hover-text
|
|
89
|
-
text: "Email"
|
|
90
|
-
- command: type
|
|
91
|
-
string: "john@example.com"
|
|
92
|
-
- command: hover-text
|
|
93
|
-
text: "Submit"
|
|
94
|
-
- command: wait-for-text
|
|
95
|
-
text: "Thank you"
|
|
96
|
-
timeout: 5000
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
**SDK (JavaScript):**
|
|
100
|
-
|
|
101
|
-
```javascript
|
|
102
|
-
const TestDriver = require("testdriverai");
|
|
103
|
-
|
|
104
|
-
async function fillContactForm() {
|
|
105
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
106
|
-
|
|
107
|
-
await client.auth();
|
|
108
|
-
await client.connect();
|
|
109
|
-
|
|
110
|
-
await client.hoverText("Name");
|
|
111
|
-
await client.type("John Doe");
|
|
112
|
-
await client.hoverText("Email");
|
|
113
|
-
await client.type("john@example.com");
|
|
114
|
-
await client.hoverText("Submit");
|
|
115
|
-
await client.waitForText("Thank you", 5000);
|
|
116
|
-
|
|
117
|
-
await client.disconnect();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
fillContactForm();
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Example 2: Complex Navigation Flow
|
|
124
|
-
|
|
125
|
-
**YAML (CLI):**
|
|
126
|
-
|
|
127
|
-
```yaml
|
|
128
|
-
version: 6.1.10
|
|
129
|
-
steps:
|
|
130
|
-
- prompt: "Navigate to settings"
|
|
131
|
-
commands:
|
|
132
|
-
- command: focus-application
|
|
133
|
-
name: "Google Chrome"
|
|
134
|
-
- command: wait
|
|
135
|
-
timeout: 2000
|
|
136
|
-
- command: hover-text
|
|
137
|
-
text: "Menu"
|
|
138
|
-
- command: wait
|
|
139
|
-
timeout: 1000
|
|
140
|
-
- command: hover-text
|
|
141
|
-
text: "Settings"
|
|
142
|
-
- command: scroll
|
|
143
|
-
direction: "down"
|
|
144
|
-
amount: 500
|
|
145
|
-
- command: assert
|
|
146
|
-
expect: "The settings page is displayed"
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
**SDK (JavaScript):**
|
|
150
|
-
|
|
151
|
-
```javascript
|
|
152
|
-
const TestDriver = require("testdriverai");
|
|
153
|
-
|
|
154
|
-
async function navigateToSettings() {
|
|
155
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
156
|
-
|
|
157
|
-
await client.auth();
|
|
158
|
-
await client.connect();
|
|
159
|
-
|
|
160
|
-
await client.focusApplication("Google Chrome");
|
|
161
|
-
await client.wait(2000);
|
|
162
|
-
await client.hoverText("Menu");
|
|
163
|
-
await client.wait(1000);
|
|
164
|
-
await client.hoverText("Settings");
|
|
165
|
-
await client.scroll("down", 500);
|
|
166
|
-
await client.assert("The settings page is displayed");
|
|
167
|
-
|
|
168
|
-
await client.disconnect();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
navigateToSettings();
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Example 3: Using Variables and Loops
|
|
175
|
-
|
|
176
|
-
**YAML (CLI):**
|
|
177
|
-
|
|
178
|
-
```yaml
|
|
179
|
-
version: 6.1.10
|
|
180
|
-
steps:
|
|
181
|
-
- prompt: "Process multiple items"
|
|
182
|
-
commands:
|
|
183
|
-
- command: exec
|
|
184
|
-
language: "js"
|
|
185
|
-
code: |
|
|
186
|
-
const items = ['Item 1', 'Item 2', 'Item 3'];
|
|
187
|
-
result = items;
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**SDK (JavaScript):**
|
|
191
|
-
|
|
192
|
-
```javascript
|
|
193
|
-
const TestDriver = require("testdriverai");
|
|
194
|
-
|
|
195
|
-
async function processMultipleItems() {
|
|
196
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
197
|
-
|
|
198
|
-
await client.auth();
|
|
199
|
-
await client.connect();
|
|
200
|
-
|
|
201
|
-
const items = ["Item 1", "Item 2", "Item 3"];
|
|
202
|
-
|
|
203
|
-
for (const item of items) {
|
|
204
|
-
await client.hoverText(item);
|
|
205
|
-
await client.wait(1000);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
await client.disconnect();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
processMultipleItems();
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
## Benefits of Using SDK
|
|
215
|
-
|
|
216
|
-
### 1. **Native JavaScript Control Flow**
|
|
217
|
-
|
|
218
|
-
```javascript
|
|
219
|
-
// Use if/else statements
|
|
220
|
-
if (await checkCondition()) {
|
|
221
|
-
await client.hoverText("Option A");
|
|
222
|
-
} else {
|
|
223
|
-
await client.hoverText("Option B");
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Use loops
|
|
227
|
-
for (let i = 0; i < 5; i++) {
|
|
228
|
-
await client.scroll("down", 100);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Use try/catch for error handling
|
|
232
|
-
try {
|
|
233
|
-
await client.waitForText("Success", 5000);
|
|
234
|
-
} catch (error) {
|
|
235
|
-
console.error("Timeout waiting for success message");
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### 2. **Integration with Testing Frameworks**
|
|
240
|
-
|
|
241
|
-
```javascript
|
|
242
|
-
// Jest
|
|
243
|
-
describe("Login Flow", () => {
|
|
244
|
-
let client;
|
|
245
|
-
|
|
246
|
-
beforeAll(async () => {
|
|
247
|
-
client = new TestDriver(process.env.TD_API_KEY);
|
|
248
|
-
await client.auth();
|
|
249
|
-
await client.connect();
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
afterAll(async () => {
|
|
253
|
-
await client.disconnect();
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
test("should login successfully", async () => {
|
|
257
|
-
await client.hoverText("Email");
|
|
258
|
-
await client.type("test@example.com");
|
|
259
|
-
await client.hoverText("Submit");
|
|
260
|
-
await client.waitForText("Dashboard");
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### 3. **Dynamic Test Data**
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
const users = [
|
|
269
|
-
{ email: "user1@test.com", password: "pass1" },
|
|
270
|
-
{ email: "user2@test.com", password: "pass2" },
|
|
271
|
-
];
|
|
272
|
-
|
|
273
|
-
for (const user of users) {
|
|
274
|
-
await client.hoverText("Email");
|
|
275
|
-
await client.type(user.email);
|
|
276
|
-
await client.hoverText("Password");
|
|
277
|
-
await client.type(user.password);
|
|
278
|
-
await client.hoverText("Login");
|
|
279
|
-
await client.waitForText("Dashboard");
|
|
280
|
-
// Logout for next iteration
|
|
281
|
-
await client.hoverText("Logout");
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### 4. **Reusable Functions**
|
|
286
|
-
|
|
287
|
-
```javascript
|
|
288
|
-
async function login(client, email, password) {
|
|
289
|
-
await client.hoverText("Email");
|
|
290
|
-
await client.type(email);
|
|
291
|
-
await client.hoverText("Password");
|
|
292
|
-
await client.type(password);
|
|
293
|
-
await client.hoverText("Login");
|
|
294
|
-
await client.waitForText("Dashboard");
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async function logout(client) {
|
|
298
|
-
await client.hoverText("Menu");
|
|
299
|
-
await client.hoverText("Logout");
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Use anywhere
|
|
303
|
-
await login(client, "user@test.com", "password123");
|
|
304
|
-
await logout(client);
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
## When to Use CLI vs SDK
|
|
308
|
-
|
|
309
|
-
### Use CLI When:
|
|
310
|
-
|
|
311
|
-
- ✅ You need exploratory testing with AI-generated tests
|
|
312
|
-
- ✅ You want to quickly prototype tests without writing code
|
|
313
|
-
- ✅ You prefer declarative YAML configuration
|
|
314
|
-
- ✅ You're using the interactive edit mode
|
|
315
|
-
|
|
316
|
-
### Use SDK When:
|
|
317
|
-
|
|
318
|
-
- ✅ You need programmatic control over test execution
|
|
319
|
-
- ✅ You want to integrate with existing test frameworks (Jest, Mocha, etc.)
|
|
320
|
-
- ✅ You need complex control flow (loops, conditionals, error handling)
|
|
321
|
-
- ✅ You want to use dynamic test data
|
|
322
|
-
- ✅ You're building automated CI/CD pipelines
|
|
323
|
-
- ✅ You need to reuse test logic across multiple tests
|
|
324
|
-
|
|
325
|
-
## Running Both CLI and SDK
|
|
326
|
-
|
|
327
|
-
You can use both approaches in the same project:
|
|
328
|
-
|
|
329
|
-
```json
|
|
330
|
-
{
|
|
331
|
-
"scripts": {
|
|
332
|
-
"test:cli": "testdriverai run testdriver/regression.yaml",
|
|
333
|
-
"test:sdk": "node tests/login.test.js",
|
|
334
|
-
"test:all": "npm run test:cli && npm run test:sdk"
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
## Best Practices
|
|
340
|
-
|
|
341
|
-
1. **Use environment variables for credentials:**
|
|
342
|
-
|
|
343
|
-
```javascript
|
|
344
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
2. **Always disconnect after tests:**
|
|
348
|
-
|
|
349
|
-
```javascript
|
|
350
|
-
try {
|
|
351
|
-
// Your tests
|
|
352
|
-
} finally {
|
|
353
|
-
await client.disconnect();
|
|
354
|
-
}
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
3. **Create helper functions for common actions:**
|
|
358
|
-
|
|
359
|
-
```javascript
|
|
360
|
-
const helpers = {
|
|
361
|
-
login: async (client, email, password) => {
|
|
362
|
-
/* ... */
|
|
363
|
-
},
|
|
364
|
-
navigateTo: async (client, page) => {
|
|
365
|
-
/* ... */
|
|
366
|
-
},
|
|
367
|
-
fillForm: async (client, data) => {
|
|
368
|
-
/* ... */
|
|
369
|
-
},
|
|
370
|
-
};
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
4. **Use async/await consistently:**
|
|
374
|
-
|
|
375
|
-
```javascript
|
|
376
|
-
// ✅ Good
|
|
377
|
-
await client.hoverText("Submit");
|
|
378
|
-
await client.wait(1000);
|
|
379
|
-
|
|
380
|
-
// ❌ Bad
|
|
381
|
-
client.hoverText("Submit");
|
|
382
|
-
client.wait(1000);
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
## Next Steps
|
|
386
|
-
|
|
387
|
-
- Read the [SDK Documentation](./SDK_README.md) for complete API reference
|
|
388
|
-
- Check out [examples](./examples/sdk-example.js) for more use cases
|
|
389
|
-
- Join our [Discord](https://discord.com/invite/cWDFW8DzPm) for support
|
package/PLUGIN_MIGRATION.md
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
# Vitest Reporter → Plugin Migration
|
|
2
|
-
|
|
3
|
-
## Summary
|
|
4
|
-
|
|
5
|
-
Converted the Vitest reporter to a plugin architecture with much simpler dashcam URL tracking.
|
|
6
|
-
|
|
7
|
-
## Key Changes
|
|
8
|
-
|
|
9
|
-
### 1. Plugin Architecture ✅
|
|
10
|
-
|
|
11
|
-
**Before (Reporter):**
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
class TestDriverReporter {
|
|
15
|
-
constructor(options = {}) {
|
|
16
|
-
this.options = options;
|
|
17
|
-
this.testRun = null;
|
|
18
|
-
// ... many instance properties
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
**After (Plugin):**
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
const pluginState = {
|
|
27
|
-
testRun: null,
|
|
28
|
-
testRunId: null,
|
|
29
|
-
dashcamUrls: new Map(), // In-memory tracking!
|
|
30
|
-
// ... all state in one place
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export default function testDriverPlugin(options = {}) {
|
|
34
|
-
return {
|
|
35
|
-
name: "testdriver-plugin",
|
|
36
|
-
// ... hooks
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### 2. Dashcam URL Tracking (MUCH SIMPLER) ✅
|
|
42
|
-
|
|
43
|
-
**Before:**
|
|
44
|
-
|
|
45
|
-
- ❌ Write JSON to temp files in `/tmp/`
|
|
46
|
-
- ❌ Read temp files on test completion
|
|
47
|
-
- ❌ Complex matching logic (sessionId, taskId, filename patterns)
|
|
48
|
-
- ❌ Manual cleanup of temp files
|
|
49
|
-
- ❌ Race conditions with parallel tests
|
|
50
|
-
- ❌ Multiple fallback mechanisms (globalThis, registry, meta)
|
|
51
|
-
|
|
52
|
-
**After:**
|
|
53
|
-
|
|
54
|
-
- ✅ Simple in-memory Map (testId → dashcamUrl)
|
|
55
|
-
- ✅ Direct API: `registerDashcamUrl(testId, url, platform)`
|
|
56
|
-
- ✅ No file system operations
|
|
57
|
-
- ✅ No complex matching
|
|
58
|
-
- ✅ No cleanup needed
|
|
59
|
-
- ✅ Thread-safe for parallel tests
|
|
60
|
-
|
|
61
|
-
### 3. Usage in Tests
|
|
62
|
-
|
|
63
|
-
**Before:**
|
|
64
|
-
|
|
65
|
-
```javascript
|
|
66
|
-
// Tests had to write to temp files
|
|
67
|
-
const tempFile = path.join(
|
|
68
|
-
os.tmpdir(),
|
|
69
|
-
`testdriver-dashcam-${sessionId}-${taskId}-${Date.now()}.json`,
|
|
70
|
-
);
|
|
71
|
-
fs.writeFileSync(
|
|
72
|
-
tempFile,
|
|
73
|
-
JSON.stringify({
|
|
74
|
-
dashcamUrl,
|
|
75
|
-
replayObjectId,
|
|
76
|
-
platform: client.os,
|
|
77
|
-
timestamp: Date.now(),
|
|
78
|
-
pid: process.pid,
|
|
79
|
-
sessionId,
|
|
80
|
-
}),
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
// AND set global variables
|
|
84
|
-
globalThis.__testdriverMeta.__lastDashcamUrl__ = dashcamUrl;
|
|
85
|
-
|
|
86
|
-
// AND register in registry
|
|
87
|
-
globalThis.__testdriverRegistry.setClient(taskId, client);
|
|
88
|
-
|
|
89
|
-
// AND store in task.meta
|
|
90
|
-
task.meta.testdriverDashcamUrl = dashcamUrl;
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**After:**
|
|
94
|
-
|
|
95
|
-
```javascript
|
|
96
|
-
// Just one simple call
|
|
97
|
-
globalThis.__testdriverPlugin.registerDashcamUrl(taskId, dashcamUrl, client.os);
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 4. Configuration
|
|
101
|
-
|
|
102
|
-
**Before:**
|
|
103
|
-
|
|
104
|
-
```javascript
|
|
105
|
-
export default defineConfig({
|
|
106
|
-
test: {
|
|
107
|
-
reporters: [
|
|
108
|
-
"default",
|
|
109
|
-
[
|
|
110
|
-
"./interfaces/vitest-reporter.js",
|
|
111
|
-
{
|
|
112
|
-
apiKey: process.env.TD_API_KEY,
|
|
113
|
-
apiRoot: process.env.TD_API_ROOT,
|
|
114
|
-
},
|
|
115
|
-
],
|
|
116
|
-
],
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
**After:**
|
|
122
|
-
|
|
123
|
-
```javascript
|
|
124
|
-
export default defineConfig({
|
|
125
|
-
plugins: [
|
|
126
|
-
testDriverPlugin({
|
|
127
|
-
apiKey: process.env.TD_API_KEY,
|
|
128
|
-
apiRoot: process.env.TD_API_ROOT,
|
|
129
|
-
}),
|
|
130
|
-
],
|
|
131
|
-
});
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Files Modified
|
|
135
|
-
|
|
136
|
-
### Plugin
|
|
137
|
-
|
|
138
|
-
- ✅ **Created**: `interfaces/vitest-plugin.mjs` (new plugin)
|
|
139
|
-
- ✅ **Deleted**: `interfaces/vitest-reporter.js` (old reporter)
|
|
140
|
-
- ✅ **Updated**: `vitest.config.mjs` (uses plugin)
|
|
141
|
-
- ✅ **Updated**: `vitest.config.example.js` (uses plugin)
|
|
142
|
-
|
|
143
|
-
### Test Helpers
|
|
144
|
-
|
|
145
|
-
- ✅ **Updated**: `testdriver/acceptance-sdk/setup/testHelpers.mjs`
|
|
146
|
-
- Removed temp file writing
|
|
147
|
-
- Removed `__testdriverRegistry` initialization
|
|
148
|
-
- Removed `__testdriverMeta` initialization
|
|
149
|
-
- Uses `globalThis.__testdriverPlugin.registerDashcamUrl()` instead
|
|
150
|
-
|
|
151
|
-
### Documentation
|
|
152
|
-
|
|
153
|
-
- ✅ **Updated**: `docs/QUICK_START_TEST_RECORDING.md`
|
|
154
|
-
- ✅ **Updated**: `docs/TEST_RECORDING.md`
|
|
155
|
-
- ✅ **Updated**: `docs/ARCHITECTURE.md`
|
|
156
|
-
|
|
157
|
-
## Code Removed
|
|
158
|
-
|
|
159
|
-
### From Plugin (vs old reporter)
|
|
160
|
-
|
|
161
|
-
- ❌ ~200 lines of file system operations
|
|
162
|
-
- ❌ `indexDashcamFiles()` - complex temp file reading
|
|
163
|
-
- ❌ `findReplayForTest()` - complex sessionId matching
|
|
164
|
-
- ❌ `findReplayForTestInline()` - complex fallback logic
|
|
165
|
-
- ❌ Imports: `fs`, `os` (no longer needed!)
|
|
166
|
-
|
|
167
|
-
### From Test Helpers
|
|
168
|
-
|
|
169
|
-
- ❌ ~60 lines of temp file writing
|
|
170
|
-
- ❌ Global registry setup
|
|
171
|
-
- ❌ Global meta initialization
|
|
172
|
-
- ❌ Multiple storage mechanisms
|
|
173
|
-
|
|
174
|
-
## Benefits
|
|
175
|
-
|
|
176
|
-
1. **Simpler**: ~300 fewer lines of complex code
|
|
177
|
-
2. **Faster**: No file I/O overhead
|
|
178
|
-
3. **More Reliable**: No file system race conditions
|
|
179
|
-
4. **Better DX**: Single API call to register dashcam URLs
|
|
180
|
-
5. **Easier to Debug**: All state in one place
|
|
181
|
-
6. **Thread-Safe**: Map-based storage handles parallel tests
|
|
182
|
-
7. **Cleaner**: No temp file cleanup needed
|
|
183
|
-
|
|
184
|
-
## Testing
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
# Verify plugin loads
|
|
188
|
-
node -e "import('./interfaces/vitest-plugin.mjs').then(m => console.log('Exports:', Object.keys(m)))"
|
|
189
|
-
|
|
190
|
-
# Run tests
|
|
191
|
-
TD_API_KEY=xxx npx vitest run
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
## Migration for Users
|
|
195
|
-
|
|
196
|
-
If you're using the TestDriver SDK in your tests:
|
|
197
|
-
|
|
198
|
-
**Old way (still works but deprecated):**
|
|
199
|
-
|
|
200
|
-
```javascript
|
|
201
|
-
// Multiple places to set dashcam URL
|
|
202
|
-
globalThis.__testdriverMeta.__lastDashcamUrl__ = dashcamUrl;
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**New way:**
|
|
206
|
-
|
|
207
|
-
```javascript
|
|
208
|
-
// Single plugin API
|
|
209
|
-
if (globalThis.__testdriverPlugin) {
|
|
210
|
-
globalThis.__testdriverPlugin.registerDashcamUrl(
|
|
211
|
-
testId,
|
|
212
|
-
dashcamUrl,
|
|
213
|
-
platform,
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
## Notes
|
|
219
|
-
|
|
220
|
-
- The plugin automatically makes itself available globally as `globalThis.__testdriverPlugin`
|
|
221
|
-
- Test helpers now use this API automatically
|
|
222
|
-
- No breaking changes for end users - just better internals!
|