askui 0.12.1 → 0.13.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/README.md +13 -19
- package/bin/askui +1 -1
- package/dist/cjs/core/model/test-case-dto/custom-element-json.d.ts +75 -0
- package/dist/cjs/core/model/test-case-dto/custom-element-json.js +2 -0
- package/dist/cjs/core/model/test-case-dto/custom-element.d.ts +21 -0
- package/dist/cjs/core/model/test-case-dto/custom-element.js +54 -0
- package/dist/cjs/core/model/test-case-dto/index.d.ts +3 -0
- package/dist/cjs/core/model/test-case-dto/index.js +5 -0
- package/dist/cjs/core/model/test-case-dto/test-step.d.ts +6 -0
- package/dist/cjs/core/model/test-case-dto/test-step.js +2 -0
- package/dist/cjs/core/model/test-case-result-dto/index.d.ts +2 -0
- package/dist/cjs/core/model/test-case-result-dto/index.js +7 -0
- package/dist/cjs/core/model/test-case-result-dto/test-step-result-dto.d.ts +9 -0
- package/dist/cjs/core/model/test-case-result-dto/test-step-result-dto.js +16 -0
- package/dist/cjs/core/model/test-case-result-dto/test-step-state.d.ts +4 -0
- package/dist/cjs/core/model/test-case-result-dto/test-step-state.js +8 -0
- package/dist/cjs/core/reporting/default-reporter.d.ts +10 -0
- package/dist/cjs/core/reporting/default-reporter.js +12 -0
- package/dist/cjs/execution/annotation-level.d.ts +5 -0
- package/dist/cjs/execution/annotation-level.js +9 -0
- package/dist/cjs/execution/ui-control-client-error.d.ts +2 -0
- package/dist/cjs/execution/ui-control-client-error.js +6 -0
- package/dist/cjs/lib/index.d.ts +1 -0
- package/dist/cjs/lib/index.js +3 -1
- package/dist/cjs/lib/interactive_cli/add-script-package-json.d.ts +1 -0
- package/dist/cjs/lib/interactive_cli/add-script-package-json.js +38 -0
- package/dist/cjs/lib/interactive_cli/cli-options-interface.d.ts +8 -0
- package/dist/cjs/lib/interactive_cli/cli-options-interface.js +2 -0
- package/dist/cjs/lib/interactive_cli/cli.d.ts +2 -0
- package/dist/cjs/lib/interactive_cli/cli.js +115 -0
- package/dist/cjs/lib/interactive_cli/create-example-project.d.ts +26 -0
- package/dist/cjs/lib/interactive_cli/create-example-project.js +293 -0
- package/dist/cjs/lib/interactive_cli/index.d.ts +1 -0
- package/dist/cjs/lib/interactive_cli/index.js +5 -0
- package/dist/cjs/lib/interactive_cli/replace-string-in-file.d.ts +1 -0
- package/dist/cjs/lib/interactive_cli/replace-string-in-file.js +31 -0
- package/dist/cjs/utils/base_64_image/base-64-image.d.ts +6 -9
- package/dist/cjs/utils/base_64_image/base-64-image.js +32 -33
- package/dist/cjs/utils/base_64_image/sharp.d.ts +2 -0
- package/dist/cjs/utils/base_64_image/sharp.js +56 -0
- package/dist/cjs/utils/proxy/proxy-builder.js +3 -1
- package/dist/cjs/utils/transformations.js +4 -2
- package/dist/esm/core/model/test-case-dto/custom-element-json.d.ts +75 -0
- package/dist/esm/core/model/test-case-dto/custom-element-json.js +1 -0
- package/dist/esm/core/model/test-case-dto/custom-element.d.ts +21 -0
- package/dist/esm/core/model/test-case-dto/custom-element.js +50 -0
- package/dist/esm/core/model/test-case-dto/index.d.ts +3 -0
- package/dist/esm/core/model/test-case-dto/index.js +1 -0
- package/dist/esm/core/model/test-case-dto/test-step.d.ts +6 -0
- package/dist/esm/core/model/test-case-dto/test-step.js +1 -0
- package/dist/esm/core/model/test-case-result-dto/index.d.ts +2 -0
- package/dist/esm/core/model/test-case-result-dto/index.js +2 -0
- package/dist/esm/core/model/test-case-result-dto/test-step-result-dto.d.ts +9 -0
- package/dist/esm/core/model/test-case-result-dto/test-step-result-dto.js +12 -0
- package/dist/esm/core/model/test-case-result-dto/test-step-state.d.ts +4 -0
- package/dist/esm/core/model/test-case-result-dto/test-step-state.js +5 -0
- package/dist/esm/core/reporting/default-reporter.d.ts +10 -0
- package/dist/esm/core/reporting/default-reporter.js +9 -0
- package/dist/esm/execution/annotation-level.d.ts +5 -0
- package/dist/esm/execution/annotation-level.js +6 -0
- package/dist/esm/execution/ui-control-client-error.d.ts +2 -0
- package/dist/esm/execution/ui-control-client-error.js +2 -0
- package/dist/esm/lib/index.d.ts +1 -0
- package/dist/esm/lib/index.js +1 -0
- package/dist/esm/lib/interactive_cli/add-script-package-json.d.ts +1 -0
- package/dist/esm/lib/interactive_cli/add-script-package-json.js +31 -0
- package/dist/esm/lib/interactive_cli/cli-options-interface.d.ts +8 -0
- package/dist/esm/lib/interactive_cli/cli-options-interface.js +1 -0
- package/dist/esm/lib/interactive_cli/cli.d.ts +2 -0
- package/dist/esm/lib/interactive_cli/cli.js +108 -0
- package/dist/esm/lib/interactive_cli/create-example-project.d.ts +26 -0
- package/dist/esm/lib/interactive_cli/create-example-project.js +286 -0
- package/dist/esm/lib/interactive_cli/index.d.ts +1 -0
- package/dist/esm/lib/interactive_cli/index.js +1 -0
- package/dist/esm/lib/interactive_cli/replace-string-in-file.d.ts +1 -0
- package/dist/esm/lib/interactive_cli/replace-string-in-file.js +24 -0
- package/dist/esm/utils/base_64_image/base-64-image.d.ts +6 -9
- package/dist/esm/utils/base_64_image/base-64-image.js +32 -33
- package/dist/esm/utils/base_64_image/sharp.d.ts +2 -0
- package/dist/esm/utils/base_64_image/sharp.js +33 -0
- package/dist/esm/utils/proxy/proxy-builder.js +3 -1
- package/dist/esm/utils/transformations.js +4 -2
- package/dist/example_projects_templates/configs/jasmine.config.json +12 -0
- package/dist/example_projects_templates/configs/jest.config.ts +13 -0
- package/dist/example_projects_templates/configs/tsconfig.json +7 -0
- package/dist/example_projects_templates/templates/askui-helper-windows.nj +35 -0
- package/dist/example_projects_templates/templates/askui-helper.nj +49 -0
- package/dist/example_projects_templates/typescript/.eslintignore +1 -0
- package/dist/example_projects_templates/typescript/.eslintignore-template +1 -0
- package/dist/example_projects_templates/typescript/.eslintrc.json +20 -0
- package/dist/example_projects_templates/typescript/.eslintrc.json-template +20 -0
- package/dist/example_projects_templates/typescript/askui_example/helpers/askui-helper.ts +39 -0
- package/dist/example_projects_templates/typescript/askui_example/my-first-askui-test-suite.test.ts +21 -0
- package/dist/example_projects_templates/typescript/tsconfig.json +7 -0
- package/package.json +11 -3
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CreateExampleProject = void 0;
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
18
|
+
const util_1 = require("util");
|
|
19
|
+
const child_process_1 = require("child_process");
|
|
20
|
+
const listr_1 = __importDefault(require("listr"));
|
|
21
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
22
|
+
const nunjucks_1 = __importDefault(require("nunjucks"));
|
|
23
|
+
const path_2 = require("../../utils/path");
|
|
24
|
+
const add_script_package_json_1 = require("./add-script-package-json");
|
|
25
|
+
class CreateExampleProject {
|
|
26
|
+
constructor(cliOptions) {
|
|
27
|
+
this.cliOptions = cliOptions;
|
|
28
|
+
this.baseDirPath = process.cwd();
|
|
29
|
+
this.exampleFolderName = 'askui_example';
|
|
30
|
+
this.distexampleFolderPath = path_1.default.join(this.baseDirPath, this.exampleFolderName);
|
|
31
|
+
this.proxyDocUrl = 'https://docs.askui.com/docs/general/Troubleshooting/proxy';
|
|
32
|
+
this.remoteDeviceControllerUrl = 'https://docs.askui.com/docs/api/Remote-Device-Controller';
|
|
33
|
+
this.helperTemplateConfig = {};
|
|
34
|
+
}
|
|
35
|
+
copyTemplateProject() {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const exampleProjectPath = path_1.default.join('example_projects_templates', 'typescript', this.exampleFolderName);
|
|
38
|
+
const runCommand = (0, util_1.promisify)(child_process_1.exec);
|
|
39
|
+
return [
|
|
40
|
+
{
|
|
41
|
+
title: 'Detect Operating System',
|
|
42
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
if (process.platform === 'win32') {
|
|
44
|
+
this.cliOptions.operatingSystem = 'windows';
|
|
45
|
+
}
|
|
46
|
+
else if (process.platform === 'darwin') {
|
|
47
|
+
this.cliOptions.operatingSystem = 'macos';
|
|
48
|
+
}
|
|
49
|
+
else if (process.platform === 'linux'
|
|
50
|
+
|| process.platform === 'freebsd'
|
|
51
|
+
|| process.platform === 'openbsd') {
|
|
52
|
+
this.cliOptions.operatingSystem = 'linux';
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new Error(`The detected operating system is ${process.platform}. We only support 'windows', 'macos' and 'linux'`);
|
|
56
|
+
}
|
|
57
|
+
}),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: 'Copy project files',
|
|
61
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
return fs_extra_1.default.copy(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), exampleProjectPath), this.distexampleFolderPath);
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
title: 'Install askui dependency',
|
|
67
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return runCommand('npm i -D askui '); }),
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
copyTestFrameworkConfig() {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
const frameworkConfigs = {
|
|
75
|
+
jest: 'jest.config.ts',
|
|
76
|
+
jasmine: 'jasmine.config.json',
|
|
77
|
+
};
|
|
78
|
+
const configFilePath = path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), 'example_projects_templates', 'configs', frameworkConfigs[this.cliOptions.testFramework]);
|
|
79
|
+
yield fs_extra_1.default.copyFile(configFilePath, path_1.default.join(this.distexampleFolderPath, frameworkConfigs[this.cliOptions.testFramework]));
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
addTestFrameWorkTimeout() {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const frameworkTimeoutstring = {
|
|
85
|
+
jest: 'jest.setTimeout(60 * 1000 * 60);',
|
|
86
|
+
jasmine: 'jasmine.DEFAULT_TIMEOUT_INTERVAL = 60 * 1000 * 60;',
|
|
87
|
+
};
|
|
88
|
+
this.helperTemplateConfig['timeout_placeholder'] = frameworkTimeoutstring[this.cliOptions.testFramework];
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
addReporterConfig() {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
if (this.cliOptions.testFramework === 'jest') {
|
|
94
|
+
this.helperTemplateConfig['allure_stepreporter_import'] = "import { AskUIAllureStepReporter } from '@askui/askui-reporters';";
|
|
95
|
+
this.helperTemplateConfig['reporter_placeholder'] = 'reporter: new AskUIAllureStepReporter(),';
|
|
96
|
+
this.helperTemplateConfig['allure_stepreporter_attach_video'] = `const video = await aui.readVideoRecording();
|
|
97
|
+
await AskUIAllureStepReporter.attachVideo(video);`;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
addAskuiRunCommand() {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const frameworkExecutionCommand = {
|
|
104
|
+
jest: `jest --config ./${this.exampleFolderName}/jest.config.ts --runInBand`,
|
|
105
|
+
jasmine: `jasmine --config=${this.exampleFolderName}/jasmine.config.json`,
|
|
106
|
+
};
|
|
107
|
+
yield (0, add_script_package_json_1.addScript)(`${this.baseDirPath}/package.json`, 'askui', frameworkExecutionCommand[this.cliOptions.testFramework]);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
addESLintRunCommand() {
|
|
111
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
yield (0, add_script_package_json_1.addScript)(`${this.baseDirPath}/package.json`, 'lint', 'eslint . --ext .ts');
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
createAskUIHelperFromTemplate() {
|
|
116
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
return [{
|
|
118
|
+
title: 'Write askui config',
|
|
119
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
return new listr_1.default([
|
|
121
|
+
{
|
|
122
|
+
title: 'Create askui-helper.ts ',
|
|
123
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
const askuiHelperTemplateFilePath = path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), 'example_projects_templates', 'templates');
|
|
125
|
+
let templateFileName = 'askui-helper.nj';
|
|
126
|
+
if (this.cliOptions.operatingSystem === 'windows') {
|
|
127
|
+
templateFileName = 'askui-helper-windows.nj';
|
|
128
|
+
}
|
|
129
|
+
nunjucks_1.default.configure(askuiHelperTemplateFilePath, { autoescape: false });
|
|
130
|
+
const result = nunjucks_1.default.render(templateFileName, this.helperTemplateConfig);
|
|
131
|
+
const filePath = path_1.default.join(this.distexampleFolderPath, 'helpers', 'askui-helper.ts');
|
|
132
|
+
yield fs_extra_1.default.mkdir(path_1.default.join(this.distexampleFolderPath, 'helpers'));
|
|
133
|
+
yield fs_extra_1.default.writeFile(filePath, result, 'utf8');
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
]);
|
|
137
|
+
}),
|
|
138
|
+
}];
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
setupTestFrameWork() {
|
|
142
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
return [{
|
|
144
|
+
title: 'Setup Test framework',
|
|
145
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
return new listr_1.default([
|
|
147
|
+
{
|
|
148
|
+
title: `Install ${this.cliOptions.testFramework}`,
|
|
149
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return this.installTestFrameworkPackages(); }),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
title: 'Copy config file',
|
|
153
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return this.copyTestFrameworkConfig(); }),
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
title: 'Add timeout',
|
|
157
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return this.addTestFrameWorkTimeout(); }),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
title: 'Add reporter (only Jest)',
|
|
161
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return this.addReporterConfig(); }),
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
title: 'Add askui run command',
|
|
165
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return this.addAskuiRunCommand(); }),
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
title: 'Add eslint run command',
|
|
169
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return this.addESLintRunCommand(); }),
|
|
170
|
+
},
|
|
171
|
+
]);
|
|
172
|
+
}),
|
|
173
|
+
}];
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
installTestFrameworkPackages() {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
const runCommand = (0, util_1.promisify)(child_process_1.exec);
|
|
179
|
+
const frameworkDepencies = {
|
|
180
|
+
jest: 'npm i -D @askui/askui-reporters typescript ts-node @types/jest ts-jest jest @askui/jest-allure-circus eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-import eslint-plugin-askui',
|
|
181
|
+
jasmine: 'npm i -D @askui/askui-reporters typescript ts-node @types/jasmine jasmine @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-import eslint-plugin-askui',
|
|
182
|
+
};
|
|
183
|
+
yield runCommand(frameworkDepencies[this.cliOptions.testFramework]);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
addUserCredentails() {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
return [{
|
|
189
|
+
title: 'Add user credentails',
|
|
190
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
return new listr_1.default([
|
|
192
|
+
{
|
|
193
|
+
title: 'Add workspace id ',
|
|
194
|
+
task: () => __awaiter(this, void 0, void 0, function* () { this.helperTemplateConfig['workspace_id'] = this.cliOptions.workspaceId; }),
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
title: 'Add access token',
|
|
198
|
+
task: () => __awaiter(this, void 0, void 0, function* () { this.helperTemplateConfig['access_token'] = this.cliOptions.accessToken; }),
|
|
199
|
+
},
|
|
200
|
+
]);
|
|
201
|
+
}),
|
|
202
|
+
}];
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
copyESLintConfigFiles() {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
const esLintRcFilePath = path_1.default.join('example_projects_templates', 'typescript', '.eslintrc.json-template');
|
|
208
|
+
const esLintIgnoreFilePath = path_1.default.join('example_projects_templates', 'typescript', '.eslintignore-template');
|
|
209
|
+
return [{
|
|
210
|
+
title: 'Copy ESLint config files',
|
|
211
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
212
|
+
return new listr_1.default([
|
|
213
|
+
{
|
|
214
|
+
title: 'Add eslintrc.json',
|
|
215
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
216
|
+
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintRcFilePath), path_1.default.join(this.baseDirPath, '.eslintrc.json'));
|
|
217
|
+
}),
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
title: 'Add .eslintignore',
|
|
221
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
222
|
+
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintIgnoreFilePath), path_1.default.join(this.baseDirPath, '.eslintignore'));
|
|
223
|
+
}),
|
|
224
|
+
},
|
|
225
|
+
]);
|
|
226
|
+
}),
|
|
227
|
+
}];
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
copyTsConfigFile() {
|
|
231
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
232
|
+
const tsConfigFilePath = path_1.default.join('example_projects_templates', 'typescript', 'tsconfig.json');
|
|
233
|
+
return [{
|
|
234
|
+
title: 'Copy ts config file',
|
|
235
|
+
enabled: () => this.cliOptions.typescriptConfig,
|
|
236
|
+
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
237
|
+
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), tsConfigFilePath), path_1.default.join(this.baseDirPath, 'tsconfig.json'));
|
|
238
|
+
}),
|
|
239
|
+
}];
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
installProxy() {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
const runCommand = (0, util_1.promisify)(child_process_1.exec);
|
|
245
|
+
return [{
|
|
246
|
+
title: 'Install Proxy',
|
|
247
|
+
enabled: () => this.cliOptions.usingProxy,
|
|
248
|
+
task: () => __awaiter(this, void 0, void 0, function* () { return runCommand('npm install --save-dev hpagent '); }),
|
|
249
|
+
}];
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
normalizeCliOptions() {
|
|
253
|
+
let useProxy = this.cliOptions.usingProxy;
|
|
254
|
+
if (typeof useProxy !== 'boolean') {
|
|
255
|
+
useProxy = (useProxy === 'true');
|
|
256
|
+
}
|
|
257
|
+
this.cliOptions.usingProxy = useProxy;
|
|
258
|
+
let { typescriptConfig } = this.cliOptions;
|
|
259
|
+
if (typeof typescriptConfig !== 'boolean') {
|
|
260
|
+
typescriptConfig = (typescriptConfig === 'true');
|
|
261
|
+
}
|
|
262
|
+
this.cliOptions.typescriptConfig = typescriptConfig;
|
|
263
|
+
}
|
|
264
|
+
createExampleProject() {
|
|
265
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
266
|
+
const tasks = new listr_1.default();
|
|
267
|
+
this.normalizeCliOptions();
|
|
268
|
+
tasks.add([
|
|
269
|
+
...yield this.copyTemplateProject(),
|
|
270
|
+
...yield this.setupTestFrameWork(),
|
|
271
|
+
...yield this.copyESLintConfigFiles(),
|
|
272
|
+
...yield this.copyTsConfigFile(),
|
|
273
|
+
...yield this.addUserCredentails(),
|
|
274
|
+
...yield this.createAskUIHelperFromTemplate(),
|
|
275
|
+
...yield this.installProxy(),
|
|
276
|
+
]);
|
|
277
|
+
yield tasks.run();
|
|
278
|
+
/* eslint-disable no-console */
|
|
279
|
+
if (this.cliOptions.usingProxy) {
|
|
280
|
+
console.log(chalk_1.default.redBright('Since you are using a Proxy. Please don\'t forget to configure it!'));
|
|
281
|
+
console.log(chalk_1.default.gray(`You can find more information under ${this.proxyDocUrl}`));
|
|
282
|
+
}
|
|
283
|
+
console.log(chalk_1.default.greenBright('\nCongratulations!'));
|
|
284
|
+
console.log(`askui example was created under ${chalk_1.default.gray(this.distexampleFolderPath)}`);
|
|
285
|
+
if (this.cliOptions.operatingSystem === 'windows') {
|
|
286
|
+
console.log(chalk_1.default.redBright(`\nPlease install and start the Remote Device Controller: ${this.remoteDeviceControllerUrl}\n`));
|
|
287
|
+
}
|
|
288
|
+
console.log(`You can start your automation with this command ${chalk_1.default.green('npm run askui')}`);
|
|
289
|
+
/* eslint-enable no-console */
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
exports.CreateExampleProject = CreateExampleProject;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { init } from './cli';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function replaceStringInFile(filePath: string, replace: string, replacement: string): Promise<void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.replaceStringInFile = void 0;
|
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
+
const logger_1 = require("../logger");
|
|
18
|
+
function replaceStringInFile(filePath, replace, replacement) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
try {
|
|
21
|
+
const data = yield fs_extra_1.default.readFile(filePath, 'utf8');
|
|
22
|
+
const result = data.replace(replace, replacement);
|
|
23
|
+
yield fs_extra_1.default.writeFile(filePath, result, 'utf8');
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
logger_1.logger.error(`Could not replace '${replace}' with '${replacement}' in file '${filePath}'`);
|
|
27
|
+
logger_1.logger.error(error.message);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
exports.replaceStringInFile = replaceStringInFile;
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import type sharp from 'sharp';
|
|
2
2
|
export declare class Base64Image {
|
|
3
|
-
private readonly aSharp;
|
|
4
|
-
private info;
|
|
5
3
|
private buffer;
|
|
6
4
|
static readonly strPrefix = "data:image/png;base64,";
|
|
5
|
+
private _sharp?;
|
|
7
6
|
private constructor();
|
|
8
|
-
private static fromSharp;
|
|
9
7
|
static fromPathOrString(pathOrStr: string): Promise<Base64Image>;
|
|
10
|
-
static fromPath(
|
|
8
|
+
static fromPath(filePath: string): Promise<Base64Image>;
|
|
11
9
|
static fromString(str: string): Promise<Base64Image>;
|
|
12
|
-
static fromBuffer
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
private static fromBuffer;
|
|
11
|
+
private getSharp;
|
|
12
|
+
getInfo(): Promise<sharp.OutputInfo>;
|
|
15
13
|
resizeToFitInto(dimension: number): Promise<Base64Image>;
|
|
16
14
|
toString(): string;
|
|
17
|
-
toBuffer(): Buffer;
|
|
18
15
|
}
|
|
@@ -13,36 +13,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.Base64Image = void 0;
|
|
16
|
-
const
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const sharp_1 = require("./sharp");
|
|
17
18
|
const base_64_image_string_error_1 = require("./base-64-image-string-error");
|
|
18
19
|
class Base64Image {
|
|
19
|
-
constructor(
|
|
20
|
-
this.aSharp = aSharp;
|
|
21
|
-
this.info = info;
|
|
20
|
+
constructor(buffer) {
|
|
22
21
|
this.buffer = buffer;
|
|
23
22
|
}
|
|
24
|
-
static fromSharp(s) {
|
|
25
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const { info, data } = yield s.toBuffer({ resolveWithObject: true });
|
|
27
|
-
return new Base64Image(s, info, data);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
23
|
static fromPathOrString(pathOrStr) {
|
|
31
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
|
|
33
|
-
return
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
if (!(error instanceof base_64_image_string_error_1.Base64ImageStringError)) {
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
25
|
+
if (pathOrStr.startsWith(Base64Image.strPrefix)) {
|
|
26
|
+
return Base64Image.fromString(pathOrStr);
|
|
39
27
|
}
|
|
40
28
|
return Base64Image.fromPath(pathOrStr);
|
|
41
29
|
});
|
|
42
30
|
}
|
|
43
|
-
static fromPath(
|
|
31
|
+
static fromPath(filePath) {
|
|
44
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
|
|
33
|
+
const data = yield fs_1.default.promises.readFile(filePath, 'base64');
|
|
34
|
+
return Base64Image.fromString(`${Base64Image.strPrefix}${data}`);
|
|
46
35
|
});
|
|
47
36
|
}
|
|
48
37
|
static fromString(str) {
|
|
@@ -51,36 +40,46 @@ class Base64Image {
|
|
|
51
40
|
throw new base_64_image_string_error_1.Base64ImageStringError(str, Base64Image.strPrefix);
|
|
52
41
|
}
|
|
53
42
|
const data = str.substring(Base64Image.strPrefix.length);
|
|
54
|
-
return Base64Image
|
|
43
|
+
return new Base64Image(Buffer.from(data, 'base64'));
|
|
55
44
|
});
|
|
56
45
|
}
|
|
57
46
|
static fromBuffer(buffer) {
|
|
58
47
|
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
-
return Base64Image
|
|
48
|
+
return new Base64Image(buffer);
|
|
60
49
|
});
|
|
61
50
|
}
|
|
62
|
-
|
|
63
|
-
return this
|
|
51
|
+
getSharp() {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
if (this._sharp === undefined) {
|
|
54
|
+
const createSharp = yield (0, sharp_1.getSharpFactory)();
|
|
55
|
+
this._sharp = createSharp(this.buffer);
|
|
56
|
+
}
|
|
57
|
+
return this._sharp;
|
|
58
|
+
});
|
|
64
59
|
}
|
|
65
|
-
|
|
66
|
-
return this
|
|
60
|
+
getInfo() {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
return (yield this.getSharp())
|
|
63
|
+
.toBuffer({ resolveWithObject: true })
|
|
64
|
+
.then(({ info }) => info);
|
|
65
|
+
});
|
|
67
66
|
}
|
|
68
67
|
resizeToFitInto(dimension) {
|
|
69
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
const { width, height } = yield this.getInfo();
|
|
70
|
+
const buffer = yield (yield this.getSharp())
|
|
71
|
+
.resize({
|
|
72
|
+
width: width >= height ? dimension : undefined,
|
|
73
|
+
height: height > width ? dimension : undefined,
|
|
74
|
+
fit: 'contain',
|
|
75
|
+
})
|
|
76
|
+
.toBuffer();
|
|
75
77
|
return Base64Image.fromBuffer(buffer);
|
|
76
78
|
});
|
|
77
79
|
}
|
|
78
80
|
toString() {
|
|
79
81
|
return `${Base64Image.strPrefix}${this.buffer.toString('base64')}`;
|
|
80
82
|
}
|
|
81
|
-
toBuffer() {
|
|
82
|
-
return this.buffer;
|
|
83
|
-
}
|
|
84
83
|
}
|
|
85
84
|
exports.Base64Image = Base64Image;
|
|
86
85
|
Base64Image.strPrefix = 'data:image/png;base64,';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.getSharpFactory = void 0;
|
|
32
|
+
let lazilyInitializedSharpFactory;
|
|
33
|
+
class SharpImportError extends Error {
|
|
34
|
+
}
|
|
35
|
+
function dynamicallyImportSharp() {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
try {
|
|
38
|
+
const sharp = yield Promise.resolve().then(() => __importStar(require('sharp')));
|
|
39
|
+
return sharp.default;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
throw new SharpImportError('Can\'t find "sharp" module to do resizing of image!'
|
|
43
|
+
+ ' Please, install sharp for resizing support with'
|
|
44
|
+
+ ' "npm install --save-dev sharp" or "npm install --save sharp".');
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function getSharpFactory() {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
if (lazilyInitializedSharpFactory === undefined) {
|
|
51
|
+
lazilyInitializedSharpFactory = yield dynamicallyImportSharp();
|
|
52
|
+
}
|
|
53
|
+
return lazilyInitializedSharpFactory;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
exports.getSharpFactory = getSharpFactory;
|
|
@@ -40,7 +40,9 @@ function dynmicImportHpagent() {
|
|
|
40
40
|
return yield Promise.resolve().then(() => __importStar(require('hpagent')));
|
|
41
41
|
}
|
|
42
42
|
catch (err) {
|
|
43
|
-
throw new ProxyImportError('Can\'t find "hpagent" module to configure proxy!
|
|
43
|
+
throw new ProxyImportError('Can\'t find "hpagent" module to configure proxy!'
|
|
44
|
+
+ ' Please, install hpagent for proxy support with'
|
|
45
|
+
+ ' "npm install --save-dev hpagent" or "npm install --save hpagent".');
|
|
44
46
|
}
|
|
45
47
|
});
|
|
46
48
|
}
|
|
@@ -28,13 +28,15 @@ function resizeBase64ImageWithSameRatio(base64ImageString, maxEdge = 1400) {
|
|
|
28
28
|
lib_1.logger.debug('Image resizing');
|
|
29
29
|
try {
|
|
30
30
|
const image = yield base_64_image_1.Base64Image.fromString(base64ImageString);
|
|
31
|
-
|
|
31
|
+
const imageInfo = yield image.getInfo();
|
|
32
|
+
if (imageInfo.height <= maxEdge && imageInfo.width <= maxEdge) {
|
|
32
33
|
return { base64Image: base64ImageString, resizeRatio: 1 };
|
|
33
34
|
}
|
|
34
35
|
const resizedImage = yield image.resizeToFitInto(maxEdge);
|
|
36
|
+
const resizedImageInfo = yield resizedImage.getInfo();
|
|
35
37
|
return {
|
|
36
38
|
base64Image: resizedImage.toString(),
|
|
37
|
-
resizeRatio:
|
|
39
|
+
resizeRatio: imageInfo.width / resizedImageInfo.width,
|
|
38
40
|
};
|
|
39
41
|
}
|
|
40
42
|
catch (error) {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines a 'custom element'. This is a UI element which is defined by
|
|
3
|
+
* providing an image and other parameters such as degree of rotation.
|
|
4
|
+
* It allows filtering for a UI element that is not recognized
|
|
5
|
+
* by our machine learning models by default.
|
|
6
|
+
* It can also be used for pixel assertions of elements using classical
|
|
7
|
+
* [template matching](https://en.wikipedia.org/wiki/Template_matching).
|
|
8
|
+
*
|
|
9
|
+
* **Important:** The `CustomElementJson` needs to capture as accurately as possible
|
|
10
|
+
* what the custom element looks like during test execution as otherwise
|
|
11
|
+
* our machine learning models cannot find it, even with the additional data
|
|
12
|
+
* provided. This is especially true for the resolution used while cropping
|
|
13
|
+
* the `CustomElementJson.customImage` which should match the resolution during
|
|
14
|
+
* test execution.
|
|
15
|
+
*
|
|
16
|
+
* Rotated custom elements can be filtered for using
|
|
17
|
+
* `CustomElementJson.rotationDegreePerStep`.
|
|
18
|
+
*/
|
|
19
|
+
export interface CustomElementJson {
|
|
20
|
+
/**
|
|
21
|
+
* An cropped image in form of a base64 string or file path,
|
|
22
|
+
* e.g., "./custom.png".
|
|
23
|
+
*/
|
|
24
|
+
customImage: string;
|
|
25
|
+
/**
|
|
26
|
+
* A unique name which can be used for filtering for the custom element,
|
|
27
|
+
* e.g.,
|
|
28
|
+
* ```typescript
|
|
29
|
+
* ...customElement({
|
|
30
|
+
* name: 'unique-name',
|
|
31
|
+
* // ... (rest of the custom element)
|
|
32
|
+
* }).withText('unique-name')
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* If not set, the text inside the custom element is
|
|
36
|
+
* detected via
|
|
37
|
+
* [OCR](https://en.wikipedia.org/wiki/Optical_character_recognition).
|
|
38
|
+
* It can also be used for filtering for the custom element.
|
|
39
|
+
*/
|
|
40
|
+
name?: string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* A threshold for how similar UI elements shown during test execution
|
|
43
|
+
* need to be to the custom element as defined by the other fields in
|
|
44
|
+
* `CustomElementJson` to be recognized as such. Takes values between
|
|
45
|
+
* `0.0` (= all elements are recognized as the custom element which is
|
|
46
|
+
* probably not what you want) and `1.0` (= elements need to look exactly
|
|
47
|
+
* like defined by `CustomElementJson` which is unlikely to be achieved
|
|
48
|
+
* as even minor differences count). Defaults to `0.9`.
|
|
49
|
+
*/
|
|
50
|
+
threshold?: number | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* A step size in rotation degree. Rotates the custom image by
|
|
53
|
+
* `rotationDegreePerStep` until 360° is exceeded. Range is between
|
|
54
|
+
* 0° - 360°. Defaults to 0°.
|
|
55
|
+
*
|
|
56
|
+
* **Important**: This increases the prediction time quite a bit. So only use
|
|
57
|
+
* it when absolutely necessary.
|
|
58
|
+
*/
|
|
59
|
+
rotationDegreePerStep?: number | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* A color compare style. Allows matching a custom element by color, e.g.,
|
|
62
|
+
* instead of filtering for all icons (blue and green ones),
|
|
63
|
+
* only the green ones captured by `customImage` are filtered for using 'RGB'.
|
|
64
|
+
* Defaults to 'grayscale'.
|
|
65
|
+
*
|
|
66
|
+
* **Important**: This increases the prediction time quite a bit. So only use
|
|
67
|
+
* it when absolutely necessary.
|
|
68
|
+
*/
|
|
69
|
+
imageCompareFormat?: 'RGB' | 'grayscale' | undefined;
|
|
70
|
+
/** A polygon to match only a certain area of the custom element. */
|
|
71
|
+
mask?: ({
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
})[] | undefined;
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|