testdriverai 7.3.35 → 7.3.37

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,16 @@
1
+ ## [7.3.37](https://github.com/testdriverai/testdriverai/compare/v7.3.36...v7.3.37) (2026-02-24)
2
+
3
+
4
+
5
+ ## [7.3.36](https://github.com/testdriverai/testdriverai/compare/v7.3.35...v7.3.36) (2026-02-24)
6
+
7
+
8
+ ### Reverts
9
+
10
+ * Revert "Fix hanging node processes on Ctrl+C (#654)" (#683) ([5e68748](https://github.com/testdriverai/testdriverai/commit/5e6874825c6718e006bbf84e2ba5edae57d173ac)), closes [#654](https://github.com/testdriverai/testdriverai/issues/654) [#683](https://github.com/testdriverai/testdriverai/issues/683)
11
+
12
+
13
+
1
14
  ## [7.3.35](https://github.com/testdriverai/testdriverai/compare/v7.3.34...v7.3.35) (2026-02-24)
2
15
 
3
16
 
@@ -128,11 +128,6 @@ const createSandbox = (emitter, analytics, sessionInstance) => {
128
128
  );
129
129
  }
130
130
  }, timeout);
131
- // Don't let pending message timeouts prevent Node process from exiting
132
- // (unref is not available in browser/non-Node environments)
133
- if (timeoutId.unref) {
134
- timeoutId.unref();
135
- }
136
131
 
137
132
  // Track timeout so close() can clear it
138
133
  this.pendingTimeouts.set(requestId, timeoutId);
@@ -365,11 +360,6 @@ const createSandbox = (emitter, analytics, sessionInstance) => {
365
360
  this.reconnecting = false;
366
361
  }
367
362
  }, delay);
368
- // Don't let the reconnect timer prevent Node process from exiting
369
- // (unref is not available in browser/non-Node environments)
370
- if (this.reconnectTimer.unref) {
371
- this.reconnectTimer.unref();
372
- }
373
363
  }
374
364
 
375
365
  /**
@@ -214,33 +214,6 @@ function cleanupConsoleSpy(client) {
214
214
  const testDriverInstances = new WeakMap();
215
215
  const lifecycleHandlers = new WeakMap();
216
216
 
217
- // Set to track all active TestDriver instances for signal-based cleanup
218
- const activeInstances = new Set();
219
-
220
- // Register signal handlers once to clean up all active instances on forced exit
221
- let signalHandlersRegistered = false;
222
- function registerSignalHandlers() {
223
- if (signalHandlersRegistered) return;
224
- signalHandlersRegistered = true;
225
-
226
- const cleanup = async () => {
227
- const instances = Array.from(activeInstances);
228
- activeInstances.clear();
229
- await Promise.race([
230
- Promise.all(instances.map((inst) => inst.disconnect().catch(() => {}))),
231
- new Promise((resolve) => setTimeout(resolve, 5000)), // 5s max for cleanup
232
- ]);
233
- };
234
-
235
- process.on("SIGINT", () => {
236
- cleanup().finally(() => process.exit(130));
237
- });
238
-
239
- process.on("SIGTERM", () => {
240
- cleanup().finally(() => process.exit(143));
241
- });
242
- }
243
-
244
217
  /**
245
218
  * Create a TestDriver client in a Vitest test with automatic lifecycle management
246
219
  *
@@ -318,8 +291,6 @@ export function TestDriver(context, options = {}) {
318
291
  testdriver.__vitestContext = context.task;
319
292
  testdriver._debugOnFailure = mergedOptions.debugOnFailure || false;
320
293
  testDriverInstances.set(context.task, testdriver);
321
- activeInstances.add(testdriver);
322
- registerSignalHandlers();
323
294
 
324
295
  // Set platform metadata early so the reporter can show the correct OS from the start
325
296
  if (!context.task.meta) {
@@ -455,9 +426,6 @@ export function TestDriver(context, options = {}) {
455
426
  // Clean up console spies
456
427
  cleanupConsoleSpy(currentInstance);
457
428
 
458
- // Remove from active instances tracking (even in debug mode we clean up tracking)
459
- activeInstances.delete(currentInstance);
460
-
461
429
  // DO NOT disconnect or terminate - keep sandbox alive for debugging
462
430
  return;
463
431
  }
@@ -584,8 +552,6 @@ export function TestDriver(context, options = {}) {
584
552
  } catch (error) {
585
553
  console.error("Error disconnecting client:", error);
586
554
  } finally {
587
- // Remove from active instances tracking
588
- activeInstances.delete(currentInstance);
589
555
  // Terminate AWS instance if one was spawned for this test
590
556
  // This must happen AFTER dashcam.stop() to ensure recording is saved
591
557
  // AND it must happen even if disconnect() fails
@@ -115,16 +115,16 @@ function cleanupAllInstances() {
115
115
  process.on("exit", cleanupAllInstances);
116
116
  process.on("SIGINT", () => {
117
117
  cleanupAllInstances();
118
- process.exit(130); // Restore default SIGINT exit behavior (128 + signal 2)
118
+ // Don't call process.exit here - let the signal handler do its job
119
119
  });
120
120
  process.on("SIGTERM", () => {
121
121
  cleanupAllInstances();
122
- process.exit(143); // Restore default SIGTERM exit behavior (128 + signal 15)
122
+ // Don't call process.exit here - let the signal handler do its job
123
123
  });
124
124
  process.on("uncaughtException", (error) => {
125
125
  console.error("[TestDriver] Uncaught exception:", error);
126
126
  cleanupAllInstances();
127
- process.exit(1); // Exit after uncaught exception cleanup
127
+ // Don't call process.exit here - let Node.js handle the exception
128
128
  });
129
129
 
130
130
  beforeEach(async (context) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "7.3.35",
3
+ "version": "7.3.37",
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
@@ -972,7 +972,7 @@ class Element {
972
972
  /**
973
973
  * Click on the element
974
974
  * @param {ClickAction} [action='click'] - Type of click action
975
- * @returns {Promise<void>}
975
+ * @returns {Promise<Element>} This element instance for chaining
976
976
  */
