testdriverai 5.4.1 → 5.4.2

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
@@ -53,6 +53,7 @@ const { emitter, events } = require("./lib/events.js");
53
53
 
54
54
  const logger = log.logger;
55
55
 
56
+ let thisFile;
56
57
  let lastPrompt = "";
57
58
  let terminalApp = "";
58
59
  let commandHistory = [];
@@ -110,12 +111,6 @@ let getArgs = () => {
110
111
  }
111
112
 
112
113
  if (!args[file]) {
113
- // make testdriver directory if it doesn't exist
114
- let testdriverFolder = path.join(workingDir, "testdriver");
115
- if (!fs.existsSync(testdriverFolder)) {
116
- fs.mkdirSync(testdriverFolder);
117
- }
118
-
119
114
  args[file] = "testdriver/testdriver.yaml";
120
115
  }
121
116
 
@@ -130,21 +125,6 @@ let getArgs = () => {
130
125
  return { command: args[command], file: args[file] };
131
126
  };
132
127
 
133
- let a = getArgs();
134
-
135
- let thisFile = a.file;
136
- const thisCommand = a.command;
137
-
138
- logger.info(chalk.green(`Howdy! I'm TestDriver v${package.version}`));
139
- logger.info(`This is beta software!`);
140
- logger.info("");
141
- logger.info(chalk.yellow(`Join our Discord for help`));
142
- logger.info(`https://discord.com/invite/cWDFW8DzPm`);
143
- logger.info("");
144
-
145
- // individual run ID for this session
146
- // let runID = new Date().getTime();
147
-
148
128
  function fileCompleter(line) {
149
129
  line = line.slice(5); // remove /run
150
130
  const lastSepIndex = line.lastIndexOf(path.sep);
@@ -407,14 +387,13 @@ const executeCommands = async (
407
387
  executionHistory[executionHistory.length - 1]?.commands.push(command);
408
388
  }
409
389
 
410
- if (!dry) {
411
- await runCommand(command, depth, shouldSave);
412
- }
413
-
414
390
  if (shouldSave) {
415
391
  await save({ silent: true });
416
392
  }
417
393
 
394
+ if (!dry) {
395
+ await runCommand(command, depth, shouldSave);
396
+ }
418
397
  let timeToComplete = (new Date().getTime() - lastCommand) / 1000;
419
398
  // logger.info(timeToComplete, 'seconds')
420
399
 
@@ -526,6 +505,10 @@ const loadYML = async (file) => {
526
505
  process.env["TD_INTERPOLATION_VARS"] || "{}",
527
506
  );
528
507
 
508
+ if (!yml) {
509
+ return {};
510
+ }
511
+
529
512
  yml = await parser.validateYAML(yml);
530
513
 
531
514
  // Inject environment variables into any ${VAR} strings
@@ -781,10 +764,10 @@ const ensureMacScreenPerms = async () => {
781
764
 
782
765
  logger.info(chalk.red("Screen capture permissions not enabled."));
783
766
  logger.info(
784
- "You must enable screen capture permissions for the application calling `testdriverai`.",
767
+ "You must enable screen capture permissions for this terminal application within System Settings.",
785
768
  );
786
769
  logger.info(
787
- "Read More: https://docs.testdriver.ai/faq/screen-recording-permissions-mac-only",
770
+ "Navigate to System Settings > Privacy & Security > Screen Recording and enable screen recording permissions for the terminal you are using to run this command.",
788
771
  );
789
772
  analytics.track("noMacPermissions");
790
773
  return exit();
@@ -797,6 +780,7 @@ const ensureMacScreenPerms = async () => {
797
780
  // simple function to backfill the chat history with a prompt and
798
781
  // then call `promptUser()` to get the user input
799
782
  const firstPrompt = async () => {
783
+
800
784
  // readline is what allows us to get user input
801
785
  rl = readline.createInterface({
802
786
  terminal: true,
@@ -807,8 +791,6 @@ const firstPrompt = async () => {
807
791
  completer,
808
792
  });
809
793
 
810
- analytics.track("first prompt");
811
-
812
794
  rl.on("SIGINT", async () => {
813
795
  analytics.track("sigint");
814
796
  await exit(false);
@@ -902,6 +884,7 @@ const firstPrompt = async () => {
902
884
  }
903
885
 
904
886
  setTerminalWindowTransparency(false);
887
+
905
888
  promptUser();
906
889
  };
907
890
 
@@ -924,18 +907,17 @@ const firstPrompt = async () => {
924
907
 
925
908
  let yml = fs.readFileSync(thisFile, "utf-8");
926
909
 
927
- let markdown = `\`\`\`yaml
928
- ${yml}
929
- \`\`\``;
910
+ if (yml) {
930
911
 
931
- logger.info(`Loaded test script ${thisFile}\n`);
932
-
933
- log.prettyMarkdown(`
934
-
935
- ${markdown}
912
+ let markdown = `\`\`\`yaml
913
+ ${yml}\`\`\``;
914
+
915
+ logger.info(`Loaded test script ${thisFile}\n`);
916
+ log.prettyMarkdown(markdown);
917
+ logger.info("New commands will be appended.")
918
+ console.log('')
936
919
 
937
- New commands will be appended.
938
- `);
920
+ }
939
921
  }
940
922
 
941
923
  promptUser();
@@ -1156,7 +1138,7 @@ ${yaml.dump(step)}
1156
1138
 
1157
1139
  const promptUser = () => {
1158
1140
  emitter.emit(events.interactive, true);
1159
- rl.prompt(true);
1141
+ process.nextTick(() => rl.prompt());
1160
1142
  };
1161
1143
 
1162
1144
  const setTerminalApp = async (win) => {
@@ -1235,6 +1217,45 @@ const start = async () => {
1235
1217
  // process.exit();
1236
1218
  // }
1237
1219
 
1220
+ let a = getArgs();
1221
+
1222
+ // make testdriver directory if it doesn't exist
1223
+ let testdriverFolder = path.join(workingDir, "testdriver");
1224
+ if (!fs.existsSync(testdriverFolder)) {
1225
+
1226
+ console.log('does not exist')
1227
+
1228
+ fs.mkdirSync(testdriverFolder);
1229
+ // log
1230
+ logger.info(chalk.dim(`Created testdriver directory`));
1231
+ console.log(
1232
+ chalk.dim(`Created testdriver directory: ${testdriverFolder}`),
1233
+ );
1234
+
1235
+ }
1236
+
1237
+ // if testdriver.yaml doesn't exist, make it
1238
+ let testdriverFile = path.join(testdriverFolder, "testdriver.yaml");
1239
+ if (!fs.existsSync(testdriverFile)) {
1240
+ fs.writeFileSync(testdriverFile, "");
1241
+ logger.info(chalk.dim(`Created testdriver.yaml`));
1242
+ console.log(chalk.dim(`Created testdriver.yaml: ${testdriverFile}`));
1243
+ }
1244
+
1245
+ thisFile = a.file;
1246
+ const thisCommand = a.command;
1247
+
1248
+ logger.info(chalk.green(`Howdy! I'm TestDriver v${package.version}`));
1249
+ logger.info(`This is beta software!`);
1250
+ logger.info("");
1251
+ logger.info(chalk.yellow(`Join our Discord for help`));
1252
+ logger.info(`https://discord.com/invite/cWDFW8DzPm`);
1253
+ logger.info("");
1254
+
1255
+ // individual run ID for this session
1256
+ // let runID = new Date().getTime();
1257
+
1258
+
1238
1259
  // await sdk.auth();
1239
1260
  if (thisCommand !== "run") {
1240
1261
  speak("Howdy! I am TestDriver version " + package.version);
@@ -1242,6 +1263,7 @@ const start = async () => {
1242
1263
 
1243
1264
  if (thisCommand !== "init" && thisCommand !== "upload-secrets") {
1244
1265
  logger.info(chalk.dim(`Working on ${thisFile}`));
1266
+ console.log("");
1245
1267
 
1246
1268
  loadYML(thisFile)
1247
1269
 
@@ -1249,11 +1271,11 @@ const start = async () => {
1249
1271
  logger.info(
1250
1272
  chalk.red("Warning! ") +
1251
1273
  chalk.dim(
1252
- "Local mode sends screenshots of the desktop to our API. Set `TD_VM=true` to run in a secure VM.",
1274
+ "Local mode sends screenshots of the desktop to our API. Set `TD_VM` to run in a secure VM.",
1253
1275
  ),
1254
1276
  );
1255
1277
  logger.info(
1256
- chalk.dim("https://docs.testdriver.ai/security-and-privacy/agent"),
1278
+ chalk.dim("Read More: https://docs.testdriver.ai/security-and-privacy/agent"),
1257
1279
  );
1258
1280
  logger.info("");
1259
1281
  }
package/lib/system.js CHANGED
@@ -162,7 +162,9 @@ const initializeActiveWindow = async () => {
162
162
  // For some reason, the import fails in certain situations
163
163
  const activeWindow = await import("get-windows")
164
164
  .then(({ activeWindow }) => activeWindow)
165
- .catch(() => null);
165
+ .catch(() => {
166
+ return null;
167
+ });
166
168
  activeWindowFn = activeWindow;
167
169
  }
168
170
  return activeWindowFn;
@@ -174,7 +176,14 @@ const activeWin = async () => {
174
176
  return "error getting active window, proceed normally";
175
177
  } else {
176
178
  const activeWindow = await initializeActiveWindow();
177
- return await activeWindow?.();
179
+ let windows;
180
+ try {
181
+ windows = await activeWindow?.();
182
+ } catch (e) {
183
+ console.error("Error getting active window", e);
184
+ return "error getting active window, proceed normally";
185
+ }
186
+ return windows;
178
187
  }
179
188
  };
180
189
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "5.4.1",
3
+ "version": "5.4.2",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "index.js",
6
6
  "bin": {
package/schema.json CHANGED
@@ -70,26 +70,26 @@
70
70
  "keys": {
71
71
  "type": "array",
72
72
  "items": {
73
- "type": "string"
74
- },
75
- "enum": [
76
- [
77
- "backspace", "delete", "enter", "tab", "escape", "up", "down", "right", "left",
78
- "home", "end", "pageup", "pagedown", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
79
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19",
80
- "f20", "f21", "f22", "f23", "f24", "capslock", "command", "alt", "right_alt",
81
- "control", "left_control", "right_control", "shift", "right_shift", "space",
82
- "printscreen", "insert", "menu", "audio_mute", "audio_vol_down", "audio_vol_up",
83
- "audio_play", "audio_stop", "audio_pause", "audio_prev", "audio_next",
84
- "audio_rewind", "audio_forward", "audio_repeat", "audio_random", "numpad_lock",
85
- "numpad_0", "numpad_1", "numpad_2", "numpad_3", "numpad_4", "numpad_5",
86
- "numpad_6", "numpad_7", "numpad_8", "numpad_9", "numpad_+", "numpad_-",
87
- "numpad_*", "numpad_/", "numpad_.", "lights_mon_up", "lights_mon_down",
88
- "lights_kbd_toggle", "lights_kbd_up", "lights_kbd_down", "a", "b", "c", "d", "e",
89
- "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
90
- "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
73
+ "type": "string",
74
+ "enum": [
75
+ [
76
+ "backspace", "delete", "enter", "tab", "escape", "up", "down", "right", "left",
77
+ "home", "end", "pageup", "pagedown", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
78
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19",
79
+ "f20", "f21", "f22", "f23", "f24", "capslock", "command", "alt", "right_alt",
80
+ "control", "left_control", "right_control", "shift", "right_shift", "space",
81
+ "printscreen", "insert", "menu", "audio_mute", "audio_vol_down", "audio_vol_up",
82
+ "audio_play", "audio_stop", "audio_pause", "audio_prev", "audio_next",
83
+ "audio_rewind", "audio_forward", "audio_repeat", "audio_random", "numpad_lock",
84
+ "numpad_0", "numpad_1", "numpad_2", "numpad_3", "numpad_4", "numpad_5",
85
+ "numpad_6", "numpad_7", "numpad_8", "numpad_9", "numpad_+", "numpad_-",
86
+ "numpad_*", "numpad_/", "numpad_.", "lights_mon_up", "lights_mon_down",
87
+ "lights_kbd_toggle", "lights_kbd_up", "lights_kbd_down", "a", "b", "c", "d", "e",
88
+ "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
89
+ "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
90
+ ]
91
91
  ]
92
- ]
92
+ }
93
93
  }
94
94
  },
95
95
  "required": [