askui 0.13.1 → 0.14.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/execution/ui-control-client.d.ts +86 -5
- package/dist/cjs/execution/ui-control-client.js +141 -0
- package/dist/cjs/lib/interactive_cli/create-example-project.d.ts +1 -1
- package/dist/cjs/lib/interactive_cli/create-example-project.js +3 -3
- package/dist/esm/execution/ui-control-client.d.ts +86 -5
- package/dist/esm/execution/ui-control-client.js +141 -0
- package/dist/esm/lib/interactive_cli/create-example-project.d.ts +1 -1
- package/dist/esm/lib/interactive_cli/create-example-project.js +3 -3
- package/package.json +4 -4
- package/dist/cjs/core/model/test-case-dto/custom-element-json.d.ts +0 -75
- package/dist/cjs/core/model/test-case-dto/custom-element-json.js +0 -2
- package/dist/cjs/core/model/test-case-dto/custom-element.d.ts +0 -21
- package/dist/cjs/core/model/test-case-dto/custom-element.js +0 -54
- package/dist/cjs/core/model/test-case-dto/index.d.ts +0 -3
- package/dist/cjs/core/model/test-case-dto/index.js +0 -5
- package/dist/cjs/core/model/test-case-dto/test-step.d.ts +0 -6
- package/dist/cjs/core/model/test-case-dto/test-step.js +0 -2
- package/dist/cjs/core/model/test-case-result-dto/index.d.ts +0 -2
- package/dist/cjs/core/model/test-case-result-dto/index.js +0 -7
- package/dist/cjs/core/model/test-case-result-dto/test-step-result-dto.d.ts +0 -9
- package/dist/cjs/core/model/test-case-result-dto/test-step-result-dto.js +0 -16
- package/dist/cjs/core/model/test-case-result-dto/test-step-state.d.ts +0 -4
- package/dist/cjs/core/model/test-case-result-dto/test-step-state.js +0 -8
- package/dist/cjs/core/reporting/default-reporter.d.ts +0 -10
- package/dist/cjs/core/reporting/default-reporter.js +0 -12
- package/dist/cjs/execution/annotation-level.d.ts +0 -5
- package/dist/cjs/execution/annotation-level.js +0 -9
- package/dist/cjs/execution/ui-control-client-error.d.ts +0 -2
- package/dist/cjs/execution/ui-control-client-error.js +0 -6
- package/dist/cjs/lib/copy-example-project.d.ts +0 -2
- package/dist/cjs/lib/copy-example-project.js +0 -65
- package/dist/cjs/lib/interactive_cli/replace-string-in-file.d.ts +0 -1
- package/dist/cjs/lib/interactive_cli/replace-string-in-file.js +0 -31
- package/dist/esm/core/model/test-case-dto/custom-element-json.d.ts +0 -75
- package/dist/esm/core/model/test-case-dto/custom-element-json.js +0 -1
- package/dist/esm/core/model/test-case-dto/custom-element.d.ts +0 -21
- package/dist/esm/core/model/test-case-dto/custom-element.js +0 -50
- package/dist/esm/core/model/test-case-dto/index.d.ts +0 -3
- package/dist/esm/core/model/test-case-dto/index.js +0 -1
- package/dist/esm/core/model/test-case-dto/test-step.d.ts +0 -6
- package/dist/esm/core/model/test-case-dto/test-step.js +0 -1
- package/dist/esm/core/model/test-case-result-dto/index.d.ts +0 -2
- package/dist/esm/core/model/test-case-result-dto/index.js +0 -2
- package/dist/esm/core/model/test-case-result-dto/test-step-result-dto.d.ts +0 -9
- package/dist/esm/core/model/test-case-result-dto/test-step-result-dto.js +0 -12
- package/dist/esm/core/model/test-case-result-dto/test-step-state.d.ts +0 -4
- package/dist/esm/core/model/test-case-result-dto/test-step-state.js +0 -5
- package/dist/esm/core/reporting/default-reporter.d.ts +0 -10
- package/dist/esm/core/reporting/default-reporter.js +0 -9
- package/dist/esm/execution/annotation-level.d.ts +0 -5
- package/dist/esm/execution/annotation-level.js +0 -6
- package/dist/esm/execution/ui-control-client-error.d.ts +0 -2
- package/dist/esm/execution/ui-control-client-error.js +0 -2
- package/dist/esm/lib/copy-example-project.d.ts +0 -2
- package/dist/esm/lib/copy-example-project.js +0 -58
- package/dist/esm/lib/interactive_cli/replace-string-in-file.d.ts +0 -1
- package/dist/esm/lib/interactive_cli/replace-string-in-file.js +0 -24
- package/dist/example_projects_templates/typescript/.eslintignore +0 -1
- package/dist/example_projects_templates/typescript/.eslintrc.json +0 -20
- package/dist/example_projects_templates/typescript/askui_example/helpers/askui-helper.ts +0 -39
- package/dist/example_projects_templates/typescript_jest/test/README.md +0 -21
- package/dist/example_projects_templates/typescript_jest/test/helper/jest.setup.ts +0 -51
- package/dist/example_projects_templates/typescript_jest/test/jest.config.ts +0 -13
- package/dist/example_projects_templates/typescript_jest/test/my-first-askui-test-suite.test.ts +0 -21
- package/dist/example_projects_templates/typescript_jest/tsconfig.json +0 -7
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CustomElementJson } from '../core/model/custom-element-json';
|
|
2
|
-
import { Exec, Executable, FluentFilters, ApiCommands } from './dsl';
|
|
2
|
+
import { Exec, Executable, FluentFilters, ApiCommands, PC_AND_MODIFIER_KEY } from './dsl';
|
|
3
3
|
import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
|
|
4
4
|
import { Annotation } from '../core/annotation/annotation';
|
|
5
5
|
import { AnnotationRequest } from '../core/model/annotation-result/annotation-interface';
|
|
@@ -56,8 +56,8 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
56
56
|
* @return {FluentFilters}
|
|
57
57
|
*/
|
|
58
58
|
typeIn(text: string, { isSecret, secretMask }?: {
|
|
59
|
-
isSecret?: boolean
|
|
60
|
-
secretMask?: string
|
|
59
|
+
isSecret?: boolean;
|
|
60
|
+
secretMask?: string;
|
|
61
61
|
}): FluentFilters;
|
|
62
62
|
/**
|
|
63
63
|
* Types a text at the current position.
|
|
@@ -78,8 +78,8 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
78
78
|
* @return {Exec}
|
|
79
79
|
*/
|
|
80
80
|
type(text: string, { isSecret, secretMask }?: {
|
|
81
|
-
isSecret?: boolean
|
|
82
|
-
secretMask?: string
|
|
81
|
+
isSecret?: boolean;
|
|
82
|
+
secretMask?: string;
|
|
83
83
|
}): Exec;
|
|
84
84
|
/**
|
|
85
85
|
* Waits for `<delayInMs>` ms, e.g., 1000 ms. The exact delay may be a little longer
|
|
@@ -90,4 +90,85 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
90
90
|
* @return {Executable}
|
|
91
91
|
*/
|
|
92
92
|
waitFor(delayInMs: number): Executable;
|
|
93
|
+
/**
|
|
94
|
+
* Press a key multiple times. At least two times.
|
|
95
|
+
*
|
|
96
|
+
* @param {PC_AND_MODIFIER_KEY} key
|
|
97
|
+
*
|
|
98
|
+
* @param {number} times
|
|
99
|
+
*/
|
|
100
|
+
pressKeyNTimes(key: PC_AND_MODIFIER_KEY, times?: number): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Press an array of keys one after another.
|
|
103
|
+
*
|
|
104
|
+
* For example press the following keys: right, left, enter.
|
|
105
|
+
*
|
|
106
|
+
* pressKeys(['right', 'left', 'enter'])
|
|
107
|
+
*
|
|
108
|
+
* @param {PC_AND_MODIFIER_KEY[]} keys
|
|
109
|
+
*/
|
|
110
|
+
pressKeys(keys: PC_AND_MODIFIER_KEY[]): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Searches for a text element and clicks it when found.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} text - A text to be searched.
|
|
115
|
+
*/
|
|
116
|
+
clickText(text: string): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Searches for text elements and clicks them
|
|
119
|
+
* one after another when found.
|
|
120
|
+
*
|
|
121
|
+
* @param {string[]} texts - An array of texts to be searched.
|
|
122
|
+
*/
|
|
123
|
+
clickTexts(texts: string[]): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Searches for an element of type button
|
|
126
|
+
* with a label and clicks it when found.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} label - The buttons label.
|
|
129
|
+
*/
|
|
130
|
+
clickButton(label: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Searches for an element of type textfield with a specific placeholder text.
|
|
133
|
+
* If found, clicks it.
|
|
134
|
+
*
|
|
135
|
+
* @param {string} placeholder - The textfields placeholder text.
|
|
136
|
+
*/
|
|
137
|
+
clickTextfield(placeholder: string): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Clicks an icon based on a description.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} description
|
|
142
|
+
*/
|
|
143
|
+
clickIcon(description: string): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Drags element1 to element2.
|
|
146
|
+
*
|
|
147
|
+
* Both must be a `moveMouse()` or `moveMouseTo()`
|
|
148
|
+
* instruction as in the example below.
|
|
149
|
+
*
|
|
150
|
+
* Usage example:
|
|
151
|
+
* dragTo(
|
|
152
|
+
* aui.moveMouseTo().text('AskUI'),
|
|
153
|
+
* aui.moveMouseTo().text('UI Automation')
|
|
154
|
+
* )
|
|
155
|
+
*
|
|
156
|
+
* @param {Executable} element1
|
|
157
|
+
* @param {Executable} element2
|
|
158
|
+
*/
|
|
159
|
+
dragTo(element1: Executable, element2: Executable): Promise<void>;
|
|
160
|
+
/**
|
|
161
|
+
* Wait until an AskUICommand does not fail.
|
|
162
|
+
*
|
|
163
|
+
* Use it to wait for an element to appear like this:
|
|
164
|
+
*
|
|
165
|
+
* await waitUntil(
|
|
166
|
+
* aui.expect().text('Github').exists()
|
|
167
|
+
* );
|
|
168
|
+
*
|
|
169
|
+
* @param {Executable} AskUICommand - For example: aui.moveMouse(0, 0)
|
|
170
|
+
* @param {number} maxTry - Number of maximum retries
|
|
171
|
+
* @param {number} waitTime - Time in milliseconds
|
|
172
|
+
*/
|
|
173
|
+
waitUntil(AskUICommand: Executable, maxTry?: number, waitTime?: number): Promise<void>;
|
|
93
174
|
}
|
|
@@ -217,5 +217,146 @@ class UiControlClient extends dsl_1.ApiCommands {
|
|
|
217
217
|
},
|
|
218
218
|
};
|
|
219
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Press a key multiple times. At least two times.
|
|
222
|
+
*
|
|
223
|
+
* @param {PC_AND_MODIFIER_KEY} key
|
|
224
|
+
*
|
|
225
|
+
* @param {number} times
|
|
226
|
+
*/
|
|
227
|
+
pressKeyNTimes(key, times = 2) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
/* eslint-disable no-await-in-loop */
|
|
230
|
+
for (let i = 0; i < times; i += 1) {
|
|
231
|
+
yield this.pressKey(key).exec();
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Press an array of keys one after another.
|
|
237
|
+
*
|
|
238
|
+
* For example press the following keys: right, left, enter.
|
|
239
|
+
*
|
|
240
|
+
* pressKeys(['right', 'left', 'enter'])
|
|
241
|
+
*
|
|
242
|
+
* @param {PC_AND_MODIFIER_KEY[]} keys
|
|
243
|
+
*/
|
|
244
|
+
pressKeys(keys) {
|
|
245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
+
/* eslint-disable no-await-in-loop */
|
|
247
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
248
|
+
yield this.pressKey(keys[i]).exec();
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Searches for a text element and clicks it when found.
|
|
254
|
+
*
|
|
255
|
+
* @param {string} text - A text to be searched.
|
|
256
|
+
*/
|
|
257
|
+
clickText(text) {
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
yield this.click().text(text).exec();
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Searches for text elements and clicks them
|
|
264
|
+
* one after another when found.
|
|
265
|
+
*
|
|
266
|
+
* @param {string[]} texts - An array of texts to be searched.
|
|
267
|
+
*/
|
|
268
|
+
clickTexts(texts) {
|
|
269
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
270
|
+
/* eslint-disable no-await-in-loop */
|
|
271
|
+
for (let i = 0; i < texts.length; i += 1) {
|
|
272
|
+
yield this.click().text(texts[i]).exec();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Searches for an element of type button
|
|
278
|
+
* with a label and clicks it when found.
|
|
279
|
+
*
|
|
280
|
+
* @param {string} label - The buttons label.
|
|
281
|
+
*/
|
|
282
|
+
clickButton(label) {
|
|
283
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
284
|
+
yield this.click().button().withText(label).exec();
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Searches for an element of type textfield with a specific placeholder text.
|
|
289
|
+
* If found, clicks it.
|
|
290
|
+
*
|
|
291
|
+
* @param {string} placeholder - The textfields placeholder text.
|
|
292
|
+
*/
|
|
293
|
+
clickTextfield(placeholder) {
|
|
294
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
295
|
+
yield this.click().textfield().contains().text()
|
|
296
|
+
.withText(placeholder)
|
|
297
|
+
.exec();
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Clicks an icon based on a description.
|
|
302
|
+
*
|
|
303
|
+
* @param {string} description
|
|
304
|
+
*/
|
|
305
|
+
clickIcon(description) {
|
|
306
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
307
|
+
yield this.click().icon().matching(description).exec();
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Drags element1 to element2.
|
|
312
|
+
*
|
|
313
|
+
* Both must be a `moveMouse()` or `moveMouseTo()`
|
|
314
|
+
* instruction as in the example below.
|
|
315
|
+
*
|
|
316
|
+
* Usage example:
|
|
317
|
+
* dragTo(
|
|
318
|
+
* aui.moveMouseTo().text('AskUI'),
|
|
319
|
+
* aui.moveMouseTo().text('UI Automation')
|
|
320
|
+
* )
|
|
321
|
+
*
|
|
322
|
+
* @param {Executable} element1
|
|
323
|
+
* @param {Executable} element2
|
|
324
|
+
*/
|
|
325
|
+
dragTo(element1, element2) {
|
|
326
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
327
|
+
yield element1.exec();
|
|
328
|
+
yield this.mouseLeftClick().exec();
|
|
329
|
+
yield this.mouseToggleDown().exec();
|
|
330
|
+
yield element2.exec();
|
|
331
|
+
yield this.mouseToggleUp().exec();
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Wait until an AskUICommand does not fail.
|
|
336
|
+
*
|
|
337
|
+
* Use it to wait for an element to appear like this:
|
|
338
|
+
*
|
|
339
|
+
* await waitUntil(
|
|
340
|
+
* aui.expect().text('Github').exists()
|
|
341
|
+
* );
|
|
342
|
+
*
|
|
343
|
+
* @param {Executable} AskUICommand - For example: aui.moveMouse(0, 0)
|
|
344
|
+
* @param {number} maxTry - Number of maximum retries
|
|
345
|
+
* @param {number} waitTime - Time in milliseconds
|
|
346
|
+
*/
|
|
347
|
+
waitUntil(AskUICommand, maxTry = 5, waitTime = 2000) {
|
|
348
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
349
|
+
try {
|
|
350
|
+
yield AskUICommand.exec();
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
if (maxTry === 0) {
|
|
354
|
+
throw error;
|
|
355
|
+
}
|
|
356
|
+
yield this.waitFor(waitTime).exec();
|
|
357
|
+
yield this.waitUntil(AskUICommand, maxTry - 1);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
220
361
|
}
|
|
221
362
|
exports.UiControlClient = UiControlClient;
|
|
@@ -17,7 +17,7 @@ export declare class CreateExampleProject {
|
|
|
17
17
|
private createAskUIHelperFromTemplate;
|
|
18
18
|
private setupTestFrameWork;
|
|
19
19
|
private installTestFrameworkPackages;
|
|
20
|
-
private
|
|
20
|
+
private addUserCredentials;
|
|
21
21
|
private copyESLintConfigFiles;
|
|
22
22
|
private copyTsConfigFile;
|
|
23
23
|
private installProxy;
|
|
@@ -185,10 +185,10 @@ class CreateExampleProject {
|
|
|
185
185
|
yield runCommand(frameworkDepencies[this.cliOptions.testFramework]);
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
|
-
|
|
188
|
+
addUserCredentials() {
|
|
189
189
|
return __awaiter(this, void 0, void 0, function* () {
|
|
190
190
|
return [{
|
|
191
|
-
title: 'Add user
|
|
191
|
+
title: 'Add user credentials',
|
|
192
192
|
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
193
193
|
return new listr_1.default([
|
|
194
194
|
{
|
|
@@ -272,7 +272,7 @@ class CreateExampleProject {
|
|
|
272
272
|
...yield this.setupTestFrameWork(),
|
|
273
273
|
...yield this.copyESLintConfigFiles(),
|
|
274
274
|
...yield this.copyTsConfigFile(),
|
|
275
|
-
...yield this.
|
|
275
|
+
...yield this.addUserCredentials(),
|
|
276
276
|
...yield this.createAskUIHelperFromTemplate(),
|
|
277
277
|
...yield this.installProxy(),
|
|
278
278
|
]);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CustomElementJson } from '../core/model/custom-element-json';
|
|
2
|
-
import { Exec, Executable, FluentFilters, ApiCommands } from './dsl';
|
|
2
|
+
import { Exec, Executable, FluentFilters, ApiCommands, PC_AND_MODIFIER_KEY } from './dsl';
|
|
3
3
|
import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
|
|
4
4
|
import { Annotation } from '../core/annotation/annotation';
|
|
5
5
|
import { AnnotationRequest } from '../core/model/annotation-result/annotation-interface';
|
|
@@ -56,8 +56,8 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
56
56
|
* @return {FluentFilters}
|
|
57
57
|
*/
|
|
58
58
|
typeIn(text: string, { isSecret, secretMask }?: {
|
|
59
|
-
isSecret?: boolean
|
|
60
|
-
secretMask?: string
|
|
59
|
+
isSecret?: boolean;
|
|
60
|
+
secretMask?: string;
|
|
61
61
|
}): FluentFilters;
|
|
62
62
|
/**
|
|
63
63
|
* Types a text at the current position.
|
|
@@ -78,8 +78,8 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
78
78
|
* @return {Exec}
|
|
79
79
|
*/
|
|
80
80
|
type(text: string, { isSecret, secretMask }?: {
|
|
81
|
-
isSecret?: boolean
|
|
82
|
-
secretMask?: string
|
|
81
|
+
isSecret?: boolean;
|
|
82
|
+
secretMask?: string;
|
|
83
83
|
}): Exec;
|
|
84
84
|
/**
|
|
85
85
|
* Waits for `<delayInMs>` ms, e.g., 1000 ms. The exact delay may be a little longer
|
|
@@ -90,4 +90,85 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
90
90
|
* @return {Executable}
|
|
91
91
|
*/
|
|
92
92
|
waitFor(delayInMs: number): Executable;
|
|
93
|
+
/**
|
|
94
|
+
* Press a key multiple times. At least two times.
|
|
95
|
+
*
|
|
96
|
+
* @param {PC_AND_MODIFIER_KEY} key
|
|
97
|
+
*
|
|
98
|
+
* @param {number} times
|
|
99
|
+
*/
|
|
100
|
+
pressKeyNTimes(key: PC_AND_MODIFIER_KEY, times?: number): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Press an array of keys one after another.
|
|
103
|
+
*
|
|
104
|
+
* For example press the following keys: right, left, enter.
|
|
105
|
+
*
|
|
106
|
+
* pressKeys(['right', 'left', 'enter'])
|
|
107
|
+
*
|
|
108
|
+
* @param {PC_AND_MODIFIER_KEY[]} keys
|
|
109
|
+
*/
|
|
110
|
+
pressKeys(keys: PC_AND_MODIFIER_KEY[]): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Searches for a text element and clicks it when found.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} text - A text to be searched.
|
|
115
|
+
*/
|
|
116
|
+
clickText(text: string): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Searches for text elements and clicks them
|
|
119
|
+
* one after another when found.
|
|
120
|
+
*
|
|
121
|
+
* @param {string[]} texts - An array of texts to be searched.
|
|
122
|
+
*/
|
|
123
|
+
clickTexts(texts: string[]): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Searches for an element of type button
|
|
126
|
+
* with a label and clicks it when found.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} label - The buttons label.
|
|
129
|
+
*/
|
|
130
|
+
clickButton(label: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Searches for an element of type textfield with a specific placeholder text.
|
|
133
|
+
* If found, clicks it.
|
|
134
|
+
*
|
|
135
|
+
* @param {string} placeholder - The textfields placeholder text.
|
|
136
|
+
*/
|
|
137
|
+
clickTextfield(placeholder: string): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Clicks an icon based on a description.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} description
|
|
142
|
+
*/
|
|
143
|
+
clickIcon(description: string): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Drags element1 to element2.
|
|
146
|
+
*
|
|
147
|
+
* Both must be a `moveMouse()` or `moveMouseTo()`
|
|
148
|
+
* instruction as in the example below.
|
|
149
|
+
*
|
|
150
|
+
* Usage example:
|
|
151
|
+
* dragTo(
|
|
152
|
+
* aui.moveMouseTo().text('AskUI'),
|
|
153
|
+
* aui.moveMouseTo().text('UI Automation')
|
|
154
|
+
* )
|
|
155
|
+
*
|
|
156
|
+
* @param {Executable} element1
|
|
157
|
+
* @param {Executable} element2
|
|
158
|
+
*/
|
|
159
|
+
dragTo(element1: Executable, element2: Executable): Promise<void>;
|
|
160
|
+
/**
|
|
161
|
+
* Wait until an AskUICommand does not fail.
|
|
162
|
+
*
|
|
163
|
+
* Use it to wait for an element to appear like this:
|
|
164
|
+
*
|
|
165
|
+
* await waitUntil(
|
|
166
|
+
* aui.expect().text('Github').exists()
|
|
167
|
+
* );
|
|
168
|
+
*
|
|
169
|
+
* @param {Executable} AskUICommand - For example: aui.moveMouse(0, 0)
|
|
170
|
+
* @param {number} maxTry - Number of maximum retries
|
|
171
|
+
* @param {number} waitTime - Time in milliseconds
|
|
172
|
+
*/
|
|
173
|
+
waitUntil(AskUICommand: Executable, maxTry?: number, waitTime?: number): Promise<void>;
|
|
93
174
|
}
|
|
@@ -214,4 +214,145 @@ export class UiControlClient extends ApiCommands {
|
|
|
214
214
|
},
|
|
215
215
|
};
|
|
216
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Press a key multiple times. At least two times.
|
|
219
|
+
*
|
|
220
|
+
* @param {PC_AND_MODIFIER_KEY} key
|
|
221
|
+
*
|
|
222
|
+
* @param {number} times
|
|
223
|
+
*/
|
|
224
|
+
pressKeyNTimes(key, times = 2) {
|
|
225
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
+
/* eslint-disable no-await-in-loop */
|
|
227
|
+
for (let i = 0; i < times; i += 1) {
|
|
228
|
+
yield this.pressKey(key).exec();
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Press an array of keys one after another.
|
|
234
|
+
*
|
|
235
|
+
* For example press the following keys: right, left, enter.
|
|
236
|
+
*
|
|
237
|
+
* pressKeys(['right', 'left', 'enter'])
|
|
238
|
+
*
|
|
239
|
+
* @param {PC_AND_MODIFIER_KEY[]} keys
|
|
240
|
+
*/
|
|
241
|
+
pressKeys(keys) {
|
|
242
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
243
|
+
/* eslint-disable no-await-in-loop */
|
|
244
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
245
|
+
yield this.pressKey(keys[i]).exec();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Searches for a text element and clicks it when found.
|
|
251
|
+
*
|
|
252
|
+
* @param {string} text - A text to be searched.
|
|
253
|
+
*/
|
|
254
|
+
clickText(text) {
|
|
255
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
256
|
+
yield this.click().text(text).exec();
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Searches for text elements and clicks them
|
|
261
|
+
* one after another when found.
|
|
262
|
+
*
|
|
263
|
+
* @param {string[]} texts - An array of texts to be searched.
|
|
264
|
+
*/
|
|
265
|
+
clickTexts(texts) {
|
|
266
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
267
|
+
/* eslint-disable no-await-in-loop */
|
|
268
|
+
for (let i = 0; i < texts.length; i += 1) {
|
|
269
|
+
yield this.click().text(texts[i]).exec();
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Searches for an element of type button
|
|
275
|
+
* with a label and clicks it when found.
|
|
276
|
+
*
|
|
277
|
+
* @param {string} label - The buttons label.
|
|
278
|
+
*/
|
|
279
|
+
clickButton(label) {
|
|
280
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
281
|
+
yield this.click().button().withText(label).exec();
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Searches for an element of type textfield with a specific placeholder text.
|
|
286
|
+
* If found, clicks it.
|
|
287
|
+
*
|
|
288
|
+
* @param {string} placeholder - The textfields placeholder text.
|
|
289
|
+
*/
|
|
290
|
+
clickTextfield(placeholder) {
|
|
291
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
292
|
+
yield this.click().textfield().contains().text()
|
|
293
|
+
.withText(placeholder)
|
|
294
|
+
.exec();
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Clicks an icon based on a description.
|
|
299
|
+
*
|
|
300
|
+
* @param {string} description
|
|
301
|
+
*/
|
|
302
|
+
clickIcon(description) {
|
|
303
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
304
|
+
yield this.click().icon().matching(description).exec();
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Drags element1 to element2.
|
|
309
|
+
*
|
|
310
|
+
* Both must be a `moveMouse()` or `moveMouseTo()`
|
|
311
|
+
* instruction as in the example below.
|
|
312
|
+
*
|
|
313
|
+
* Usage example:
|
|
314
|
+
* dragTo(
|
|
315
|
+
* aui.moveMouseTo().text('AskUI'),
|
|
316
|
+
* aui.moveMouseTo().text('UI Automation')
|
|
317
|
+
* )
|
|
318
|
+
*
|
|
319
|
+
* @param {Executable} element1
|
|
320
|
+
* @param {Executable} element2
|
|
321
|
+
*/
|
|
322
|
+
dragTo(element1, element2) {
|
|
323
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
324
|
+
yield element1.exec();
|
|
325
|
+
yield this.mouseLeftClick().exec();
|
|
326
|
+
yield this.mouseToggleDown().exec();
|
|
327
|
+
yield element2.exec();
|
|
328
|
+
yield this.mouseToggleUp().exec();
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Wait until an AskUICommand does not fail.
|
|
333
|
+
*
|
|
334
|
+
* Use it to wait for an element to appear like this:
|
|
335
|
+
*
|
|
336
|
+
* await waitUntil(
|
|
337
|
+
* aui.expect().text('Github').exists()
|
|
338
|
+
* );
|
|
339
|
+
*
|
|
340
|
+
* @param {Executable} AskUICommand - For example: aui.moveMouse(0, 0)
|
|
341
|
+
* @param {number} maxTry - Number of maximum retries
|
|
342
|
+
* @param {number} waitTime - Time in milliseconds
|
|
343
|
+
*/
|
|
344
|
+
waitUntil(AskUICommand, maxTry = 5, waitTime = 2000) {
|
|
345
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
346
|
+
try {
|
|
347
|
+
yield AskUICommand.exec();
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
if (maxTry === 0) {
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
yield this.waitFor(waitTime).exec();
|
|
354
|
+
yield this.waitUntil(AskUICommand, maxTry - 1);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
217
358
|
}
|
|
@@ -17,7 +17,7 @@ export declare class CreateExampleProject {
|
|
|
17
17
|
private createAskUIHelperFromTemplate;
|
|
18
18
|
private setupTestFrameWork;
|
|
19
19
|
private installTestFrameworkPackages;
|
|
20
|
-
private
|
|
20
|
+
private addUserCredentials;
|
|
21
21
|
private copyESLintConfigFiles;
|
|
22
22
|
private copyTsConfigFile;
|
|
23
23
|
private installProxy;
|
|
@@ -179,10 +179,10 @@ export class CreateExampleProject {
|
|
|
179
179
|
yield runCommand(frameworkDepencies[this.cliOptions.testFramework]);
|
|
180
180
|
});
|
|
181
181
|
}
|
|
182
|
-
|
|
182
|
+
addUserCredentials() {
|
|
183
183
|
return __awaiter(this, void 0, void 0, function* () {
|
|
184
184
|
return [{
|
|
185
|
-
title: 'Add user
|
|
185
|
+
title: 'Add user credentials',
|
|
186
186
|
task: () => __awaiter(this, void 0, void 0, function* () {
|
|
187
187
|
return new Listr([
|
|
188
188
|
{
|
|
@@ -266,7 +266,7 @@ export class CreateExampleProject {
|
|
|
266
266
|
...yield this.setupTestFrameWork(),
|
|
267
267
|
...yield this.copyESLintConfigFiles(),
|
|
268
268
|
...yield this.copyTsConfigFile(),
|
|
269
|
-
...yield this.
|
|
269
|
+
...yield this.addUserCredentials(),
|
|
270
270
|
...yield this.createAskUIHelperFromTemplate(),
|
|
271
271
|
...yield this.installProxy(),
|
|
272
272
|
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "askui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.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",
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
"nunjucks": "^3.2.4",
|
|
63
63
|
"pino": "7.8.1",
|
|
64
64
|
"pino-pretty": "7.5.3",
|
|
65
|
-
"tough-cookie": "4.1.
|
|
65
|
+
"tough-cookie": "^4.1.3",
|
|
66
66
|
"url-join": "4.0.1",
|
|
67
67
|
"wait-port": "0.2.9",
|
|
68
|
-
"ws": "7.
|
|
68
|
+
"ws": "^7.5.9",
|
|
69
69
|
"yup": "0.32.11"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"jest": "28.1.1",
|
|
85
85
|
"jest-extended": "^4.0.1",
|
|
86
86
|
"proxy": "^1.0.2",
|
|
87
|
-
"proxy-agent": "^
|
|
87
|
+
"proxy-agent": "^6.3.1",
|
|
88
88
|
"shx": "0.3.4",
|
|
89
89
|
"ts-jest": "28.0.4",
|
|
90
90
|
"typescript": "4.5.4"
|
|
@@ -1,75 +0,0 @@
|
|
|
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
|
-
}
|