testdriverai 5.6.2 → 5.6.3

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/agent.js CHANGED
@@ -233,14 +233,14 @@ const haveAIResolveError = async (
233
233
 
234
234
  let safeKey = JSON.stringify(eMessage);
235
235
  errorCounts[safeKey] = errorCounts[safeKey] ? errorCounts[safeKey] + 1 : 1;
236
+
237
+ logger.error(chalk.red("Error detected"));
236
238
 
237
- logger.error(eMessage);
239
+ log.prettyMarkdown(eMessage);
238
240
 
239
241
  logger.debug("%j", error);
240
242
  logger.debug("%s", error.stack);
241
243
 
242
- log.prettyMarkdown(eMessage);
243
-
244
244
  // if we get the same error 3 times in `run` mode, we exit
245
245
  if (errorCounts[safeKey] > errorLimit - 1) {
246
246
  logger.info(chalk.red("Error loop detected. Exiting."));
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: macOS Automation Limitations
3
+ description: Understanding the limitations of synthetic input automation on macOS when using tools like robot.js in TestDriver.
4
+ ---
5
+
6
+ # macOS Automation Limitations
7
+
8
+ macOS includes several system-level security features that affect how synthetic input—like mouse clicks and keyboard presses generated by automation tools—is interpreted. If you're using tools like `robot.js` for test automation, it's important to understand which applications and interactions may be blocked or ignored by the system.
9
+
10
+ ## 🔐 System-Level Protected Apps
11
+
12
+ Some macOS applications are **heavily protected** by System Integrity Protection (SIP) and will **not respond to synthetic input**, even if Accessibility permissions are granted.
13
+
14
+ Examples include:
15
+
16
+ - **Finder**
17
+ - **System Settings / System Preferences**
18
+ - **Dock**
19
+ - **Menu Bar**
20
+ - **Login Window**
21
+ - **Launchpad**
22
+ - **Installer**
23
+ - **File Open / Save Dialogs**
24
+
25
+ These apps typically ignore input generated by tools like `robot.js` or even AppleScript unless scripted via system-sanctioned methods.
26
+
27
+ <Alert type="warning" title="Heads up">
28
+ Synthetic double-clicks often fail in Finder, even when the correct timing and coordinates are used.
29
+ </Alert>
30
+
31
+ ## 🛡️ TCC-Protected Applications
32
+
33
+ Apps protected by Transparency, Consent, and Control (TCC) **can be automated** if the right permissions are granted.
34
+
35
+ To enable automation for these apps:
36
+
37
+ 1. Go to **System Settings > Privacy & Security > Accessibility**
38
+ 2. Add and check the app or terminal running your automation (e.g., Terminal, iTerm, VS Code).
39
+ 3. You may also need to grant:
40
+ - **Input Monitoring**
41
+ - **Screen Recording**
42
+ - **Full Disk Access**
43
+
44
+ These permissions allow tools like `robot.js` to simulate clicks, keystrokes, and screen interactions in:
45
+
46
+ - **Google Chrome**
47
+ - **Safari**
48
+ - **Slack**
49
+ - **Mail**
50
+ - **Calendar**
51
+ - **Notes**
52
+ - **VS Code**
53
+ - **Xcode**
54
+
55
+ ## ⚙️ Best Targets for UI Automation
56
+
57
+ For reliable automation, use `robot.js` or TestDriver with:
58
+
59
+ - Chromium-based browsers (Chrome, Brave, Edge)
60
+ - Electron apps (Slack, Discord)
61
+ - Most third-party GUI apps
62
+ - Terminal emulators
63
+
64
+ These apps typically respect synthetic input when appropriate permissions are granted.
65
+
66
+ ## 🚫 Actions That Can't Be Automated
67
+
68
+ macOS enforces strict security policies on certain sensitive UI elements. Automation is **not possible** for:
69
+
70
+ - Login screen interactions
71
+ - Security permission prompts (e.g., “Allow Screen Recording”)
72
+ - Password input in secure dialogs
73
+ - Force Quit window
74
+ - Crash reporter popups
75
+
76
+ ## ✅ Recommendations
77
+
78
+ - Always **grant Accessibility permissions** to the app or terminal running `robot.js`.
79
+ - Use **AppleScript** for system apps like Finder or System Settings.
80
+ - For GUI testing, prefer apps that are not protected by SIP.
81
+ - Consider using native tools like **XCUITest** or **Appium** for native macOS apps.
82
+
83
+ <Alert type="info" title="Need Help?">
84
+ If you're running into automation issues in specific apps, reach out on Discord or contact the TestDriver team.
85
+ </Alert>
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+
2
3
  const config = require("./lib/config.js");
3
4
  // We need to initialize the IPC server quickly
4
5
  require("./lib/ipc.js");
package/lib/commander.js CHANGED
@@ -250,7 +250,7 @@ commands:
250
250
  return response;
251
251
 
252
252
  } catch (error) {
253
- logger.error(error);
253
+ logger.debug(error);
254
254
  throw error;
255
255
  }
256
256
  }