977
977
  async click(action = "click") {
978
978
  if (!this._found || !this.coordinates) {
@@ -1025,11 +1025,13 @@ class Element {
1025
1025
  elementData,
1026
1026
  );
1027
1027
  }
1028
+
1029
+ return this;
1028
1030
  }
1029
1031
 
1030
1032
  /**
1031
1033
  * Hover over the element
1032
- * @returns {Promise<void>}
1034
+ * @returns {Promise<Element>} This element instance for chaining
1033
1035
  */
1034
1036
  async hover() {
1035
1037
  if (!this._found || !this.coordinates) {
@@ -1066,11 +1068,13 @@ class Element {
1066
1068
  this.coordinates.y,
1067
1069
  elementData,
1068
1070
  );
1071
+
1072
+ return this;
1069
1073
  }
1070
1074
 
1071
1075
  /**
1072
1076
  * Double-click on the element
1073
- * @returns {Promise<void>}
1077
+ * @returns {Promise<Element>} This element instance for chaining
1074
1078
  */
1075
1079
  async doubleClick() {
1076
1080
  return this.click("double-click");
@@ -1078,7 +1082,7 @@ class Element {
1078
1082
 
1079
1083
  /**
1080
1084
  * Right-click on the element
1081
- * @returns {Promise<void>}
1085
+ * @returns {Promise<Element>} This element instance for chaining
1082
1086
  */
1083
1087
  async rightClick() {
1084
1088
  return this.click("right-click");
@@ -1086,7 +1090,7 @@ class Element {
1086
1090
 
1087
1091
  /**
1088
1092
  * Press mouse button down on this element
1089
- * @returns {Promise<void>}
1093
+ * @returns {Promise<Element>} This element instance for chaining
1090
1094
  */
1091
1095
  async mouseDown() {
1092
1096
  return this.click("mouseDown");
@@ -1094,7 +1098,7 @@ class Element {
1094
1098
 
1095
1099
  /**
1096
1100
  * Release mouse button on this element
1097
- * @returns {Promise<void>}
1101
+ * @returns {Promise<Element>} This element instance for chaining
1098
1102
  */
1099
1103
  async mouseUp() {
1100
1104
  return this.click("mouseUp");