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.
- package/dist/cjs/core/model/custom-element.js +2 -2
- package/dist/cjs/core/reporting/default-step.js +2 -2
- package/dist/cjs/execution/execution-runtime.js +1 -1
- package/dist/cjs/execution/inference-client.js +1 -1
- package/dist/cjs/execution/ui-control-client-dependency-builder.js +1 -1
- package/dist/cjs/execution/ui-control-client.d.ts +7 -0
- package/dist/cjs/execution/ui-control-client.js +13 -1
- package/dist/cjs/lib/download-binaries.d.ts +1 -1
- package/dist/cjs/lib/download-binaries.js +2 -2
- package/dist/cjs/lib/interactive_cli/cli-options-interface.d.ts +4 -3
- package/dist/cjs/lib/interactive_cli/cli.js +15 -7
- package/dist/cjs/lib/interactive_cli/create-example-project.d.ts +5 -3
- package/dist/cjs/lib/interactive_cli/create-example-project.js +32 -17
- package/dist/cjs/lib/logger.js +3 -3
- package/dist/cjs/lib/ui-controller-args.d.ts +3 -3
- package/dist/cjs/lib/ui-controller-args.js +4 -4
- package/dist/cjs/lib/ui-controller-facade.js +1 -1
- package/dist/cjs/utils/base_64_image/base-64-image.js +2 -2
- package/dist/cjs/utils/http/http-client-got.js +15 -15
- package/dist/esm/core/model/custom-element.js +2 -2
- package/dist/esm/core/reporting/default-step.js +2 -2
- package/dist/esm/execution/execution-runtime.js +1 -1
- package/dist/esm/execution/inference-client.js +1 -1
- package/dist/esm/execution/ui-control-client-dependency-builder.js +1 -1
- package/dist/esm/execution/ui-control-client.d.ts +7 -0
- package/dist/esm/execution/ui-control-client.js +13 -1
- package/dist/esm/lib/download-binaries.d.ts +1 -1
- package/dist/esm/lib/download-binaries.js +2 -2
- package/dist/esm/lib/interactive_cli/cli-options-interface.d.ts +4 -3
- package/dist/esm/lib/interactive_cli/cli.js +15 -7
- package/dist/esm/lib/interactive_cli/create-example-project.d.ts +5 -3
- package/dist/esm/lib/interactive_cli/create-example-project.js +32 -17
- package/dist/esm/lib/logger.js +3 -3
- package/dist/esm/lib/ui-controller-args.d.ts +3 -3
- package/dist/esm/lib/ui-controller-args.js +4 -4
- package/dist/esm/lib/ui-controller-facade.js +1 -1
- package/dist/esm/utils/base_64_image/base-64-image.js +2 -2
- package/dist/esm/utils/http/http-client-got.js +15 -15
- package/dist/example_projects_templates/configs/jest.config.ts +2 -2
- 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), {
|
|
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), {
|
|
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
|
*
|
|
@@ -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
|
|
5
|
-
private
|
|
6
|
-
private
|
|
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.
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
114
|
+
jest: `jest --config ./${this.automationsDirectoryName}/jest.config.ts --runInBand`,
|
|
104
115
|
};
|
|
105
|
-
yield (0, add_remove_script_package_json_1.addScript)(`${this.
|
|
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.
|
|
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.
|
|
130
|
-
if (!fs_extra_1.default.existsSync(path_1.default.join(this.
|
|
131
|
-
yield fs_extra_1.default.mkdir(path_1.default.join(this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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')}`);
|
package/dist/cjs/lib/logger.js
CHANGED
|
@@ -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
|
|
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
|
|
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 {
|
|
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), {
|
|
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), {
|
|
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
|
*
|
|
@@ -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
|
|
5
|
-
private
|
|
6
|
-
private
|
|
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.
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
108
|
+
jest: `jest --config ./${this.automationsDirectoryName}/jest.config.ts --runInBand`,
|
|
98
109
|
};
|
|
99
|
-
yield addScript(`${this.
|
|
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.
|
|
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.
|
|
124
|
-
if (!fs.existsSync(path.join(this.
|
|
125
|
-
yield fs.mkdir(path.join(this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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')}`);
|
package/dist/esm/lib/logger.js
CHANGED
|
@@ -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
|
|
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
|
|
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 {
|
|
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.
|
|
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": "
|
|
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"
|