askui 0.16.0 → 0.17.0

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.
Files changed (40) hide show
  1. package/dist/cjs/core/model/custom-element.js +2 -2
  2. package/dist/cjs/core/reporting/default-step.js +2 -2
  3. package/dist/cjs/execution/execution-runtime.js +1 -1
  4. package/dist/cjs/execution/inference-client.js +1 -1
  5. package/dist/cjs/execution/ui-control-client-dependency-builder.js +1 -1
  6. package/dist/cjs/execution/ui-control-client.d.ts +7 -0
  7. package/dist/cjs/execution/ui-control-client.js +13 -1
  8. package/dist/cjs/lib/download-binaries.d.ts +1 -1
  9. package/dist/cjs/lib/download-binaries.js +2 -2
  10. package/dist/cjs/lib/interactive_cli/cli-options-interface.d.ts +4 -3
  11. package/dist/cjs/lib/interactive_cli/cli.js +15 -7
  12. package/dist/cjs/lib/interactive_cli/create-example-project.d.ts +5 -3
  13. package/dist/cjs/lib/interactive_cli/create-example-project.js +32 -17
  14. package/dist/cjs/lib/logger.js +3 -3
  15. package/dist/cjs/lib/ui-controller-args.d.ts +3 -3
  16. package/dist/cjs/lib/ui-controller-args.js +4 -4
  17. package/dist/cjs/lib/ui-controller-facade.js +1 -1
  18. package/dist/cjs/utils/base_64_image/base-64-image.js +2 -2
  19. package/dist/cjs/utils/http/http-client-got.js +15 -15
  20. package/dist/esm/core/model/custom-element.js +2 -2
  21. package/dist/esm/core/reporting/default-step.js +2 -2
  22. package/dist/esm/execution/execution-runtime.js +1 -1
  23. package/dist/esm/execution/inference-client.js +1 -1
  24. package/dist/esm/execution/ui-control-client-dependency-builder.js +1 -1
  25. package/dist/esm/execution/ui-control-client.d.ts +7 -0
  26. package/dist/esm/execution/ui-control-client.js +13 -1
  27. package/dist/esm/lib/download-binaries.d.ts +1 -1
  28. package/dist/esm/lib/download-binaries.js +2 -2
  29. package/dist/esm/lib/interactive_cli/cli-options-interface.d.ts +4 -3
  30. package/dist/esm/lib/interactive_cli/cli.js +15 -7
  31. package/dist/esm/lib/interactive_cli/create-example-project.d.ts +5 -3
  32. package/dist/esm/lib/interactive_cli/create-example-project.js +32 -17
  33. package/dist/esm/lib/logger.js +3 -3
  34. package/dist/esm/lib/ui-controller-args.d.ts +3 -3
  35. package/dist/esm/lib/ui-controller-args.js +4 -4
  36. package/dist/esm/lib/ui-controller-facade.js +1 -1
  37. package/dist/esm/utils/base_64_image/base-64-image.js +2 -2
  38. package/dist/esm/utils/http/http-client-got.js +15 -15
  39. package/dist/example_projects_templates/configs/jest.config.ts +2 -2
  40. package/package.json +15 -3
@@ -48,7 +48,7 @@ class CustomElement {
48
48
  }
49
49
  exports.CustomElement = CustomElement;
50
50
  CustomElement.schema = (0, yup_1.object)({
51
- threshold: (0, yup_1.number)().optional().min(0).max(1),
52
- rotationDegreePerStep: (0, yup_1.number)().optional().min(0).lessThan(360),
53
51
  mask: (0, yup_1.array)().optional().min(3, 'mask must contain at least 3 points'),
52
+ rotationDegreePerStep: (0, yup_1.number)().optional().min(0).lessThan(360),
53
+ threshold: (0, yup_1.number)().optional().min(0).max(1),
54
54
  });
@@ -62,9 +62,9 @@ class DefaultStep {
62
62
  return (0, lodash_1.cloneDeep)(this);
63
63
  }
64
64
  onEnd(snapshot, error) {
65
- this.runs = [...this.runs.slice(0, -1), Object.assign(Object.assign({}, this.lastRun), { status: DefaultStep.determineLastRunStatus(error), end: snapshot, error,
65
+ this.runs = [...this.runs.slice(0, -1), Object.assign(Object.assign({}, this.lastRun), {
66
66
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
- duration: snapshot.createdAt.getTime() - this.lastRun.begin.createdAt.getTime() })];
67
+ duration: snapshot.createdAt.getTime() - this.lastRun.begin.createdAt.getTime(), end: snapshot, error, status: DefaultStep.determineLastRunStatus(error) })];
68
68
  return (0, lodash_1.cloneDeep)(this);
69
69
  }
70
70
  static determineLastRunStatus(error) {
@@ -144,8 +144,8 @@ class ExecutionRuntime {
144
144
  const annotation = this.isAnnotationRequired() ? yield this.annotateImage() : undefined;
145
145
  return {
146
146
  createdAt,
147
- screenshot,
148
147
  detectedElements: annotation === null || annotation === void 0 ? void 0 : annotation.detected_elements,
148
+ screenshot,
149
149
  };
150
150
  });
151
151
  }
