testdriverai 7.3.41 → 7.3.43

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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [7.3.43](https://github.com/testdriverai/testdriverai/compare/v7.3.42...v7.3.43) (2026-02-25)
2
+
3
+
4
+
5
+ ## [7.3.42](https://github.com/testdriverai/testdriverai/compare/v7.3.41...v7.3.42) (2026-02-25)
6
+
7
+
8
+
1
9
  ## [7.3.41](https://github.com/testdriverai/testdriverai/compare/v7.3.40...v7.3.41) (2026-02-25)
2
10
 
3
11
 
@@ -108,6 +108,11 @@ class Dashcam {
108
108
  */
109
109
  async _getDashcamPath() {
110
110
  const shell = this._getShell();
111
+
112
+ if (this.client.os === "windows") {
113
+ return "C:\\Program Files\\nodejs\\dashcam.cmd";
114
+ }
115
+
111
116
  const npmPrefix = await this.client.exec(
112
117
  shell,
113
118
  "npm prefix -g",
@@ -115,9 +120,6 @@ class Dashcam {
115
120
  process.env.DEBUG == "true" ? false : true,
116
121
  );
117
122
 
118
- if (this.client.os === "windows") {
119
- return "C:\\Program Files\\nodejs\\dashcam.cmd";
120
- }
121
123
  return npmPrefix.trim() + "/bin/dashcam";
122
124
  }
123
125
 
@@ -217,6 +217,47 @@ function cleanupConsoleSpy(client) {
217
217
  const testDriverInstances = new WeakMap();
218
218
  const lifecycleHandlers = new WeakMap();
219
219
 
220
+ /**
221
+ * Known log file paths on the Windows test runner.
222
+ * These are written by pyautogui-cli.py and related services.
223
+ */
224
+ const WINDOWS_RUNNER_LOG_PATHS = [
225
+ "C:\\Windows\\Temp\\pyautogui-cli.log",
226
+ ];
227
+
228
+ /**
229
+ * Fetch log files from the Windows test runner via exec() and save them locally.
230
+ * This runs before disconnect so we can still communicate with the sandbox.
231
+ *
232
+ * @param {import('../../sdk.js').default} client - TestDriver SDK instance
233
+ * @param {string} testName - Test file name (used for local directory naming)
234
+ */
235
+ async function fetchRunnerLogs(client, testName) {
236
+ if (!client.connected) return;
237
+ if (client.os !== "windows") return;
238
+
239
+ for (const remotePath of WINDOWS_RUNNER_LOG_PATHS) {
240
+ const localName = path.basename(remotePath);
241
+ try {
242
+ // Read the log file contents via PowerShell
243
+ const cmd = `if (Test-Path '${remotePath}') { Get-Content -Path '${remotePath}' -Raw } else { Write-Output '__FILE_NOT_FOUND__' }`;
244
+ const result = await Promise.race([
245
+ client.exec("pwsh", cmd, 10000, true),
246
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 15000)),
247
+ ]);
248
+
249
+ if (result && typeof result === "string" && !result.includes("__FILE_NOT_FOUND__")) {
250
+ console.log(`\n[TestDriver] === Runner Log: ${localName} ===`);
251
+ console.log(result);
252
+ console.log(`[TestDriver] === End Runner Log ===\n`);
253
+ }
254
+ } catch (err) {
255
+ // Fire-and-forget — don't let log retrieval break cleanup
256
+ console.warn(`[TestDriver] Could not fetch runner log ${remotePath}: ${err.message}`);
257
+ }
258
+ }
259
+ }
260
+
220
261
  /**
221
262
  * Upload buffered SDK + console logs directly to S3 via the existing Log system.
222
263
  * Extracts the replayId from the dashcam URL, calls POST /api/v1/logs to create
@@ -632,6 +673,16 @@ export function TestDriver(context, options = {}) {
632
673
  context.task.meta.dashcamUrl = null;
633
674
  }
634
675
 
676
+ // Fetch runner logs before disconnecting (Windows only)
677
+ // This grabs pyautogui-cli logs from the runner while we still have a connection
678
+ try {
679
+ const logTestName = testFile.replace(/[/\\]/g, "_").replace(/\.test\.m?js$/, "");
680
+ await fetchRunnerLogs(currentInstance, logTestName);
681
+ } catch (err) {
682
+ // Never let log retrieval block cleanup
683
+ console.warn("[TestDriver] Runner log fetch failed:", err.message);
684
+ }
685
+
635
686
  // Clean up console spies
636
687
  cleanupConsoleSpy(currentInstance);
637
688
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "7.3.41",
3
+ "version": "7.3.43",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "sdk.js",
6
6
  "types": "sdk.d.ts",
package/sdk.js CHANGED
@@ -615,11 +615,10 @@ class Element {
615
615
 
616
616
  // Track find interaction once at the end (fire-and-forget, don't block)
617
617
  const sessionId = this.sdk.getSessionId();
618
- if (sessionId && this.sdk.sandbox?.send) {
619
- await this.sdk.sandbox
620
- .send({
621
- type: "trackInteraction",
622
- interactionType: "find",
618
+ if (sessionId && this.sdk.apiClient) {
619
+ this.sdk.apiClient
620
+ .req("interaction/track", {
621
+ type: "find",
623
622
  session: sessionId,
624
623
  prompt: description,
625
624
  timestamp: absoluteTimestamp, // Absolute epoch timestamp - frontend calculates relative using clientStartDate
@@ -1896,7 +1895,7 @@ class TestDriverSDK {
1896
1895
  // Add web log tracking with domain wildcard pattern, then start dashcam
1897
1896
  if (this.dashcamEnabled) {
1898
1897
  const domainPattern = this._getUrlDomainPattern(url);
1899
- await this.dashcam.addWebLog(domainPattern, "Web Logs");
1898
+ // await this.dashcam.addWebLog(domainPattern, "Web Logs");
1900
1899
 
1901
1900
  // Start dashcam recording after logs are configured
1902
1901
  if (!(await this.dashcam.isRecording())) {
@@ -2463,7 +2462,7 @@ with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
2463
2462
  const pattern = this._provisionedChromeUrl
2464
2463
  ? this._getUrlDomainPattern(this._provisionedChromeUrl)
2465
2464
  : "**";
2466
- await this.dashcam.addWebLog(pattern, "Web Logs");
2465
+ // await this.dashcam.addWebLog(pattern, "Web Logs");
2467
2466
  }
2468
2467
 
2469
2468
  // Start recording if not already recording
@@ -3173,11 +3172,10 @@ CAPTCHA_SOLVER_EOF`,
3173
3172
 
3174
3173
  // Track successful findAll interaction (fire-and-forget, don't block)
3175
3174
  const sessionId = this.getSessionId();
3176
- if (sessionId && this.sandbox?.send) {
3177
- this.sandbox
3178
- .send({
3179
- type: "trackInteraction",
3180
- interactionType: "findAll",
3175
+ if (sessionId && this.apiClient) {
3176
+ this.apiClient
3177
+ .req("interaction/track", {
3178
+ type: "findAll",
3181
3179
  session: sessionId,
3182
3180
  prompt: description,
3183
3181
  timestamp: absoluteTimestamp, // Absolute epoch timestamp - frontend calculates relative using clientStartDate
@@ -3229,11 +3227,10 @@ CAPTCHA_SOLVER_EOF`,
3229
3227
 
3230
3228
  // No elements found - track interaction (fire-and-forget, don't block)
3231
3229
  const sessionId = this.getSessionId();
3232
- if (sessionId && this.sandbox?.send) {
3233
- this.sandbox
3234
- .send({
3235
- type: "trackInteraction",
3236
- interactionType: "findAll",
3230
+ if (sessionId && this.apiClient) {
3231
+ this.apiClient
3232
+ .req("interaction/track", {
3233
+ type: "findAll",
3237
3234
  session: sessionId,
3238
3235
  prompt: description,
3239
3236
  timestamp: absoluteTimestamp, // Absolute epoch timestamp - frontend calculates relative using clientStartDate
@@ -3274,11 +3271,10 @@ CAPTCHA_SOLVER_EOF`,
3274
3271
 
3275
3272
  // Track findAll error interaction (fire-and-forget, don't block)
3276
3273
  const sessionId = this.getSessionId();
3277
- if (sessionId && this.sandbox?.send) {
3278
- this.sandbox
3279
- .send({
3280
- type: "trackInteraction",
3281
- interactionType: "findAll",
3274
+ if (sessionId && this.apiClient) {
3275
+ this.apiClient
3276
+ .req("interaction/track", {
3277
+ type: "findAll",
3282
3278
  session: sessionId,
3283
3279
  prompt: description,
3284
3280
  timestamp: absoluteTimestamp, // Absolute epoch timestamp - frontend calculates relative using clientStartDate