package/lib/commands.js CHANGED
@@ -233,6 +233,9 @@ const scroll = async (direction = "down", amount = 300, method = "mouse") => {
233
233
  // perform a mouse click
234
234
  // click, right-click, double-click, hover
235
235
  const click = async (x, y, action = "click") => {
236
+
237
+ emitter.emit(events.interactive, true);
238
+
236
239
  await redraw.start();
237
240
 
238
241
  let button = "left";
@@ -256,6 +259,7 @@ const click = async (x, y, action = "click") => {
256
259
  config.TD_VM
257
260
  ? await sandbox.send({ type: "moveMouse", x, y })
258
261
  : await robot.moveMouseSmooth(x, y, 0.1);
262
+
259
263
  emitter.emit(events.mouseMove, { x, y });
260
264
 
261
265
  await delay(1000); // wait for the mouse to move
@@ -286,8 +290,10 @@ const click = async (x, y, action = "click") => {
286
290
  } else if (action === "drag-end") {
287
291
  robot.mouseToggle("up", button);
288
292
  } else {
293
+
289
294
  robot.mouseClick(button, double);
290
295
  }
296
+
291
297
  }
292
298
 
293
299
  emitter.emit(events.mouseClick, { x, y, button, click });
@@ -299,6 +305,9 @@ const click = async (x, y, action = "click") => {
299
305
  }
300
306
 
301
307
  await redraw.wait(5000);
308
+
309
+ emitter.emit(events.interactive, false);
310
+
302
311
  return;
303
312
  };
304
313
 
@@ -49,7 +49,7 @@ async function focusApplication(appName) {
49
49
  if (config.TD_VM) {
50
50
  let result = await sandbox.send({type: "commands.run", command: `/home/user/scripts/control_window.sh "${appName}" Focus`});
51
51
  if (result.type == "error") {
52
- logger.error(result.error.result.stdout);
52
+ logger.debug(result.error.result.stdout);
53
53
  }
54
54
 
55
55
  return;
@@ -65,7 +65,7 @@ async function focusApplication(appName) {
65
65
  return runPwsh(appName, "Focus");
66
66
  }
67
67
  } catch (error) {
68
- logger.error(error);
68
+ logger.debug(error);
69
69
  }
70
70
  }
71
71
 
@@ -79,7 +79,7 @@ async function hideTerminal(appName) {
79
79
  return runPwsh(appName, "Minimize");
80
80
  }
81
81
  } catch (error) {
82
- logger.error(error);
82
+ logger.debug(error);
83
83
  }
84
84
  }
85
85
  }
@@ -88,12 +88,14 @@ async function showTerminal(appName) {
88
88
  if (!config.TD_VM) {
89
89
  try {
90
90
  if (platform() == "mac") {
91
- return await execSync(`osascript -e '${appleScriptActivate(appName)}'`);
91
+ await execSync(`osascript -e '${appleScriptActivate(appName)}'`);
92
+ await execSync(`osascript -e '${appleScriptSetFrontmost(appName)}'`);
93
+
92
94
  } else if (platform() == "windows") {
93
95
  return runPwsh(appName, "Restore");
94
96
  }
95
97
  } catch (error) {
96
- logger.error(error);
98
+ logger.debug(error);
97
99
  }
98
100
  }
99
101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "5.6.2",
3
+ "version": "5.6.3",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "index.js",
6
6
  "bin": {