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.
Files changed (112) hide show
  1. package/AGENTS.md +550 -0
  2. package/CODEOWNERS +0 -1
  3. package/README.md +126 -0
  4. package/agent/index.js +43 -18
  5. package/agent/lib/commands.js +794 -135
  6. package/agent/lib/redraw.js +124 -39
  7. package/agent/lib/sandbox.js +10 -1
  8. package/agent/lib/sdk.js +21 -0
  9. package/docs/MIGRATION.md +425 -0
  10. package/docs/PRESETS.md +210 -0
  11. package/docs/docs.json +91 -37
  12. package/docs/guide/best-practices-polling.mdx +154 -0
  13. package/docs/v7/api/dashcam.mdx +497 -0
  14. package/docs/v7/api/doubleClick.mdx +102 -0
  15. package/docs/v7/api/mouseDown.mdx +161 -0
  16. package/docs/v7/api/mouseUp.mdx +164 -0
  17. package/docs/v7/api/rightClick.mdx +123 -0
  18. package/docs/v7/getting-started/configuration.mdx +380 -0
  19. package/docs/v7/getting-started/quickstart.mdx +273 -140
  20. package/docs/v7/guides/best-practices.mdx +486 -0
  21. package/docs/v7/guides/caching-ai.mdx +215 -0
  22. package/docs/v7/guides/caching-selectors.mdx +292 -0
  23. package/docs/v7/guides/caching.mdx +366 -0
  24. package/docs/v7/guides/ci-cd/azure.mdx +587 -0
  25. package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
  26. package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
  27. package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
  28. package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
  29. package/docs/v7/guides/ci-cd/travis.mdx +438 -0
  30. package/docs/v7/guides/debugging.mdx +349 -0
  31. package/docs/v7/guides/faq.mdx +393 -0
  32. package/docs/v7/guides/performance.mdx +517 -0
  33. package/docs/v7/guides/troubleshooting.mdx +526 -0
  34. package/docs/v7/guides/vitest-plugin.mdx +477 -0
  35. package/docs/v7/guides/vitest.mdx +535 -0
  36. package/docs/v7/platforms/linux.mdx +308 -0
  37. package/docs/v7/platforms/macos.mdx +433 -0
  38. package/docs/v7/platforms/windows.mdx +430 -0
  39. package/docs/v7/presets/chrome-extension.mdx +223 -0
  40. package/docs/v7/presets/chrome.mdx +287 -0
  41. package/docs/v7/presets/electron.mdx +435 -0
  42. package/docs/v7/presets/vscode.mdx +398 -0
  43. package/docs/v7/presets/webapp.mdx +396 -0
  44. package/docs/v7/progressive-apis/CORE.md +459 -0
  45. package/docs/v7/progressive-apis/HOOKS.md +360 -0
  46. package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
  47. package/docs/v7/progressive-apis/PROVISION.md +266 -0
  48. package/interfaces/vitest-plugin.mjs +186 -100
  49. package/package.json +12 -1
  50. package/sdk.d.ts +335 -42
  51. package/sdk.js +756 -95
  52. package/src/core/Dashcam.js +469 -0
  53. package/src/core/index.d.ts +150 -0
  54. package/src/core/index.js +12 -0
  55. package/src/presets/index.mjs +331 -0
  56. package/src/vitest/extended.mjs +108 -0
  57. package/src/vitest/hooks.d.ts +119 -0
  58. package/src/vitest/hooks.mjs +298 -0
  59. package/src/vitest/index.mjs +64 -0
  60. package/src/vitest/lifecycle.mjs +277 -0
  61. package/src/vitest/utils.mjs +150 -0
  62. package/test/dashcam.test.js +137 -0
  63. package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
  64. package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
  65. package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
  66. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
  67. package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
  68. package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
  69. package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
  70. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
  71. package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
  72. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
  73. package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
  74. package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
  75. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
  76. package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
  77. package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
  78. package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
  79. package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
  80. package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
  81. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
  82. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
  83. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
  84. package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
  85. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
  86. package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
  87. package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
  88. package/testdriver/acceptance-sdk/type.test.mjs +19 -58
  89. package/vitest.config.mjs +1 -0
  90. package/.vscode/mcp.json +0 -9
  91. package/MIGRATION.md +0 -389
  92. package/PLUGIN_MIGRATION.md +0 -222
  93. package/PROMPT_CACHE.md +0 -200
  94. package/SDK_LOGGING.md +0 -222
  95. package/SDK_MIGRATION.md +0 -474
  96. package/SDK_README.md +0 -1122
  97. package/debug-screenshot-1763401388589.png +0 -0
  98. package/examples/run-tests-with-recording.sh +0 -70
  99. package/examples/screenshot-example.js +0 -63
  100. package/examples/sdk-awesome-logs-demo.js +0 -177
  101. package/examples/sdk-cache-thresholds.js +0 -96
  102. package/examples/sdk-element-properties.js +0 -155
  103. package/examples/sdk-simple-example.js +0 -65
  104. package/examples/test-recording-example.test.js +0 -166
  105. package/mcp-server/AI_GUIDELINES.md +0 -57
  106. package/test-find-api.js +0 -73
  107. package/test-prompt-cache.js +0 -96
  108. package/test-sandbox-render.js +0 -28
  109. package/test-sdk-methods.js +0 -15
  110. package/test-sdk-refactor.js +0 -53
  111. package/test-stack-trace.mjs +0 -57
  112. 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
@@ -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!