testdriverai 7.2.2 → 7.2.9
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/.github/workflows/publish.yaml +15 -7
- package/.github/workflows/testdriver.yml +36 -0
- package/agent/index.js +28 -109
- package/bin/testdriverai.js +8 -0
- package/debugger/index.html +37 -0
- package/docs/docs.json +2 -11
- package/docs/v7/_drafts/architecture.mdx +1 -26
- package/docs/v7/_drafts/provision.mdx +251 -188
- package/docs/v7/_drafts/quick-start-test-recording.mdx +0 -1
- package/docs/v7/_drafts/test-recording.mdx +0 -6
- package/docs/v7/api/act.mdx +1 -0
- package/docs/v7/getting-started/quickstart.mdx +9 -16
- package/interfaces/cli/commands/init.js +33 -19
- package/interfaces/cli/lib/base.js +24 -0
- package/interfaces/cli.js +8 -1
- package/interfaces/logger.js +8 -3
- package/interfaces/vitest-plugin.mjs +16 -71
- package/lib/sentry.js +343 -0
- package/lib/vitest/hooks.mjs +23 -31
- package/package.json +4 -3
- package/sdk-log-formatter.js +41 -0
- package/sdk.js +335 -94
- package/test/testdriver/act.test.mjs +30 -0
- package/test/testdriver/assert.test.mjs +1 -1
- package/test/testdriver/hover-text.test.mjs +1 -1
- package/test/testdriver/installer.test.mjs +47 -0
- package/test/testdriver/launch-vscode-linux.test.mjs +55 -0
- package/test/testdriver/setup/testHelpers.mjs +8 -118
- package/tests/example.test.js +33 -0
- package/tests/login.js +28 -0
- package/vitest.config.js +18 -0
- package/vitest.config.mjs +1 -0
- package/agent/lib/cache.js +0 -142
package/lib/vitest/hooks.mjs
CHANGED
|
@@ -15,11 +15,9 @@
|
|
|
15
15
|
* });
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import
|
|
19
|
-
import os from 'os';
|
|
18
|
+
import chalk from 'chalk';
|
|
20
19
|
import path from 'path';
|
|
21
20
|
import { vi } from 'vitest';
|
|
22
|
-
import chalk from 'chalk';
|
|
23
21
|
import TestDriverSDK from '../../sdk.js';
|
|
24
22
|
|
|
25
23
|
/**
|
|
@@ -78,26 +76,30 @@ function setupConsoleSpy(client, taskId) {
|
|
|
78
76
|
}
|
|
79
77
|
};
|
|
80
78
|
|
|
79
|
+
// Store original console methods before spying
|
|
80
|
+
const originalLog = console.log.bind(console);
|
|
81
|
+
const originalError = console.error.bind(console);
|
|
82
|
+
const originalWarn = console.warn.bind(console);
|
|
83
|
+
const originalInfo = console.info.bind(console);
|
|
84
|
+
|
|
81
85
|
// Create spies for each console method
|
|
82
86
|
const logSpy = vi.spyOn(console, 'log').mockImplementation((...args) => {
|
|
83
|
-
// Call
|
|
84
|
-
logSpy.mock.calls; // Track calls
|
|
85
|
-
process.stdout.write(args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' ') + '\n');
|
|
87
|
+
originalLog(...args); // Call original (Vitest will capture this)
|
|
86
88
|
forwardToSandbox(args);
|
|
87
89
|
});
|
|
88
90
|
|
|
89
91
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation((...args) => {
|
|
90
|
-
|
|
92
|
+
originalError(...args);
|
|
91
93
|
forwardToSandbox(args);
|
|
92
94
|
});
|
|
93
95
|
|
|
94
96
|
const warnSpy = vi.spyOn(console, 'warn').mockImplementation((...args) => {
|
|
95
|
-
|
|
97
|
+
originalWarn(...args);
|
|
96
98
|
forwardToSandbox(args);
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
const infoSpy = vi.spyOn(console, 'info').mockImplementation((...args) => {
|
|
100
|
-
|
|
102
|
+
originalInfo(...args);
|
|
101
103
|
forwardToSandbox(args);
|
|
102
104
|
});
|
|
103
105
|
|
|
@@ -133,6 +135,7 @@ const lifecycleHandlers = new WeakMap();
|
|
|
133
135
|
* @param {string} [options.apiKey] - TestDriver API key (defaults to process.env.TD_API_KEY)
|
|
134
136
|
* @param {boolean} [options.headless] - Run sandbox in headless mode
|
|
135
137
|
* @param {boolean} [options.newSandbox] - Create new sandbox
|
|
138
|
+
* @param {number} [options.timeout=0] - Sandbox timeout (TTL) in milliseconds. 0 = use provider default (5 min for E2B Linux)
|
|
136
139
|
* @param {boolean} [options.autoConnect=true] - Automatically connect to sandbox
|
|
137
140
|
* @returns {TestDriver} TestDriver client instance
|
|
138
141
|
*
|
|
@@ -238,9 +241,9 @@ export function TestDriver(context, options = {}) {
|
|
|
238
241
|
console.log('');
|
|
239
242
|
console.log('🎥' + chalk.yellow(` Dashcam URL`) + `: ${dashcamUrl}`);
|
|
240
243
|
console.log('');
|
|
241
|
-
|
|
242
|
-
//
|
|
243
|
-
|
|
244
|
+
|
|
245
|
+
// Set test metadata directly on the Vitest task context
|
|
246
|
+
// This is the proper way to pass data from test to reporter
|
|
244
247
|
const platform = testdriver.os || 'linux';
|
|
245
248
|
const absolutePath = context.task.file?.filepath || context.task.file?.name || 'unknown';
|
|
246
249
|
const projectRoot = process.cwd();
|
|
@@ -248,27 +251,16 @@ export function TestDriver(context, options = {}) {
|
|
|
248
251
|
? path.relative(projectRoot, absolutePath)
|
|
249
252
|
: absolutePath;
|
|
250
253
|
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// Write test result file
|
|
258
|
-
const testResultFile = path.join(resultsDir, `${testId}.json`);
|
|
259
|
-
const testResult = {
|
|
260
|
-
dashcamUrl: dashcamUrl || null,
|
|
261
|
-
platform,
|
|
262
|
-
testFile,
|
|
263
|
-
testOrder: 0,
|
|
264
|
-
sessionId: testdriver.getSessionId(),
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
fs.writeFileSync(testResultFile, JSON.stringify(testResult, null, 2));
|
|
254
|
+
// Set metadata on the task for the reporter to read
|
|
255
|
+
context.task.meta.dashcamUrl = dashcamUrl || null;
|
|
256
|
+
context.task.meta.platform = platform;
|
|
257
|
+
context.task.meta.testFile = testFile;
|
|
258
|
+
context.task.meta.testOrder = 0;
|
|
259
|
+
context.task.meta.sessionId = testdriver.getSessionId();
|
|
268
260
|
|
|
269
|
-
// Also register in memory if plugin is available
|
|
261
|
+
// Also register in memory if plugin is available (for cross-process scenarios)
|
|
270
262
|
if (globalThis.__testdriverPlugin?.registerDashcamUrl) {
|
|
271
|
-
globalThis.__testdriverPlugin.registerDashcamUrl(
|
|
263
|
+
globalThis.__testdriverPlugin.registerDashcamUrl(context.task.id, dashcamUrl, platform);
|
|
272
264
|
}
|
|
273
265
|
} catch (error) {
|
|
274
266
|
// Log more detailed error information for debugging
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testdriverai",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.9",
|
|
4
4
|
"description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
|
|
5
5
|
"main": "sdk.js",
|
|
6
6
|
"exports": {
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@oclif/plugin-help": "^6.2.30",
|
|
53
53
|
"@oclif/plugin-not-found": "^3.2.59",
|
|
54
54
|
"@oclif/plugin-warn-if-update-available": "^3.1.43",
|
|
55
|
+
"@sentry/node": "^9.47.1",
|
|
55
56
|
"@stoplight/yaml-ast-parser": "^0.0.50",
|
|
56
57
|
"ajv": "^8.17.1",
|
|
57
58
|
"arktype": "^2.1.19",
|
|
@@ -97,8 +98,8 @@
|
|
|
97
98
|
"mocha": "^10.8.2",
|
|
98
99
|
"node-addon-api": "^8.0.0",
|
|
99
100
|
"prettier": "3.3.3",
|
|
100
|
-
"testdriverai": "^
|
|
101
|
-
"vitest": "^4.0.
|
|
101
|
+
"testdriverai": "^7.2.3",
|
|
102
|
+
"vitest": "^4.0.16"
|
|
102
103
|
},
|
|
103
104
|
"optionalDependencies": {
|
|
104
105
|
"@esbuild/linux-x64": "^0.21.5"
|
package/sdk-log-formatter.js
CHANGED
|
@@ -878,6 +878,47 @@ class SDKLogFormatter {
|
|
|
878
878
|
|
|
879
879
|
return `\n${parts.join(" ")}\n`;
|
|
880
880
|
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Format act() start message - provides visual scope boundary
|
|
884
|
+
* @param {string} task - The task being executed
|
|
885
|
+
* @returns {string} Formatted act start message
|
|
886
|
+
*/
|
|
887
|
+
formatActStart(task) {
|
|
888
|
+
const parts = [];
|
|
889
|
+
this.addTimestamp(parts);
|
|
890
|
+
parts.push(this.getPrefix("action"));
|
|
891
|
+
parts.push(chalk.bold.cyan("Act"));
|
|
892
|
+
parts.push(chalk.cyan(`"${task}"`));
|
|
893
|
+
return parts.join(" ");
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Format act() completion message - provides visual scope boundary
|
|
898
|
+
* @param {number} durationMs - Duration in milliseconds
|
|
899
|
+
* @param {boolean} success - Whether the act completed successfully
|
|
900
|
+
* @param {string} [error] - Error message if failed
|
|
901
|
+
* @returns {string} Formatted act complete message
|
|
902
|
+
*/
|
|
903
|
+
formatActComplete(durationMs, success, error = null) {
|
|
904
|
+
const parts = [];
|
|
905
|
+
this.addTimestamp(parts);
|
|
906
|
+
parts.push(this.getResultPrefix());
|
|
907
|
+
|
|
908
|
+
if (success) {
|
|
909
|
+
parts.push(chalk.green("complete"));
|
|
910
|
+
} else {
|
|
911
|
+
parts.push(chalk.red("failed"));
|
|
912
|
+
if (error) {
|
|
913
|
+
parts.push(chalk.dim("·"));
|
|
914
|
+
parts.push(chalk.red(error));
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
parts.push(this.formatDurationColored(durationMs, "default"));
|
|
919
|
+
|
|
920
|
+
return parts.join(" ");
|
|
921
|
+
}
|
|
881
922
|
}
|
|
882
923
|
|
|
883
924
|
// Export singleton instance
|