@@ -63,9 +63,9 @@ class InferenceClient {
63
63
  return __awaiter(this, void 0, void 0, function* () {
64
64
  const resizedImage = yield this.resizeIfNeeded(customElements, image);
65
65
  const response = yield this.httpClient.post(this.urls.inference, {
66
+ customElements,
66
67
  image: resizedImage.base64Image,
67
68
  instruction,
68
- customElements,
69
69
  modelComposition: this.modelComposition,
70
70
  });
71
71
  InferenceClient.logMetaInformation(response);
@@ -52,7 +52,7 @@ class UiControlClientDependencyBuilder {
52
52
  static getClientArgsWithDefaults(clientArgs) {
53
53
  var _a, _b, _c;
54
54
  return __awaiter(this, void 0, void 0, function* () {
55
- return Object.assign(Object.assign({}, clientArgs), { uiControllerUrl: (_a = clientArgs.uiControllerUrl) !== null && _a !== void 0 ? _a : 'http://127.0.0.1:6769', inferenceServerUrl: (_b = clientArgs.inferenceServerUrl) !== null && _b !== void 0 ? _b : 'https://inference.askui.com', credentials: (0, read_credentials_1.readCredentials)(clientArgs), proxyAgents: (_c = clientArgs.proxyAgents) !== null && _c !== void 0 ? _c : (yield (0, proxy_builder_1.envProxyAgents)()) });
55
+ return Object.assign(Object.assign({}, clientArgs), { credentials: (0, read_credentials_1.readCredentials)(clientArgs), inferenceServerUrl: (_a = clientArgs.inferenceServerUrl) !== null && _a !== void 0 ? _a : 'https://inference.askui.com', proxyAgents: (_b = clientArgs.proxyAgents) !== null && _b !== void 0 ? _b : (yield (0, proxy_builder_1.envProxyAgents)()), uiControllerUrl: (_c = clientArgs.uiControllerUrl) !== null && _c !== void 0 ? _c : 'http://127.0.0.1:6769' });
56
56
  });
57
57
  }
58
58
  }
@@ -135,6 +135,13 @@ export declare class UiControlClient extends ApiCommands {
135
135
  * @param {string} placeholder - The textfields placeholder text.
136
136
  */
137
137
  clickTextfield(placeholder: string): Promise<void>;
138
+ /**
139
+ * Searches for an element of type textfield with a specific
140
+ * label nearest to it. If found, clicks it.
141
+ *
142
+ * @param {string} label - The textfields label.
143
+ */
144
+ clickTextfieldNearestTo(label: string): Promise<void>;
138
145
  /**
139
146
  * Clicks an icon based on a description.
140
147
  *
@@ -115,8 +115,8 @@ class UiControlClient extends dsl_1.ApiCommands {
115
115
  return __awaiter(this, void 0, void 0, function* () {
116
116
  return {
117
117
  customElements: yield custom_element_1.CustomElement.fromJsonListWithImagePathOrImage(customElementJson),
118
- value: instructionString,
119
118
  secretText: this.getAndResetSecretText(),
119
+ value: instructionString,
120
120
  valueHumanReadable: this.escapeSeparatorString(instructionString),
121
121
  };
122
122
  });
@@ -297,6 +297,18 @@ class UiControlClient extends dsl_1.ApiCommands {
297
297
  .exec();
298
298
  });
299
299
  }
300
+ /**
301
+ * Searches for an element of type textfield with a specific
302
+ * label nearest to it. If found, clicks it.
303
+ *
304
+ * @param {string} label - The textfields label.
305
+ */
306
+ clickTextfieldNearestTo(label) {
307
+ return __awaiter(this, void 0, void 0, function* () {
308
+ yield this.click().textfield().nearestTo().text(label)
309
+ .exec();
310
+ });
311
+ }
300
312
  /**
301
313
  * Clicks an icon based on a description.
302
314
  *
@@ -2,8 +2,8 @@
2
2
  import http from 'http';
3
3
  import https from 'https';
4
4
  declare enum SupportedPlatform {
5
- LINUX = "linux",
6
5
  DARWIN = "darwin",
6
+ LINUX = "linux",
7
7
  WIN32 = "win32"
8
8
  }
9
9
  export declare function platform(): SupportedPlatform;
@@ -23,13 +23,13 @@ const path_2 = require("../utils/path");
23
23
  const logger_1 = require("./logger");
24
24
  var SupportedPlatform;
25
25
  (function (SupportedPlatform) {
26
- SupportedPlatform["LINUX"] = "linux";
27
26
  SupportedPlatform["DARWIN"] = "darwin";
27
+ SupportedPlatform["LINUX"] = "linux";
28
28
  SupportedPlatform["WIN32"] = "win32";
29
29
  })(SupportedPlatform || (SupportedPlatform = {}));
30
30
  const binarySubPathsByPlatform = {
31
- linux: ['linux', 'askui-ui-controller.AppImage'],
32
31
  darwin: ['darwin', 'askui-ui-controller.dmg'],
32
+ linux: ['linux', 'askui-ui-controller.AppImage'],
33
33
  win32: ['windows', 'askui-ui-controller.exe'],
34
34
  };
35
35
  function isSupportedPlatform(value) {
@@ -1,8 +1,9 @@
1
1
  export interface CliOptions {
2
- skipCredentials: boolean;
3
- operatingSystem: 'windows' | 'linux' | 'macos';
4
- workspaceId: string;
5
2
  accessToken: string;
3
+ automationsDirectory: string;
4
+ operatingSystem: 'windows' | 'linux' | 'macos';
5
+ skipCredentials: boolean;
6
6
  testFramework: 'jest';
7
7
  typescriptConfig: boolean;
8
+ workspaceId: string;
8
9
  }
@@ -18,6 +18,7 @@ const commander_1 = require("commander");
18
18
  const fs_extra_1 = __importDefault(require("fs-extra"));
19
19
  const create_example_project_1 = require("./create-example-project");
20
20
  const nonEmpty = (subject) => (input) => input.trim().length > 0 || `${subject} is required.`;
21
+ /* eslint-disable sort-keys */
21
22
  const questions = [
22
23
  {
23
24
  type: 'list',
@@ -48,33 +49,40 @@ const questions = [
48
49
  when: (_answers) => fs_extra_1.default.existsSync('tsconfig.json'),
49
50
  },
50
51
  ];
52
+ /* eslint-enable */
51
53
  const options = [
52
54
  {
53
- option: '-f, --test-framework <value>',
54
55
  choices: ['jest'],
55
- description: 'the test framework to use.',
56
56
  default: 'jest',
57
+ description: 'the test framework to use.',
58
+ option: '-f, --test-framework <value>',
57
59
  },
58
60
  {
59
- option: '-sc, --skip-credentials',
60
61
  choices: [],
61
- description: 'skip the credentials setup.',
62
62
  default: false,
63
+ description: 'skip the credentials setup.',
64
+ option: '-sc, --skip-credentials',
63
65
  },
64
66
  {
65
- option: '-w, --workspace-id <value>',
66
67
  choices: [],
67
68
  description: 'a workspace id.',
69
+ option: '-w, --workspace-id <value>',
68
70
  },
69
71
  {
70
- option: '-a, --access-token <value>',
71
72
  choices: [],
72
73
  description: 'an access token for the workspace with the id.',
74
+ option: '-a, --access-token <value>',
75
+ },
76
+ {
77
+ choices: [],
78
+ default: 'askui_example',
79
+ description: 'a name for the directory askui stores its configuration and workflows in.',
80
+ option: '-ad, --automations-directory <value>',
73
81
  },
74
82
  {
75
- option: '-t, --typescript-config',
76
83
  choices: [],
77
84
  description: 'overwrite tsconfig.json flag',
85
+ option: '-t, --typescript-config',
78
86
  },
79
87
  ];
80
88
  const createProgram = () => {
@@ -1,12 +1,14 @@
1
1
  import { CliOptions } from './cli-options-interface';
2
2
  export declare class CreateExampleProject {
3
3
  readonly cliOptions: CliOptions;
4
- private distexampleFolderPath;
5
- private exampleFolderName;
6
- private baseDirPath;
4
+ private automationsDirectoryPath;
5
+ private exampleTemplateDirectoryName;
6
+ private automationsDirectoryName;
7
+ private projectRootDirectoryPath;
7
8
  private askUIControllerUrl;
8
9
  private helperTemplateConfig;
9
10
  constructor(cliOptions: CliOptions);
11
+ private getAutomationsDirectoryName;
10
12
  private copyTemplateProject;
11
13
  private copyTestFrameworkConfig;
12
14
  private addTestFrameWorkTimeout;
@@ -20,20 +20,31 @@ const child_process_1 = require("child_process");
20
20
  const listr_1 = __importDefault(require("listr"));
21
21
  const chalk_1 = __importDefault(require("chalk"));
22
22
  const nunjucks_1 = __importDefault(require("nunjucks"));
23
+ const yup_1 = require("yup");
23
24
  const path_2 = require("../../utils/path");
24
25
  const add_remove_script_package_json_1 = require("./add-remove-script-package-json");
25
26
  class CreateExampleProject {
26
27
  constructor(cliOptions) {
27
28
  this.cliOptions = cliOptions;
28
- this.baseDirPath = process.cwd();
29
- this.exampleFolderName = 'askui_example';
30
- this.distexampleFolderPath = path_1.default.join(this.baseDirPath, this.exampleFolderName);
29
+ this.exampleTemplateDirectoryName = 'askui_example';
30
+ this.projectRootDirectoryPath = process.cwd();
31
+ this.automationsDirectoryName = this.getAutomationsDirectoryName();
32
+ this.automationsDirectoryPath = path_1.default.join(this.projectRootDirectoryPath, this.automationsDirectoryName);
31
33
  this.askUIControllerUrl = 'https://docs.askui.com/docs/general/Components/AskUI-Controller';
32
34
  this.helperTemplateConfig = {};
33
35
  }
36
+ getAutomationsDirectoryName() {
37
+ if (this.cliOptions.automationsDirectory) {
38
+ if (/\s/g.test(this.cliOptions.automationsDirectory.trim())) {
39
+ throw new yup_1.ValidationError('Automations directory (-ad, --automations-directory) must not contain whitespaces');
40
+ }
41
+ return this.cliOptions.automationsDirectory.trim();
42
+ }
43
+ return this.exampleTemplateDirectoryName;
44
+ }
34
45
  copyTemplateProject() {
35
46
  return __awaiter(this, void 0, void 0, function* () {
36
- const exampleProjectPath = path_1.default.join('example_projects_templates', 'typescript', this.exampleFolderName);
47
+ const exampleProjectPath = path_1.default.join('example_projects_templates', 'typescript', this.exampleTemplateDirectoryName);
37
48
  const runCommand = (0, util_1.promisify)(child_process_1.exec);
38
49
  return [
39
50
  {
@@ -58,14 +69,14 @@ class CreateExampleProject {
58
69
  {
59
70
  title: 'Copy project files',
60
71
  task: () => __awaiter(this, void 0, void 0, function* () {
61
- return fs_extra_1.default.copy(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), exampleProjectPath), this.distexampleFolderPath);
72
+ return fs_extra_1.default.copy(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), exampleProjectPath), this.automationsDirectoryPath);
62
73
  }),
63
74
  },
64
75
  {
65
76
  title: 'Install askui dependency',
66
77
  task: () => __awaiter(this, void 0, void 0, function* () {
67
78
  yield runCommand('npm init -y');
68
- yield (0, add_remove_script_package_json_1.removeScript)(`${this.baseDirPath}/package.json`, 'test');
79
+ yield (0, add_remove_script_package_json_1.removeScript)(`${this.projectRootDirectoryPath}/package.json`, 'test');
69
80
  yield runCommand('npm i -D askui ');
70
81
  }),
71
82
  },
@@ -78,7 +89,7 @@ class CreateExampleProject {
78
89
  jest: 'jest.config.ts',
79
90
  };
80
91
  const configFilePath = path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), 'example_projects_templates', 'configs', frameworkConfigs.jest);
81
- yield fs_extra_1.default.copyFile(configFilePath, path_1.default.join(this.distexampleFolderPath, frameworkConfigs.jest));
92
+ yield fs_extra_1.default.copyFile(configFilePath, path_1.default.join(this.automationsDirectoryPath, frameworkConfigs.jest));
82
93
  });
83
94
  }
84
95
  addTestFrameWorkTimeout() {
@@ -100,14 +111,14 @@ class CreateExampleProject {
100
111
  addAskuiRunCommand() {
101
112
  return __awaiter(this, void 0, void 0, function* () {
102
113
  const frameworkExecutionCommand = {
103
- jest: `jest --config ./${this.exampleFolderName}/jest.config.ts --runInBand`,
114
+ jest: `jest --config ./${this.automationsDirectoryName}/jest.config.ts --runInBand`,
104
115
  };
105
- yield (0, add_remove_script_package_json_1.addScript)(`${this.baseDirPath}/package.json`, 'askui', frameworkExecutionCommand.jest);
116
+ yield (0, add_remove_script_package_json_1.addScript)(`${this.projectRootDirectoryPath}/package.json`, 'askui', frameworkExecutionCommand.jest);
106
117
  });
107
118
  }
108
119
  addESLintRunCommand() {
109
120
  return __awaiter(this, void 0, void 0, function* () {
110
- yield (0, add_remove_script_package_json_1.addScript)(`${this.baseDirPath}/package.json`, 'lint', 'eslint . --ext .ts');
121
+ yield (0, add_remove_script_package_json_1.addScript)(`${this.projectRootDirectoryPath}/package.json`, 'lint', 'eslint . --ext .ts');
111
122
  });
112
123
  }
113
124
  createAskUIHelperFromTemplate() {
@@ -126,9 +137,9 @@ class CreateExampleProject {
126
137
  }
127
138
  nunjucks_1.default.configure(askuiHelperTemplateFilePath, { autoescape: false });
128
139
  const result = nunjucks_1.default.render(templateFileName, this.helperTemplateConfig);
129
- const filePath = path_1.default.join(this.distexampleFolderPath, 'helpers', 'askui-helper.ts');
130
- if (!fs_extra_1.default.existsSync(path_1.default.join(this.distexampleFolderPath, 'helpers'))) {
131
- yield fs_extra_1.default.mkdir(path_1.default.join(this.distexampleFolderPath, 'helpers'));
140
+ const filePath = path_1.default.join(this.automationsDirectoryPath, 'helpers', 'askui-helper.ts');
141
+ if (!fs_extra_1.default.existsSync(path_1.default.join(this.automationsDirectoryPath, 'helpers'))) {
142
+ yield fs_extra_1.default.mkdir(path_1.default.join(this.automationsDirectoryPath, 'helpers'));
132
143
  }
133
144
  yield fs_extra_1.default.writeFile(filePath, result, 'utf8');
134
145
  }),
@@ -186,6 +197,7 @@ class CreateExampleProject {
186
197
  return __awaiter(this, void 0, void 0, function* () {
187
198
  return [
188
199
  {
200
+ /* eslint-disable sort-keys */
189
201
  title: 'Add user credentials',
190
202
  enabled: () => !this.cliOptions.skipCredentials,
191
203
  task: () => __awaiter(this, void 0, void 0, function* () {
@@ -195,6 +207,7 @@ class CreateExampleProject {
195
207
  },`;
196
208
  }),
197
209
  },
210
+ /* eslint-enable */
198
211
  ];
199
212
  });
200
213
  }
@@ -209,13 +222,13 @@ class CreateExampleProject {
209
222
  {
210
223
  title: 'Add eslintrc.json',
211
224
  task: () => __awaiter(this, void 0, void 0, function* () {
212
- return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintRcFilePath), path_1.default.join(this.baseDirPath, '.eslintrc.json'));
225
+ return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintRcFilePath), path_1.default.join(this.projectRootDirectoryPath, '.eslintrc.json'));
213
226
  }),
214
227
  },
215
228
  {
216
229
  title: 'Add .eslintignore',
217
230
  task: () => __awaiter(this, void 0, void 0, function* () {
218
- return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintIgnoreFilePath), path_1.default.join(this.baseDirPath, '.eslintignore'));
231
+ return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintIgnoreFilePath), path_1.default.join(this.projectRootDirectoryPath, '.eslintignore'));
219
232
  }),
220
233
  },
221
234
  ]);
@@ -227,7 +240,8 @@ class CreateExampleProject {
227
240
  copyTsConfigFile() {
228
241
  return __awaiter(this, void 0, void 0, function* () {
229
242
  const tsConfigFilePath = path_1.default.join('example_projects_templates', 'typescript', 'tsconfig.json');
230
- const tsConfigTargetFilePath = path_1.default.join(this.baseDirPath, 'tsconfig.json');
243
+ const tsConfigTargetFilePath = path_1.default.join(this.projectRootDirectoryPath, 'tsconfig.json');
244
+ /* eslint-disable sort-keys */
231
245
  return [
232
246
  {
233
247
  title: 'Copy ts config file',
@@ -239,6 +253,7 @@ class CreateExampleProject {
239
253
  ];
240
254
  });
241
255
  }
256
+ /* eslint-enable */
242
257
  createExampleProject() {
243
258
  return __awaiter(this, void 0, void 0, function* () {
244
259
  const tasks = new listr_1.default();
@@ -253,7 +268,7 @@ class CreateExampleProject {
253
268
  yield tasks.run();
254
269
  /* eslint-disable no-console */
255
270
  console.log(chalk_1.default.greenBright('\nCongratulations!'));
256
- console.log(`askui example was created under ${chalk_1.default.gray(this.distexampleFolderPath)}`);
271
+ console.log(`askui example was created under ${chalk_1.default.gray(this.automationsDirectoryPath)}`);
257
272
  if (this.cliOptions.operatingSystem === 'windows') {
258
273
  console.log(chalk_1.default.redBright(`\nPlease make sure the AskUI Controller is running: ${this.askUIControllerUrl}\n`));
259
274
  console.log(`You can start your automation with this command ${chalk_1.default.green('AskUI-RunProject')}`);
@@ -17,17 +17,17 @@ function isProcessEnvLogLevelValid() {
17
17
  }
18
18
  const stream = (0, pino_pretty_1.default)({
19
19
  colorize: true,
20
- translateTime: 'SYS:standard',
21
20
  ignore: 'pid,hostname,filename',
21
+ translateTime: 'SYS:standard',
22
22
  });
23
23
  const defaultLogLevel = 'info';
24
24
  const pinoLevel = isProcessEnvLogLevelValid() ? process.env['LOG_LEVEL'] : defaultLogLevel;
25
25
  const logger = (0, pino_1.default)({
26
- name: 'askuiUiControlClient',
27
- level: pinoLevel,
28
26
  customLevels: {
29
27
  verbose: 5,
30
28
  },
29
+ level: pinoLevel,
30
+ name: 'askuiUiControlClient',
31
31
  }, stream);
32
32
  exports.logger = logger;
33
33
  if (!(isProcessEnvLogLevelValid()) && process.env['LOG_LEVEL'] !== undefined) {
@@ -31,11 +31,11 @@ import { LogLevels } from '../shared/log-levels';
31
31
  * @param {ProxyAgentArgs} proxyAgents - To configure the proxy agents for our http(s) requests.
32
32
  */
33
33
  export interface UiControllerArgs {
34
- readonly display?: number;
35
34
  readonly actionDelayInMs?: number;
36
35
  readonly binaryVersion?: string;
37
- readonly port?: number;
36
+ readonly display?: number;
38
37
  readonly host?: string;
38
+ readonly port?: number;
39
39
  readonly minimize?: boolean;
40
40
  readonly overWriteBinary?: boolean;
41
41
  readonly logLevel?: LogLevels;
@@ -43,9 +43,9 @@ export interface UiControllerArgs {
43
43
  readonly proxyAgents?: ProxyAgentArgs;
44
44
  }
45
45
  export interface UiControllerArgsWithDefaults extends UiControllerArgs {
46
- readonly display: number;
47
46
  readonly actionDelayInMs: number;
48
47
  readonly binaryVersion: string;
48
+ readonly display: number;
49
49
  readonly overWriteBinary: boolean;
50
50
  readonly port: number;
51
51
  readonly host: string;
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createCliFlagsFromArgs = exports.createArgsWithDefaults = void 0;
4
4
  function createArgsWithDefaults(args) {
5
5
  const defaults = {
6
+ actionDelayInMs: 1000,
6
7
  binaryVersion: 'latest',
7
8
  display: 0,
8
- actionDelayInMs: 1000,
9
- overWriteBinary: false,
10
- minimize: true,
11
- port: 6769,
12
9
  host: '127.0.0.1',
13
10
  logLevel: 'debug',
11
+ minimize: true,
12
+ overWriteBinary: false,
13
+ port: 6769,
14
14
  };
15
15
  return Object.assign(defaults, args);
16
16
  }
@@ -89,9 +89,9 @@ class UiControllerFacade {
89
89
  ? maxWaitingForStartingInSeconds * 1000 : this.DefaultmaxWaitingForStartingInMs;
90
90
  (0, wait_port_1.default)({
91
91
  host: args.host,
92
+ output: (process === null || process === void 0 ? void 0 : process.env['LOG_LEVEL']) === 'verbose' ? 'dots' : 'silent',
92
93
  port: args.port,
93
94
  timeout: timeoutInMs,
94
- output: (process === null || process === void 0 ? void 0 : process.env['LOG_LEVEL']) === 'verbose' ? 'dots' : 'silent',
95
95
  }).then((open) => {
96
96
  if (open) {
97
97
  logger_1.logger.info('The Control UI Server has been started.');
@@ -69,9 +69,9 @@ class Base64Image {
69
69
  const { width, height } = yield this.getInfo();
70
70
  const buffer = yield (yield this.getSharp())
71
71
  .resize({
72
- width: width >= height ? dimension : undefined,
73
- height: height > width ? dimension : undefined,
74
72
  fit: 'contain',
73
+ height: height > width ? dimension : undefined,
74
+ width: width >= height ? dimension : undefined,
75
75
  })
76
76
  .toBuffer();
77
77
  return Base64Image.fromBuffer(buffer);
@@ -33,19 +33,6 @@ class HttpClientGot {
33
33
  buildGotExtendOptions(proxyAgents) {
34
34
  const gotExtendOptions = {
35
35
  retry: {
36
- limit: 5,
37
- methods: ['POST', 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE'],
38
- statusCodes: [408, 413, 429, 500, 502, 503, 504, 521, 522, 524],
39
- errorCodes: [
40
- 'ETIMEDOUT',
41
- 'ECONNRESET',
42
- 'EADDRINUSE',
43
- 'ECONNREFUSED',
44
- 'EPIPE',
45
- 'ENOTFOUND',
46
- 'ENETUNREACH',
47
- 'EAI_AGAIN',
48
- ],
49
36
  calculateDelay: ({ attemptCount, retryOptions, error, computedValue, }) => {
50
37
  var _a, _b, _c;
51
38
  if (attemptCount > retryOptions.limit
@@ -60,6 +47,19 @@ class HttpClientGot {
60
47
  lib_1.logger.debug(`Request to ${(_c = error.request) === null || _c === void 0 ? void 0 : _c.requestUrl} failed.\n${error.message}\nRetrying... (attempt ${attemptCount})`);
61
48
  return computedValue;
62
49
  },
50
+ errorCodes: [
51
+ 'ETIMEDOUT',
52
+ 'ECONNRESET',
53
+ 'EADDRINUSE',
54
+ 'ECONNREFUSED',
55
+ 'EPIPE',
56
+ 'ENOTFOUND',
57
+ 'ENETUNREACH',
58
+ 'EAI_AGAIN',
59
+ ],
60
+ limit: 5,
61
+ methods: ['POST', 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE'],
62
+ statusCodes: [408, 413, 429, 500, 502, 503, 504, 521, 522, 524],
63
63
  },
64
64
  };
65
65
  if (proxyAgents) {
@@ -88,7 +88,7 @@ class HttpClientGot {
88
88
  .forEach((cookie) => {
89
89
  cookieJar.setCookieSync(cookie, url);
90
90
  });
91
- return Object.assign(Object.assign({}, options), { headers: this.headers, cookieJar });
91
+ return Object.assign(Object.assign({}, options), { cookieJar, headers: this.headers });
92
92
  }
93
93
  post(url, data) {
94
94
  return __awaiter(this, void 0, void 0, function* () {
@@ -104,7 +104,7 @@ class HttpClientGot {
104
104
  if (statusCode !== 200) {
105
105
  throw (0, custom_errors_1.httpClientErrorHandler)(statusCode, JSON.stringify(body));
106
106
  }
107
- return { headers, body };
107
+ return { body, headers };
108
108
  });
109
109
  }
110
110
  get(url, options = { responseType: 'json' }) {
@@ -44,7 +44,7 @@ export class CustomElement {
44
44
  }
45
45
  }
46
46
  CustomElement.schema = object({
47
- threshold: number().optional().min(0).max(1),
48
- rotationDegreePerStep: number().optional().min(0).lessThan(360),
49
47
  mask: array().optional().min(3, 'mask must contain at least 3 points'),
48
+ rotationDegreePerStep: number().optional().min(0).lessThan(360),
49
+ threshold: number().optional().min(0).max(1),
50
50
  });
@@ -59,9 +59,9 @@ export class DefaultStep {
59
59
  return cloneDeep(this);
60
60
  }
61
61
  onEnd(snapshot, error) {
62
- this.runs = [...this.runs.slice(0, -1), Object.assign(Object.assign({}, this.lastRun), { status: DefaultStep.determineLastRunStatus(error), end: snapshot, error,
62
+ this.runs = [...this.runs.slice(0, -1), Object.assign(Object.assign({}, this.lastRun), {
63
63
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
64
- duration: snapshot.createdAt.getTime() - this.lastRun.begin.createdAt.getTime() })];
64
+ duration: snapshot.createdAt.getTime() - this.lastRun.begin.createdAt.getTime(), end: snapshot, error, status: DefaultStep.determineLastRunStatus(error) })];
65
65
  return cloneDeep(this);
66
66
  }
67
67
  static determineLastRunStatus(error) {
@@ -141,8 +141,8 @@ export class ExecutionRuntime {
141
141
  const annotation = this.isAnnotationRequired() ? yield this.annotateImage() : undefined;
142
142
  return {
143
143
  createdAt,
144
- screenshot,
145
144
  detectedElements: annotation === null || annotation === void 0 ? void 0 : annotation.detected_elements,
145
+ screenshot,
146
146
  };
147
147
  });
148
148
  }
@@ -57,9 +57,9 @@ export class InferenceClient {
57
57
  return __awaiter(this, void 0, void 0, function* () {
58
58
  const resizedImage = yield this.resizeIfNeeded(customElements, image);
59
59
  const response = yield this.httpClient.post(this.urls.inference, {
60
+ customElements,
60
61
  image: resizedImage.base64Image,
61
62
  instruction,
62
- customElements,
63
63
  modelComposition: this.modelComposition,
64
64
  });
65
65
  InferenceClient.logMetaInformation(response);
@@ -49,7 +49,7 @@ export class UiControlClientDependencyBuilder {
49
49
  static getClientArgsWithDefaults(clientArgs) {
50
50
  var _a, _b, _c;
51
51
  return __awaiter(this, void 0, void 0, function* () {
52
- return Object.assign(Object.assign({}, clientArgs), { uiControllerUrl: (_a = clientArgs.uiControllerUrl) !== null && _a !== void 0 ? _a : 'http://127.0.0.1:6769', inferenceServerUrl: (_b = clientArgs.inferenceServerUrl) !== null && _b !== void 0 ? _b : 'https://inference.askui.com', credentials: readCredentials(clientArgs), proxyAgents: (_c = clientArgs.proxyAgents) !== null && _c !== void 0 ? _c : (yield envProxyAgents()) });
52
+ return Object.assign(Object.assign({}, clientArgs), { credentials: readCredentials(clientArgs), inferenceServerUrl: (_a = clientArgs.inferenceServerUrl) !== null && _a !== void 0 ? _a : 'https://inference.askui.com', proxyAgents: (_b = clientArgs.proxyAgents) !== null && _b !== void 0 ? _b : (yield envProxyAgents()), uiControllerUrl: (_c = clientArgs.uiControllerUrl) !== null && _c !== void 0 ? _c : 'http://127.0.0.1:6769' });
53
53
  });
54
54
  }
55
55
  }
@@ -135,6 +135,13 @@ export declare class UiControlClient extends ApiCommands {
135
135
  * @param {string} placeholder - The textfields placeholder text.
136
136
  */
137
137
  clickTextfield(placeholder: string): Promise<void>;
138
+ /**
139
+ * Searches for an element of type textfield with a specific
140
+ * label nearest to it. If found, clicks it.
141
+ *
142
+ * @param {string} label - The textfields label.
143
+ */
144
+ clickTextfieldNearestTo(label: string): Promise<void>;
138
145
  /**
139
146
  * Clicks an icon based on a description.
140
147
  *
@@ -112,8 +112,8 @@ export class UiControlClient extends ApiCommands {
112
112
  return __awaiter(this, void 0, void 0, function* () {
113
113
  return {
114
114
  customElements: yield CustomElement.fromJsonListWithImagePathOrImage(customElementJson),
115
- value: instructionString,
116
115
  secretText: this.getAndResetSecretText(),
116
+ value: instructionString,
117
117
  valueHumanReadable: this.escapeSeparatorString(instructionString),
118
118
  };
119
119
  });
@@ -294,6 +294,18 @@ export class UiControlClient extends ApiCommands {
294
294
  .exec();
295
295
  });
296
296
  }
297
+ /**
298
+ * Searches for an element of type textfield with a specific
299
+ * label nearest to it. If found, clicks it.
300
+ *
301
+ * @param {string} label - The textfields label.
302
+ */
303
+ clickTextfieldNearestTo(label) {
304
+ return __awaiter(this, void 0, void 0, function* () {
305
+ yield this.click().textfield().nearestTo().text(label)
306
+ .exec();
307
+ });
308
+ }
297
309
  /**
298
310
  * Clicks an icon based on a description.
299
311
  *
@@ -2,8 +2,8 @@
2
2
  import http from 'http';
3
3
  import https from 'https';
4
4
  declare enum SupportedPlatform {
5
- LINUX = "linux",
6
5
  DARWIN = "darwin",
6
+ LINUX = "linux",
7
7
  WIN32 = "win32"
8
8
  }
9
9
  export declare function platform(): SupportedPlatform;
@@ -17,13 +17,13 @@ import { getPathToNodeModulesRoot } from '../utils/path';
17
17
  import { logger } from './logger';
18
18
  var SupportedPlatform;
19
19
  (function (SupportedPlatform) {
20
- SupportedPlatform["LINUX"] = "linux";
21
20
  SupportedPlatform["DARWIN"] = "darwin";
21
+ SupportedPlatform["LINUX"] = "linux";
22
22
  SupportedPlatform["WIN32"] = "win32";
23
23
  })(SupportedPlatform || (SupportedPlatform = {}));
24
24
  const binarySubPathsByPlatform = {
25
- linux: ['linux', 'askui-ui-controller.AppImage'],
26
25
  darwin: ['darwin', 'askui-ui-controller.dmg'],
26
+ linux: ['linux', 'askui-ui-controller.AppImage'],
27
27
  win32: ['windows', 'askui-ui-controller.exe'],
28
28
  };
29
29
  function isSupportedPlatform(value) {
@@ -1,8 +1,9 @@
1
1
  export interface CliOptions {
2
- skipCredentials: boolean;
3
- operatingSystem: 'windows' | 'linux' | 'macos';
4
- workspaceId: string;
5
2
  accessToken: string;
3
+ automationsDirectory: string;
4
+ operatingSystem: 'windows' | 'linux' | 'macos';
5
+ skipCredentials: boolean;
6
6
  testFramework: 'jest';
7
7
  typescriptConfig: boolean;
8
+ workspaceId: string;
8
9
  }
@@ -12,6 +12,7 @@ import { Command, Option } from 'commander';
12
12
  import fs from 'fs-extra';
13
13
  import { CreateExampleProject } from './create-example-project';
14
14
  const nonEmpty = (subject) => (input) => input.trim().length > 0 || `${subject} is required.`;
15
+ /* eslint-disable sort-keys */
15
16
  const questions = [
16
17
  {
17
18
  type: 'list',
@@ -42,33 +43,40 @@ const questions = [
42
43
  when: (_answers) => fs.existsSync('tsconfig.json'),
43
44
  },
44
45
  ];
46
+ /* eslint-enable */
45
47
  const options = [
46
48
  {
47
- option: '-f, --test-framework <value>',
48
49
  choices: ['jest'],
49
- description: 'the test framework to use.',
50
50
  default: 'jest',
51
+ description: 'the test framework to use.',
52
+ option: '-f, --test-framework <value>',
51
53
  },
52
54
  {
53
- option: '-sc, --skip-credentials',
54
55
  choices: [],
55
- description: 'skip the credentials setup.',
56
56
  default: false,
57
+ description: 'skip the credentials setup.',
58
+ option: '-sc, --skip-credentials',
57
59
  },
58
60
  {
59
- option: '-w, --workspace-id <value>',
60
61
  choices: [],
61
62
  description: 'a workspace id.',
63
+ option: '-w, --workspace-id <value>',
62
64
  },
63
65
  {
64
- option: '-a, --access-token <value>',
65
66
  choices: [],
66
67
  description: 'an access token for the workspace with the id.',
68
+ option: '-a, --access-token <value>',
69
+ },
70
+ {
71
+ choices: [],
72
+ default: 'askui_example',
73
+ description: 'a name for the directory askui stores its configuration and workflows in.',
74
+ option: '-ad, --automations-directory <value>',
67
75
  },
68
76
  {
69
- option: '-t, --typescript-config',
70
77
  choices: [],
71
78
  description: 'overwrite tsconfig.json flag',
79
+ option: '-t, --typescript-config',
72
80
  },
73
81
  ];
74
82
  const createProgram = () => {
@@ -1,12 +1,14 @@
1
1
  import { CliOptions } from './cli-options-interface';
2
2
  export declare class CreateExampleProject {
3
3
  readonly cliOptions: CliOptions;
4
- private distexampleFolderPath;
5
- private exampleFolderName;
6
- private baseDirPath;
4
+ private automationsDirectoryPath;
5
+ private exampleTemplateDirectoryName;
6
+ private automationsDirectoryName;
7
+ private projectRootDirectoryPath;
7
8
  private askUIControllerUrl;
8
9
  private helperTemplateConfig;
9
10
  constructor(cliOptions: CliOptions);
11
+ private getAutomationsDirectoryName;
10
12
  private copyTemplateProject;
11
13
  private copyTestFrameworkConfig;
12
14
  private addTestFrameWorkTimeout;
@@ -14,20 +14,31 @@ import { exec } from 'child_process';
14
14
  import Listr from 'listr';
15
15
  import chalk from 'chalk';
16
16
  import nunjucks from 'nunjucks';
17
+ import { ValidationError } from 'yup';
17
18
  import { getPathToNodeModulesRoot } from '../../utils/path';
18
19
  import { addScript, removeScript } from './add-remove-script-package-json';
19
20
  export class CreateExampleProject {
20
21
  constructor(cliOptions) {
21
22
  this.cliOptions = cliOptions;
22
- this.baseDirPath = process.cwd();
23
- this.exampleFolderName = 'askui_example';
24
- this.distexampleFolderPath = path.join(this.baseDirPath, this.exampleFolderName);
23
+ this.exampleTemplateDirectoryName = 'askui_example';
24
+ this.projectRootDirectoryPath = process.cwd();
25
+ this.automationsDirectoryName = this.getAutomationsDirectoryName();
26
+ this.automationsDirectoryPath = path.join(this.projectRootDirectoryPath, this.automationsDirectoryName);
25
27
  this.askUIControllerUrl = 'https://docs.askui.com/docs/general/Components/AskUI-Controller';
26
28
  this.helperTemplateConfig = {};
27
29
  }
30
+ getAutomationsDirectoryName() {
31
+ if (this.cliOptions.automationsDirectory) {
32
+ if (/\s/g.test(this.cliOptions.automationsDirectory.trim())) {
33
+ throw new ValidationError('Automations directory (-ad, --automations-directory) must not contain whitespaces');
34
+ }
35
+ return this.cliOptions.automationsDirectory.trim();
36
+ }
37
+ return this.exampleTemplateDirectoryName;
38
+ }
28
39
  copyTemplateProject() {
29
40
  return __awaiter(this, void 0, void 0, function* () {
30
- const exampleProjectPath = path.join('example_projects_templates', 'typescript', this.exampleFolderName);
41
+ const exampleProjectPath = path.join('example_projects_templates', 'typescript', this.exampleTemplateDirectoryName);
31
42
  const runCommand = promisify(exec);
32
43
  return [
33
44
  {
@@ -52,14 +63,14 @@ export class CreateExampleProject {
52
63
  {
53
64
  title: 'Copy project files',
54
65
  task: () => __awaiter(this, void 0, void 0, function* () {
55
- return fs.copy(path.join(getPathToNodeModulesRoot(), exampleProjectPath), this.distexampleFolderPath);
66
+ return fs.copy(path.join(getPathToNodeModulesRoot(), exampleProjectPath), this.automationsDirectoryPath);
56
67
  }),
57
68
  },
58
69
  {
59
70
  title: 'Install askui dependency',
60
71
  task: () => __awaiter(this, void 0, void 0, function* () {
61
72
  yield runCommand('npm init -y');
62
- yield removeScript(`${this.baseDirPath}/package.json`, 'test');
73
+ yield removeScript(`${this.projectRootDirectoryPath}/package.json`, 'test');
63
74
  yield runCommand('npm i -D askui ');
64
75
  }),
65
76
  },
@@ -72,7 +83,7 @@ export class CreateExampleProject {
72
83
  jest: 'jest.config.ts',
73
84
  };
74
85
  const configFilePath = path.join(getPathToNodeModulesRoot(), 'example_projects_templates', 'configs', frameworkConfigs.jest);
75
- yield fs.copyFile(configFilePath, path.join(this.distexampleFolderPath, frameworkConfigs.jest));
86
+ yield fs.copyFile(configFilePath, path.join(this.automationsDirectoryPath, frameworkConfigs.jest));
76
87
  });
77
88
  }
78
89
  addTestFrameWorkTimeout() {
@@ -94,14 +105,14 @@ export class CreateExampleProject {
94
105
  addAskuiRunCommand() {
95
106
  return __awaiter(this, void 0, void 0, function* () {
96
107
  const frameworkExecutionCommand = {
97
- jest: `jest --config ./${this.exampleFolderName}/jest.config.ts --runInBand`,
108
+ jest: `jest --config ./${this.automationsDirectoryName}/jest.config.ts --runInBand`,
98
109
  };
99
- yield addScript(`${this.baseDirPath}/package.json`, 'askui', frameworkExecutionCommand.jest);
110
+ yield addScript(`${this.projectRootDirectoryPath}/package.json`, 'askui', frameworkExecutionCommand.jest);
100
111
  });
101
112
  }
102
113
  addESLintRunCommand() {
103
114
  return __awaiter(this, void 0, void 0, function* () {
104
- yield addScript(`${this.baseDirPath}/package.json`, 'lint', 'eslint . --ext .ts');
115
+ yield addScript(`${this.projectRootDirectoryPath}/package.json`, 'lint', 'eslint . --ext .ts');
105
116
  });
106
117
  }
107
118
  createAskUIHelperFromTemplate() {
@@ -120,9 +131,9 @@ export class CreateExampleProject {
120
131
  }
121
132
  nunjucks.configure(askuiHelperTemplateFilePath, { autoescape: false });
122
133
  const result = nunjucks.render(templateFileName, this.helperTemplateConfig);
123
- const filePath = path.join(this.distexampleFolderPath, 'helpers', 'askui-helper.ts');
124
- if (!fs.existsSync(path.join(this.distexampleFolderPath, 'helpers'))) {
125
- yield fs.mkdir(path.join(this.distexampleFolderPath, 'helpers'));
134
+ const filePath = path.join(this.automationsDirectoryPath, 'helpers', 'askui-helper.ts');
135
+ if (!fs.existsSync(path.join(this.automationsDirectoryPath, 'helpers'))) {
136
+ yield fs.mkdir(path.join(this.automationsDirectoryPath, 'helpers'));
126
137
  }
127
138
  yield fs.writeFile(filePath, result, 'utf8');
128
139
  }),
@@ -180,6 +191,7 @@ export class CreateExampleProject {
180
191
  return __awaiter(this, void 0, void 0, function* () {
181
192
  return [
182
193
  {
194
+ /* eslint-disable sort-keys */
183
195
  title: 'Add user credentials',
184
196
  enabled: () => !this.cliOptions.skipCredentials,
185
197
  task: () => __awaiter(this, void 0, void 0, function* () {
@@ -189,6 +201,7 @@ export class CreateExampleProject {
189
201
  },`;
190
202
  }),
191
203
  },
204
+ /* eslint-enable */
192
205
  ];
193
206
  });
194
207
  }
@@ -203,13 +216,13 @@ export class CreateExampleProject {
203
216
  {
204
217
  title: 'Add eslintrc.json',
205
218
  task: () => __awaiter(this, void 0, void 0, function* () {
206
- return fs.copyFile(path.join(getPathToNodeModulesRoot(), esLintRcFilePath), path.join(this.baseDirPath, '.eslintrc.json'));
219
+ return fs.copyFile(path.join(getPathToNodeModulesRoot(), esLintRcFilePath), path.join(this.projectRootDirectoryPath, '.eslintrc.json'));
207
220
  }),
208
221
  },
209
222
  {
210
223
  title: 'Add .eslintignore',
211
224
  task: () => __awaiter(this, void 0, void 0, function* () {
212
- return fs.copyFile(path.join(getPathToNodeModulesRoot(), esLintIgnoreFilePath), path.join(this.baseDirPath, '.eslintignore'));
225
+ return fs.copyFile(path.join(getPathToNodeModulesRoot(), esLintIgnoreFilePath), path.join(this.projectRootDirectoryPath, '.eslintignore'));
213
226
  }),
214
227
  },
215
228
  ]);
@@ -221,7 +234,8 @@ export class CreateExampleProject {
221
234
  copyTsConfigFile() {
222
235
  return __awaiter(this, void 0, void 0, function* () {
223
236
  const tsConfigFilePath = path.join('example_projects_templates', 'typescript', 'tsconfig.json');
224
- const tsConfigTargetFilePath = path.join(this.baseDirPath, 'tsconfig.json');
237
+ const tsConfigTargetFilePath = path.join(this.projectRootDirectoryPath, 'tsconfig.json');
238
+ /* eslint-disable sort-keys */
225
239
  return [
226
240
  {
227
241
  title: 'Copy ts config file',
@@ -233,6 +247,7 @@ export class CreateExampleProject {
233
247
  ];
234
248
  });
235
249
  }
250
+ /* eslint-enable */
236
251
  createExampleProject() {
237
252
  return __awaiter(this, void 0, void 0, function* () {
238
253
  const tasks = new Listr();
@@ -247,7 +262,7 @@ export class CreateExampleProject {
247
262
  yield tasks.run();
248
263
  /* eslint-disable no-console */
249
264
  console.log(chalk.greenBright('\nCongratulations!'));
250
- console.log(`askui example was created under ${chalk.gray(this.distexampleFolderPath)}`);
265
+ console.log(`askui example was created under ${chalk.gray(this.automationsDirectoryPath)}`);
251
266
  if (this.cliOptions.operatingSystem === 'windows') {
252
267
  console.log(chalk.redBright(`\nPlease make sure the AskUI Controller is running: ${this.askUIControllerUrl}\n`));
253
268
  console.log(`You can start your automation with this command ${chalk.green('AskUI-RunProject')}`);
@@ -11,17 +11,17 @@ function isProcessEnvLogLevelValid() {
11
11
  }
12
12
  const stream = pretty({
13
13
  colorize: true,
14
- translateTime: 'SYS:standard',
15
14
  ignore: 'pid,hostname,filename',
15
+ translateTime: 'SYS:standard',
16
16
  });
17
17
  const defaultLogLevel = 'info';
18
18
  const pinoLevel = isProcessEnvLogLevelValid() ? process.env['LOG_LEVEL'] : defaultLogLevel;
19
19
  const logger = pino({
20
- name: 'askuiUiControlClient',
21
- level: pinoLevel,
22
20
  customLevels: {
23
21
  verbose: 5,
24
22
  },
23
+ level: pinoLevel,
24
+ name: 'askuiUiControlClient',
25
25
  }, stream);
26
26
  if (!(isProcessEnvLogLevelValid()) && process.env['LOG_LEVEL'] !== undefined) {
27
27
  logger.warn(`"${process.env['LOG_LEVEL']}" is not supported as log level. Supported log levels: ${SupportedLogValues.join(', ')}`);
@@ -31,11 +31,11 @@ import { LogLevels } from '../shared/log-levels';
31
31
  * @param {ProxyAgentArgs} proxyAgents - To configure the proxy agents for our http(s) requests.
32
32
  */
33
33
  export interface UiControllerArgs {
34
- readonly display?: number;
35
34
  readonly actionDelayInMs?: number;
36
35
  readonly binaryVersion?: string;
37
- readonly port?: number;
36
+ readonly display?: number;
38
37
  readonly host?: string;
38
+ readonly port?: number;
39
39
  readonly minimize?: boolean;
40
40
  readonly overWriteBinary?: boolean;
41
41
  readonly logLevel?: LogLevels;
@@ -43,9 +43,9 @@ export interface UiControllerArgs {
43
43
  readonly proxyAgents?: ProxyAgentArgs;
44
44
  }
45
45
  export interface UiControllerArgsWithDefaults extends UiControllerArgs {
46
- readonly display: number;
47
46
  readonly actionDelayInMs: number;
48
47
  readonly binaryVersion: string;
48
+ readonly display: number;
49
49
  readonly overWriteBinary: boolean;
50
50
  readonly port: number;
51
51
  readonly host: string;
@@ -1,13 +1,13 @@
1
1
  export function createArgsWithDefaults(args) {
2
2
  const defaults = {
3
+ actionDelayInMs: 1000,
3
4
  binaryVersion: 'latest',
4
5
  display: 0,
5
- actionDelayInMs: 1000,
6
- overWriteBinary: false,
7
- minimize: true,
8
- port: 6769,
9
6
  host: '127.0.0.1',
10
7
  logLevel: 'debug',
8
+ minimize: true,
9
+ overWriteBinary: false,
10
+ port: 6769,
11
11
  };
12
12
  return Object.assign(defaults, args);
13
13
  }
@@ -83,9 +83,9 @@ export class UiControllerFacade {
83
83
  ? maxWaitingForStartingInSeconds * 1000 : this.DefaultmaxWaitingForStartingInMs;
84
84
  waitPort({
85
85
  host: args.host,
86
+ output: (process === null || process === void 0 ? void 0 : process.env['LOG_LEVEL']) === 'verbose' ? 'dots' : 'silent',
86
87
  port: args.port,
87
88
  timeout: timeoutInMs,
88
- output: (process === null || process === void 0 ? void 0 : process.env['LOG_LEVEL']) === 'verbose' ? 'dots' : 'silent',
89
89
  }).then((open) => {
90
90
  if (open) {
91
91
  logger.info('The Control UI Server has been started.');
@@ -63,9 +63,9 @@ export class Base64Image {
63
63
  const { width, height } = yield this.getInfo();
64
64
  const buffer = yield (yield this.getSharp())
65
65
  .resize({
66
- width: width >= height ? dimension : undefined,
67
- height: height > width ? dimension : undefined,
68
66
  fit: 'contain',
67
+ height: height > width ? dimension : undefined,
68
+ width: width >= height ? dimension : undefined,
69
69
  })
70
70
  .toBuffer();
71
71
  return Base64Image.fromBuffer(buffer);
@@ -27,19 +27,6 @@ export class HttpClientGot {
27
27
  buildGotExtendOptions(proxyAgents) {
28
28
  const gotExtendOptions = {
29
29
  retry: {
30
- limit: 5,
31
- methods: ['POST', 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE'],
32
- statusCodes: [408, 413, 429, 500, 502, 503, 504, 521, 522, 524],
33
- errorCodes: [
34
- 'ETIMEDOUT',
35
- 'ECONNRESET',
36
- 'EADDRINUSE',
37
- 'ECONNREFUSED',
38
- 'EPIPE',
39
- 'ENOTFOUND',
40
- 'ENETUNREACH',
41
- 'EAI_AGAIN',
42
- ],
43
30
  calculateDelay: ({ attemptCount, retryOptions, error, computedValue, }) => {
44
31
  var _a, _b, _c;
45
32
  if (attemptCount > retryOptions.limit
@@ -54,6 +41,19 @@ export class HttpClientGot {
54
41
  logger.debug(`Request to ${(_c = error.request) === null || _c === void 0 ? void 0 : _c.requestUrl} failed.\n${error.message}\nRetrying... (attempt ${attemptCount})`);
55
42
  return computedValue;
56
43
  },
44
+ errorCodes: [
45
+ 'ETIMEDOUT',
46
+ 'ECONNRESET',
47
+ 'EADDRINUSE',
48
+ 'ECONNREFUSED',
49
+ 'EPIPE',
50
+ 'ENOTFOUND',
51
+ 'ENETUNREACH',
52
+ 'EAI_AGAIN',
53
+ ],
54
+ limit: 5,
55
+ methods: ['POST', 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE'],
56
+ statusCodes: [408, 413, 429, 500, 502, 503, 504, 521, 522, 524],
57
57
  },
58
58
  };
59
59
  if (proxyAgents) {
@@ -82,7 +82,7 @@ export class HttpClientGot {
82
82
  .forEach((cookie) => {
83
83
  cookieJar.setCookieSync(cookie, url);
84
84
  });
85
- return Object.assign(Object.assign({}, options), { headers: this.headers, cookieJar });
85
+ return Object.assign(Object.assign({}, options), { cookieJar, headers: this.headers });
86
86
  }
87
87
  post(url, data) {
88
88
  return __awaiter(this, void 0, void 0, function* () {
@@ -98,7 +98,7 @@ export class HttpClientGot {
98
98
  if (statusCode !== 200) {
99
99
  throw httpClientErrorHandler(statusCode, JSON.stringify(body));
100
100
  }
101
- return { headers, body };
101
+ return { body, headers };
102
102
  });
103
103
  }
104
104
  get(url, options = { responseType: 'json' }) {
@@ -2,11 +2,11 @@ import type { Config } from '@jest/types';
2
2
 
3
3
  const config: Config.InitialOptions = {
4
4
  preset: 'ts-jest',
5
- testEnvironment: '@askui/jest-allure-circus',
6
- setupFilesAfterEnv: ['./helpers/askui-helper.ts'],
7
5
  sandboxInjectedGlobals: [
8
6
  'Math',
9
7
  ],
8
+ setupFilesAfterEnv: ['./helpers/askui-helper.ts'],
9
+ testEnvironment: '@askui/jest-allure-circus',
10
10
  };
11
11
 
12
12
  // eslint-disable-next-line import/no-default-export
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "askui",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "license": "MIT",
5
5
  "author": "askui GmbH <info@askui.com> (http://www.askui.com/)",
6
6
  "description": "Reliable, automated end-to-end-testing that depends on what is shown on your screen instead of the technology you are running on",
@@ -40,7 +40,9 @@
40
40
  "lint": "eslint --cache --fix --max-warnings 0 \"./**/*.{js,ts}\"",
41
41
  "lint:staged": "lint-staged",
42
42
  "test": "NODE_EXTRA_CA_CERTS='test/proxy/certs/unit_test.pem' jest '/src'",
43
- "postinstall": "node -e \"require('./bin/askui-postinstall')\""
43
+ "postinstall": "node -e \"require('./bin/askui-postinstall')\"",
44
+ "release:prerelease": "release-it --preRelease=next",
45
+ "release": "release-it"
44
46
  },
45
47
  "files": [
46
48
  "dist/cjs/",
@@ -62,7 +64,7 @@
62
64
  "nunjucks": "3.2.4",
63
65
  "pino": "8.19.0",
64
66
  "pino-pretty": "10.3.1",
65
- "tough-cookie": "^4.1.3",
67
+ "tough-cookie": "4.1.3",
66
68
  "url-join": "4.0.1",
67
69
  "wait-port": "0.2.9",
68
70
  "ws": "^7.5.9",
@@ -80,11 +82,21 @@
80
82
  "@types/sharp": "0.30.4",
81
83
  "@types/webrtc": "0.0.30",
82
84
  "@types/ws": "7.4.4",
85
+ "@typescript-eslint/eslint-plugin": "5.10.0",
86
+ "@typescript-eslint/parser": "5.10.0",
87
+ "@release-it/bumper": "6.0.1",
88
+ "@release-it/conventional-changelog": "8.0.1",
89
+ "eslint": "8.7.0",
90
+ "eslint-config-airbnb-base": "15.0.0",
91
+ "eslint-config-airbnb-typescript": "16.1.0",
92
+ "eslint-plugin-import": "2.25.4",
83
93
  "hpagent": "^1.2.0",
84
94
  "jest": "29.7.0",
85
95
  "jest-extended": "^4.0.1",
96
+ "lint-staged": "15.2.2",
86
97
  "proxy": "^1.0.2",
87
98
  "proxy-agent": "^6.3.1",
99
+ "release-it": "17.0.3",
88
100
  "shx": "0.3.4",
89
101
  "ts-jest": "29.1.2",
90
102
  "typescript": "4.5.4"