askui 0.17.0 → 0.18.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/context.d.ts +12 -0
- package/dist/cjs/execution/context.js +2 -0
- package/dist/cjs/execution/index.d.ts +1 -1
- package/dist/cjs/execution/ui-control-client-dependency-builder.js +9 -3
- package/dist/cjs/execution/ui-control-client.d.ts +154 -13
- package/dist/cjs/execution/ui-control-client.js +219 -21
- package/dist/cjs/execution/ui-controller-client-interface.d.ts +41 -19
- package/dist/cjs/lib/interactive_cli/create-example-project.js +1 -1
- package/dist/cjs/main.d.ts +1 -1
- package/dist/cjs/utils/analytics/analytics-interface.d.ts +2 -1
- package/dist/cjs/utils/analytics/analytics.d.ts +2 -1
- package/dist/cjs/utils/analytics/analytics.js +3 -2
- package/dist/esm/execution/context.d.ts +12 -0
- package/dist/esm/execution/context.js +1 -0
- package/dist/esm/execution/index.d.ts +1 -1
- package/dist/esm/execution/ui-control-client-dependency-builder.js +6 -3
- package/dist/esm/execution/ui-control-client.d.ts +154 -13
- package/dist/esm/execution/ui-control-client.js +216 -21
- package/dist/esm/execution/ui-controller-client-interface.d.ts +41 -19
- package/dist/esm/lib/interactive_cli/create-example-project.js +1 -1
- package/dist/esm/main.d.ts +1 -1
- package/dist/esm/utils/analytics/analytics-interface.d.ts +2 -1
- package/dist/esm/utils/analytics/analytics.d.ts +2 -1
- package/dist/esm/utils/analytics/analytics.js +3 -2
- package/dist/example_projects_templates/typescript/.eslintrc.json-template +3 -2
- package/package.json +7 -5
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context object to provide additional information about the context of (test) automation.
|
|
3
|
+
*
|
|
4
|
+
* @property {boolean} isCi - Default: Determined automatically by https://github.com/watson/is-ci;
|
|
5
|
+
* see https://github.com/watson/ci-info#supported-ci-tools for all supported CI tools.
|
|
6
|
+
* Can be used for overriding the automatic detection of CI tools, e.g., if not supported by
|
|
7
|
+
* `is-ci`, so that AskUI can be optimized for the corresponding environment, e.g., adjusting
|
|
8
|
+
* caching behavior.
|
|
9
|
+
*/
|
|
10
|
+
export interface Context {
|
|
11
|
+
readonly isCi: boolean;
|
|
12
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { UiControlClient } from './ui-control-client';
|
|
1
|
+
export { UiControlClient, RelationsForConvenienceMethods } from './ui-control-client';
|
|
@@ -8,8 +8,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.UiControlClientDependencyBuilder = void 0;
|
|
16
|
+
const is_ci_1 = __importDefault(require("is-ci"));
|
|
13
17
|
const http_client_got_1 = require("../utils/http/http-client-got");
|
|
14
18
|
const ui_controller_client_1 = require("./ui-controller-client");
|
|
15
19
|
const inference_client_1 = require("./inference-client");
|
|
@@ -23,7 +27,7 @@ class UiControlClientDependencyBuilder {
|
|
|
23
27
|
var _a;
|
|
24
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
29
|
const analytics = new analytics_1.Analytics();
|
|
26
|
-
const analyticsHeaders = yield analytics.getAnalyticsHeaders();
|
|
30
|
+
const analyticsHeaders = yield analytics.getAnalyticsHeaders(clientArgs.context);
|
|
27
31
|
const analyticsCookies = yield analytics.getAnalyticsCookies();
|
|
28
32
|
return new http_client_got_1.HttpClientGot((_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.token, analyticsHeaders, analyticsCookies, clientArgs.proxyAgents);
|
|
29
33
|
});
|
|
@@ -50,9 +54,11 @@ class UiControlClientDependencyBuilder {
|
|
|
50
54
|
});
|
|
51
55
|
}
|
|
52
56
|
static getClientArgsWithDefaults(clientArgs) {
|
|
53
|
-
var _a, _b, _c;
|
|
57
|
+
var _a, _b, _c, _d, _e;
|
|
54
58
|
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
-
return Object.assign(Object.assign({}, clientArgs), {
|
|
59
|
+
return Object.assign(Object.assign({}, clientArgs), { context: {
|
|
60
|
+
isCi: (_b = (_a = clientArgs.context) === null || _a === void 0 ? void 0 : _a.isCi) !== null && _b !== void 0 ? _b : is_ci_1.default,
|
|
61
|
+
}, credentials: (0, read_credentials_1.readCredentials)(clientArgs), inferenceServerUrl: (_c = clientArgs.inferenceServerUrl) !== null && _c !== void 0 ? _c : 'https://inference.askui.com', proxyAgents: (_d = clientArgs.proxyAgents) !== null && _d !== void 0 ? _d : (yield (0, proxy_builder_1.envProxyAgents)()), uiControllerUrl: (_e = clientArgs.uiControllerUrl) !== null && _e !== void 0 ? _e : 'http://127.0.0.1:6769' });
|
|
56
62
|
});
|
|
57
63
|
}
|
|
58
64
|
}
|
|
@@ -5,6 +5,7 @@ import { Annotation } from '../core/annotation/annotation';
|
|
|
5
5
|
import { AnnotationRequest } from '../core/model/annotation-result/annotation-interface';
|
|
6
6
|
import { DetectedElement } from '../core/model/annotation-result/detected-element';
|
|
7
7
|
import { ClientArgs } from './ui-controller-client-interface';
|
|
8
|
+
export declare type RelationsForConvenienceMethods = 'nearestTo' | 'leftOf' | 'above' | 'rightOf' | 'below' | 'contains';
|
|
8
9
|
export declare class UiControlClient extends ApiCommands {
|
|
9
10
|
private executionRuntime;
|
|
10
11
|
private stepReporter;
|
|
@@ -108,12 +109,6 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
108
109
|
* @param {PC_AND_MODIFIER_KEY[]} keys
|
|
109
110
|
*/
|
|
110
111
|
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
112
|
/**
|
|
118
113
|
* Searches for text elements and clicks them
|
|
119
114
|
* one after another when found.
|
|
@@ -121,13 +116,6 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
121
116
|
* @param {string[]} texts - An array of texts to be searched.
|
|
122
117
|
*/
|
|
123
118
|
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
119
|
/**
|
|
132
120
|
* Searches for an element of type textfield with a specific placeholder text.
|
|
133
121
|
* If found, clicks it.
|
|
@@ -162,4 +150,157 @@ export declare class UiControlClient extends ApiCommands {
|
|
|
162
150
|
* @param {number} waitTime - Time in milliseconds
|
|
163
151
|
*/
|
|
164
152
|
waitUntil(AskUICommand: Executable, maxTry?: number, waitTime?: number): Promise<void>;
|
|
153
|
+
private evaluateRelation;
|
|
154
|
+
/**
|
|
155
|
+
* Click a button with a specific label.
|
|
156
|
+
* Optional relation identifies the button in relation to another element.
|
|
157
|
+
*
|
|
158
|
+
* **Examples:**
|
|
159
|
+
* ```typescript
|
|
160
|
+
* await aui.clickButton({})
|
|
161
|
+
* await aui.clickButton({label: 'Checkout here'})
|
|
162
|
+
* await aui.clickButton({relation: {type: 'leftOf', text: 'Choose a ticket'}})
|
|
163
|
+
* await aui.clickButton({label: 'Click', {relation: {type: 'leftOf', text: 'Choose a ticket'}})
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* @param {Object} params - Object containing properties.
|
|
167
|
+
* @property {string} [params.label] - The text label of the button. Defaults to an empty string.
|
|
168
|
+
* @property {Object} [params.relation] - Object describing the relationship between
|
|
169
|
+
* the clicked button and another element.
|
|
170
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
171
|
+
* @property {string} params.relation.text - The text element the relation is based on.
|
|
172
|
+
*/
|
|
173
|
+
clickButton(params: {
|
|
174
|
+
label?: string;
|
|
175
|
+
relation?: {
|
|
176
|
+
type: RelationsForConvenienceMethods;
|
|
177
|
+
text: string;
|
|
178
|
+
};
|
|
179
|
+
}): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Click a checkbox with a specific label.
|
|
182
|
+
* You can also specify where the label is placed relationally.
|
|
183
|
+
*
|
|
184
|
+
* **Examples:**
|
|
185
|
+
* ```typescript
|
|
186
|
+
* await aui.clickCheckbox({label: 'Toggle'})
|
|
187
|
+
* await aui.clickCheckbox({label: 'Toggle', relation: {type: 'leftOf'}})
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @param {Object} params - Object containing required `label` property and
|
|
191
|
+
* optional `relation` property.
|
|
192
|
+
* @property {string} params.label - The label for the checkbox.
|
|
193
|
+
* @property {Object} params.relation - Object describing the relationship between
|
|
194
|
+
* the clicked checkbox and another element.
|
|
195
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
196
|
+
*/
|
|
197
|
+
clickCheckbox(params: {
|
|
198
|
+
label: string;
|
|
199
|
+
relation?: {
|
|
200
|
+
type: RelationsForConvenienceMethods;
|
|
201
|
+
};
|
|
202
|
+
}): Promise<void>;
|
|
203
|
+
/**
|
|
204
|
+
* Click a switch with a specific label.
|
|
205
|
+
* You can also specify where the label is placed relationally.
|
|
206
|
+
*
|
|
207
|
+
* **Examples:**
|
|
208
|
+
* ```typescript
|
|
209
|
+
* await aui.clickSwitch({label: 'Toggle'})
|
|
210
|
+
* await aui.clickSwitch({label: 'Toggle', relation: {type: 'leftOf'}})
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* @param {Object} params - Object containing required `label` property and
|
|
214
|
+
* optional `relation` property.
|
|
215
|
+
* @property {string} params.label - The label for the checkbox.
|
|
216
|
+
* @property {Object} params.relation - Object describing the relationship between
|
|
217
|
+
* the clicked checkbox and another element.
|
|
218
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
219
|
+
*/
|
|
220
|
+
clickSwitch(params: {
|
|
221
|
+
label: string;
|
|
222
|
+
relation?: {
|
|
223
|
+
type: RelationsForConvenienceMethods;
|
|
224
|
+
};
|
|
225
|
+
}): Promise<void>;
|
|
226
|
+
/**
|
|
227
|
+
* Types a given text into a textfield.
|
|
228
|
+
* Use a relation to specify how to find
|
|
229
|
+
* the textfield in relation to a specific label.
|
|
230
|
+
*
|
|
231
|
+
* **Examples:**
|
|
232
|
+
* ```typescript
|
|
233
|
+
* // Finds the textfield nearest to the label 'Email'
|
|
234
|
+
* await aui.typeIntoTextfield({textToWrite: 'Hello World', relation: {label: 'Email'}});
|
|
235
|
+
*
|
|
236
|
+
* // Finds the textfield above/below a label 'Password'
|
|
237
|
+
* await aui.typeIntoTextfield(
|
|
238
|
+
* {textToWrite: 'Hello World', relation: {type: 'above', label: 'Password'}}
|
|
239
|
+
* );
|
|
240
|
+
* await aui.typeIntoTextfield(
|
|
241
|
+
* {textToWrite: 'Hello World', relation: {type: 'below', label: 'Password'}}
|
|
242
|
+
* );
|
|
243
|
+
*
|
|
244
|
+
* // If there is no label but a placeholder, the label is contained in the textfield
|
|
245
|
+
* await aui.typeIntoTextfield(
|
|
246
|
+
* {textToWrite: 'Hello World', relation: {type: 'contains', label: 'Enter email'}}
|
|
247
|
+
* );
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @param {Object} params - Object containing required `textToWrite` property and
|
|
251
|
+
* optional `relation` property.
|
|
252
|
+
* @property {string} params.textToWrite - The text to be typed into the textfield.
|
|
253
|
+
* @property {Object} params.relation - Object describing the relationship between the
|
|
254
|
+
* textfield being interacted with and another element.
|
|
255
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of
|
|
256
|
+
* relation, optional.
|
|
257
|
+
* @property {string} params.relation.label - The label associated with the related
|
|
258
|
+
* element, optional.
|
|
259
|
+
*/
|
|
260
|
+
typeIntoTextfield(params: {
|
|
261
|
+
textToWrite: string;
|
|
262
|
+
relation: {
|
|
263
|
+
type?: RelationsForConvenienceMethods;
|
|
264
|
+
label: string;
|
|
265
|
+
};
|
|
266
|
+
}): Promise<void>;
|
|
267
|
+
/**
|
|
268
|
+
* Click on a specific text.
|
|
269
|
+
* You can also use a RegEx or match the text exactly by specifyicing the specific flag.
|
|
270
|
+
* Use a relation to find the text in relation to a specific text.
|
|
271
|
+
*
|
|
272
|
+
* **Examples:**
|
|
273
|
+
* ```typescript
|
|
274
|
+
* // Click text that matches exactly
|
|
275
|
+
* await aui.clickText({text: 'askui', type: 'similar'})
|
|
276
|
+
*
|
|
277
|
+
* // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
|
|
278
|
+
* await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', type: 'regex'})
|
|
279
|
+
*
|
|
280
|
+
* // Click the text 'TERMINAL' that is left of the text 'Ports'
|
|
281
|
+
* await aui.clickText({
|
|
282
|
+
* text: 'TERMINAL',
|
|
283
|
+
* type: "exact",
|
|
284
|
+
* relation: { type: 'leftOf', text: 'PORTS' }
|
|
285
|
+
* })
|
|
286
|
+
* ```
|
|
287
|
+
* @param {Object} params - Object containing required `text` property and optional properties
|
|
288
|
+
* for regular expression matching and relation.
|
|
289
|
+
* @property {string} params.text - The text to be clicked.
|
|
290
|
+
* @property {string} params.type - Whether the text is matched using similarity,
|
|
291
|
+
* exact match or a regular expression.
|
|
292
|
+
* @property {Object} params.relation - Object describing the relationship between the
|
|
293
|
+
* clicked text and another element.
|
|
294
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
295
|
+
* @property {string} params.relation.text - The label or text associated with the
|
|
296
|
+
* related element or state.
|
|
297
|
+
*/
|
|
298
|
+
clickText(params: {
|
|
299
|
+
text: string;
|
|
300
|
+
type: 'similar' | 'exact' | 'regex';
|
|
301
|
+
relation?: {
|
|
302
|
+
type: RelationsForConvenienceMethods;
|
|
303
|
+
text: string;
|
|
304
|
+
};
|
|
305
|
+
}): Promise<void>;
|
|
165
306
|
}
|
|
@@ -8,8 +8,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.UiControlClient = void 0;
|
|
16
|
+
const ValidationError_1 = __importDefault(require("yup/lib/ValidationError"));
|
|
13
17
|
const custom_element_1 = require("../core/model/custom-element");
|
|
14
18
|
const dsl_1 = require("./dsl");
|
|
15
19
|
const annotation_writer_1 = require("../core/annotation/annotation-writer");
|
|
@@ -249,16 +253,6 @@ class UiControlClient extends dsl_1.ApiCommands {
|
|
|
249
253
|
}
|
|
250
254
|
});
|
|
251
255
|
}
|
|
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
256
|
/**
|
|
263
257
|
* Searches for text elements and clicks them
|
|
264
258
|
* one after another when found.
|
|
@@ -273,17 +267,6 @@ class UiControlClient extends dsl_1.ApiCommands {
|
|
|
273
267
|
}
|
|
274
268
|
});
|
|
275
269
|
}
|
|
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
270
|
/**
|
|
288
271
|
* Searches for an element of type textfield with a specific placeholder text.
|
|
289
272
|
* If found, clicks it.
|
|
@@ -346,5 +329,220 @@ class UiControlClient extends dsl_1.ApiCommands {
|
|
|
346
329
|
}
|
|
347
330
|
});
|
|
348
331
|
}
|
|
332
|
+
// eslint-disable-next-line class-methods-use-this
|
|
333
|
+
evaluateRelation(command, relation, text) {
|
|
334
|
+
let commando = command;
|
|
335
|
+
switch (relation) {
|
|
336
|
+
case 'nearestTo':
|
|
337
|
+
commando = command.nearestTo().text(text);
|
|
338
|
+
break;
|
|
339
|
+
case 'leftOf':
|
|
340
|
+
commando = command.leftOf().text(text);
|
|
341
|
+
break;
|
|
342
|
+
case 'above':
|
|
343
|
+
commando = command.above().text(text);
|
|
344
|
+
break;
|
|
345
|
+
case 'rightOf':
|
|
346
|
+
commando = command.rightOf().text(text);
|
|
347
|
+
break;
|
|
348
|
+
case 'below':
|
|
349
|
+
commando = command.below().text(text);
|
|
350
|
+
break;
|
|
351
|
+
case 'contains':
|
|
352
|
+
commando = command.contains().text(text);
|
|
353
|
+
break;
|
|
354
|
+
default:
|
|
355
|
+
throw new ValidationError_1.default('No valid Relation.Type was passed.');
|
|
356
|
+
}
|
|
357
|
+
return commando;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Click a button with a specific label.
|
|
361
|
+
* Optional relation identifies the button in relation to another element.
|
|
362
|
+
*
|
|
363
|
+
* **Examples:**
|
|
364
|
+
* ```typescript
|
|
365
|
+
* await aui.clickButton({})
|
|
366
|
+
* await aui.clickButton({label: 'Checkout here'})
|
|
367
|
+
* await aui.clickButton({relation: {type: 'leftOf', text: 'Choose a ticket'}})
|
|
368
|
+
* await aui.clickButton({label: 'Click', {relation: {type: 'leftOf', text: 'Choose a ticket'}})
|
|
369
|
+
* ```
|
|
370
|
+
*
|
|
371
|
+
* @param {Object} params - Object containing properties.
|
|
372
|
+
* @property {string} [params.label] - The text label of the button. Defaults to an empty string.
|
|
373
|
+
* @property {Object} [params.relation] - Object describing the relationship between
|
|
374
|
+
* the clicked button and another element.
|
|
375
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
376
|
+
* @property {string} params.relation.text - The text element the relation is based on.
|
|
377
|
+
*/
|
|
378
|
+
clickButton(params) {
|
|
379
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
380
|
+
let command = this.click().button();
|
|
381
|
+
if (params.label) {
|
|
382
|
+
command = command.withText(params.label);
|
|
383
|
+
}
|
|
384
|
+
if (params.relation) {
|
|
385
|
+
command = this.evaluateRelation(command, params.relation.type, params.relation.text);
|
|
386
|
+
}
|
|
387
|
+
yield command.exec();
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Click a checkbox with a specific label.
|
|
392
|
+
* You can also specify where the label is placed relationally.
|
|
393
|
+
*
|
|
394
|
+
* **Examples:**
|
|
395
|
+
* ```typescript
|
|
396
|
+
* await aui.clickCheckbox({label: 'Toggle'})
|
|
397
|
+
* await aui.clickCheckbox({label: 'Toggle', relation: {type: 'leftOf'}})
|
|
398
|
+
* ```
|
|
399
|
+
*
|
|
400
|
+
* @param {Object} params - Object containing required `label` property and
|
|
401
|
+
* optional `relation` property.
|
|
402
|
+
* @property {string} params.label - The label for the checkbox.
|
|
403
|
+
* @property {Object} params.relation - Object describing the relationship between
|
|
404
|
+
* the clicked checkbox and another element.
|
|
405
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
406
|
+
*/
|
|
407
|
+
clickCheckbox(params) {
|
|
408
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
+
let command = this.click().checkbox();
|
|
410
|
+
if (!params.relation) {
|
|
411
|
+
command = command.nearestTo().text(params.label);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
command = this.evaluateRelation(command, params.relation.type, params.label);
|
|
415
|
+
}
|
|
416
|
+
yield command.exec();
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Click a switch with a specific label.
|
|
421
|
+
* You can also specify where the label is placed relationally.
|
|
422
|
+
*
|
|
423
|
+
* **Examples:**
|
|
424
|
+
* ```typescript
|
|
425
|
+
* await aui.clickSwitch({label: 'Toggle'})
|
|
426
|
+
* await aui.clickSwitch({label: 'Toggle', relation: {type: 'leftOf'}})
|
|
427
|
+
* ```
|
|
428
|
+
*
|
|
429
|
+
* @param {Object} params - Object containing required `label` property and
|
|
430
|
+
* optional `relation` property.
|
|
431
|
+
* @property {string} params.label - The label for the checkbox.
|
|
432
|
+
* @property {Object} params.relation - Object describing the relationship between
|
|
433
|
+
* the clicked checkbox and another element.
|
|
434
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
435
|
+
*/
|
|
436
|
+
clickSwitch(params) {
|
|
437
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
438
|
+
let command = this.click().switch();
|
|
439
|
+
if (!params.relation) {
|
|
440
|
+
command = command.nearestTo().text(params.label);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
command = this.evaluateRelation(command, params.relation.type, params.label);
|
|
444
|
+
}
|
|
445
|
+
yield command.exec();
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Types a given text into a textfield.
|
|
450
|
+
* Use a relation to specify how to find
|
|
451
|
+
* the textfield in relation to a specific label.
|
|
452
|
+
*
|
|
453
|
+
* **Examples:**
|
|
454
|
+
* ```typescript
|
|
455
|
+
* // Finds the textfield nearest to the label 'Email'
|
|
456
|
+
* await aui.typeIntoTextfield({textToWrite: 'Hello World', relation: {label: 'Email'}});
|
|
457
|
+
*
|
|
458
|
+
* // Finds the textfield above/below a label 'Password'
|
|
459
|
+
* await aui.typeIntoTextfield(
|
|
460
|
+
* {textToWrite: 'Hello World', relation: {type: 'above', label: 'Password'}}
|
|
461
|
+
* );
|
|
462
|
+
* await aui.typeIntoTextfield(
|
|
463
|
+
* {textToWrite: 'Hello World', relation: {type: 'below', label: 'Password'}}
|
|
464
|
+
* );
|
|
465
|
+
*
|
|
466
|
+
* // If there is no label but a placeholder, the label is contained in the textfield
|
|
467
|
+
* await aui.typeIntoTextfield(
|
|
468
|
+
* {textToWrite: 'Hello World', relation: {type: 'contains', label: 'Enter email'}}
|
|
469
|
+
* );
|
|
470
|
+
* ```
|
|
471
|
+
*
|
|
472
|
+
* @param {Object} params - Object containing required `textToWrite` property and
|
|
473
|
+
* optional `relation` property.
|
|
474
|
+
* @property {string} params.textToWrite - The text to be typed into the textfield.
|
|
475
|
+
* @property {Object} params.relation - Object describing the relationship between the
|
|
476
|
+
* textfield being interacted with and another element.
|
|
477
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of
|
|
478
|
+
* relation, optional.
|
|
479
|
+
* @property {string} params.relation.label - The label associated with the related
|
|
480
|
+
* element, optional.
|
|
481
|
+
*/
|
|
482
|
+
typeIntoTextfield(params) {
|
|
483
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
484
|
+
let command = this.typeIn(params.textToWrite).textfield();
|
|
485
|
+
if (!params.relation.type) {
|
|
486
|
+
command = command.nearestTo().text(params.relation.label);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
command = this.evaluateRelation(command, params.relation.type, params.relation.label);
|
|
490
|
+
}
|
|
491
|
+
yield command.exec();
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Click on a specific text.
|
|
496
|
+
* You can also use a RegEx or match the text exactly by specifyicing the specific flag.
|
|
497
|
+
* Use a relation to find the text in relation to a specific text.
|
|
498
|
+
*
|
|
499
|
+
* **Examples:**
|
|
500
|
+
* ```typescript
|
|
501
|
+
* // Click text that matches exactly
|
|
502
|
+
* await aui.clickText({text: 'askui', type: 'similar'})
|
|
503
|
+
*
|
|
504
|
+
* // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
|
|
505
|
+
* await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', type: 'regex'})
|
|
506
|
+
*
|
|
507
|
+
* // Click the text 'TERMINAL' that is left of the text 'Ports'
|
|
508
|
+
* await aui.clickText({
|
|
509
|
+
* text: 'TERMINAL',
|
|
510
|
+
* type: "exact",
|
|
511
|
+
* relation: { type: 'leftOf', text: 'PORTS' }
|
|
512
|
+
* })
|
|
513
|
+
* ```
|
|
514
|
+
* @param {Object} params - Object containing required `text` property and optional properties
|
|
515
|
+
* for regular expression matching and relation.
|
|
516
|
+
* @property {string} params.text - The text to be clicked.
|
|
517
|
+
* @property {string} params.type - Whether the text is matched using similarity,
|
|
518
|
+
* exact match or a regular expression.
|
|
519
|
+
* @property {Object} params.relation - Object describing the relationship between the
|
|
520
|
+
* clicked text and another element.
|
|
521
|
+
* @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
|
|
522
|
+
* @property {string} params.relation.text - The label or text associated with the
|
|
523
|
+
* related element or state.
|
|
524
|
+
*/
|
|
525
|
+
clickText(params) {
|
|
526
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
527
|
+
let command = this.click().text();
|
|
528
|
+
switch (params.type) {
|
|
529
|
+
case 'similar':
|
|
530
|
+
command = command.withText(params.text);
|
|
531
|
+
break;
|
|
532
|
+
case 'exact':
|
|
533
|
+
command = command.withExactText(params.text);
|
|
534
|
+
break;
|
|
535
|
+
case 'regex':
|
|
536
|
+
command = command.withTextRegex(params.text);
|
|
537
|
+
break;
|
|
538
|
+
default:
|
|
539
|
+
throw new ValidationError_1.default('"type" must be "similar", "exact" or "regex"');
|
|
540
|
+
}
|
|
541
|
+
if (params.relation) {
|
|
542
|
+
command = this.evaluateRelation(command, params.relation.type, params.relation.text);
|
|
543
|
+
}
|
|
544
|
+
yield command.exec();
|
|
545
|
+
});
|
|
546
|
+
}
|
|
349
547
|
}
|
|
350
548
|
exports.UiControlClient = UiControlClient;
|
|
@@ -2,27 +2,47 @@ import { CredentialArgs } from './credentials-args';
|
|
|
2
2
|
import { ProxyAgentArgs } from '../shared/proxy-agent-args';
|
|
3
3
|
import { ModelCompositionBranch } from './model-composition-branch';
|
|
4
4
|
import { Reporter } from '../core/reporting';
|
|
5
|
+
import { Context } from './context';
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* Context object to provide additional information about the context of (test) automation.
|
|
7
8
|
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* @
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @
|
|
24
|
-
*
|
|
25
|
-
*
|
|
9
|
+
* @property {(boolean | undefined)} [isCi] - Default: Determined automatically by
|
|
10
|
+
* https://github.com/watson/is-ci; see https://github.com/watson/ci-info#supported-ci-tools for
|
|
11
|
+
* all supported CI tools. Can be used for overriding the automatic detection of CI tools, e.g.,
|
|
12
|
+
* if not supported by `is-ci`, so that AskUI can be optimized for the corresponding
|
|
13
|
+
* environment, e.g., adjusting caching behavior.
|
|
14
|
+
*/
|
|
15
|
+
export interface ContextArgs {
|
|
16
|
+
readonly isCi?: boolean | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Configuration options for AskUI's UiControlClient.
|
|
20
|
+
*
|
|
21
|
+
* @property {string} [uiControllerUrl] - Default: `'http://127.0.0.1:6769'`. The address of
|
|
22
|
+
* AskUI's UiController that interacts with the operating system, e.g., simulating input
|
|
23
|
+
* events and capturing screenshots.
|
|
24
|
+
* @property {string} [inferenceServerUrl] - Default: `'https://inference.askui.com'`.
|
|
25
|
+
* Address of the AskUI's inference server which is responsible for understanding the
|
|
26
|
+
* screenshots and extracting data from them and returning commands for the UiController.
|
|
27
|
+
* @property {(CredentialArgs | undefined)} [credentials] - Optional. Credentials for
|
|
28
|
+
* the authenticating and authorizing with the inference server.
|
|
29
|
+
* @property {(ProxyAgentArgs | undefined)} [proxyAgents] - Optional. Proxy agents for http(s)
|
|
30
|
+
* requests against the inference server if running behind a proxy.
|
|
31
|
+
* @property {number} [resize] - Optional. Length in px to resize the screenshot image to before
|
|
32
|
+
* sending it to the inference server so that the screenshot image's longer side is equal to or
|
|
33
|
+
* less than it. Aspect ratio (of width and height) is preserved. This can be used to reduce the
|
|
34
|
+
* inference time by reducing the request size, e.g., if network bandwidth is limited. But it
|
|
35
|
+
* can cause a decrease in the prediction quality. If undefined, the screenshot image is not
|
|
36
|
+
* resized but sent as is.
|
|
37
|
+
* @property {(Reporter | Reporter[] | undefined)} [reporter] - Default: `[]`. To configure the
|
|
38
|
+
* reporter(s) to report on steps (see
|
|
39
|
+
* https://docs.askui.com/docs/next/general/Components/askui-ui-control-client#reporter).
|
|
40
|
+
* @property {ModelCompositionBranch[]} [modelComposition] - Default: `[]`. To configure the model
|
|
41
|
+
* composition for the inference server, i.e., which models are used for the inference, e.g.,
|
|
42
|
+
* test recognition or object detection.
|
|
43
|
+
* @property {(Context | undefined)} [context] - Optional. Context object to provide additional
|
|
44
|
+
* information about the context of (test) automation, e.g., to allow for optimizations based on
|
|
45
|
+
* the environment, e.g., CI/CD.
|
|
26
46
|
*/
|
|
27
47
|
export interface ClientArgs {
|
|
28
48
|
readonly uiControllerUrl?: string;
|
|
@@ -32,8 +52,10 @@ export interface ClientArgs {
|
|
|
32
52
|
readonly resize?: number;
|
|
33
53
|
readonly modelComposition?: ModelCompositionBranch[];
|
|
34
54
|
readonly reporter?: Reporter | Reporter[] | undefined;
|
|
55
|
+
readonly context?: ContextArgs | undefined;
|
|
35
56
|
}
|
|
36
57
|
export interface ClientArgsWithDefaults extends ClientArgs {
|
|
37
58
|
readonly uiControllerUrl: string;
|
|
38
59
|
readonly inferenceServerUrl: string;
|
|
60
|
+
readonly context: Context;
|
|
39
61
|
}
|
|
@@ -188,7 +188,7 @@ class CreateExampleProject {
|
|
|
188
188
|
return __awaiter(this, void 0, void 0, function* () {
|
|
189
189
|
const runCommand = (0, util_1.promisify)(child_process_1.exec);
|
|
190
190
|
const frameworkDependencies = {
|
|
191
|
-
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 hpagent',
|
|
191
|
+
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 @askui/eslint-plugin-askui hpagent',
|
|
192
192
|
};
|
|
193
193
|
yield runCommand(frameworkDependencies.jest);
|
|
194
194
|
});
|
package/dist/cjs/main.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { UiController } from './lib';
|
|
2
|
-
export { UiControlClient } from './execution';
|
|
2
|
+
export { UiControlClient, RelationsForConvenienceMethods } from './execution';
|
|
3
3
|
export { Instruction, Reporter, ReporterConfig, Snapshot, SnapshotDetailLevel, Step, StepStatus, StepStatusEnd, } from './core/reporting';
|
|
4
4
|
export { Annotation } from './core/annotation/annotation';
|
|
5
5
|
export { DetectedElement } from './core/model/annotation-result/detected-element';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AnalyticsInterface } from './analytics-interface';
|
|
2
|
+
import { Context } from '@/execution/context';
|
|
2
3
|
export declare class Analytics implements AnalyticsInterface {
|
|
3
4
|
private userIdentifier;
|
|
4
|
-
getAnalyticsHeaders(): Promise<Record<string, string>>;
|
|
5
|
+
getAnalyticsHeaders(context: Context): Promise<Record<string, string>>;
|
|
5
6
|
getAnalyticsCookies(): Promise<Record<string, string>>;
|
|
6
7
|
}
|
|
@@ -20,12 +20,13 @@ class Analytics {
|
|
|
20
20
|
constructor() {
|
|
21
21
|
this.userIdentifier = new user_identifier_1.UserIdentifier();
|
|
22
22
|
}
|
|
23
|
-
getAnalyticsHeaders() {
|
|
23
|
+
getAnalyticsHeaders(context) {
|
|
24
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
25
|
const userID = yield this.userIdentifier.userId();
|
|
26
26
|
const headers = {
|
|
27
|
-
'askui-
|
|
27
|
+
'askui-is-ci': String(context.isCi),
|
|
28
28
|
'askui-user-agent': `os:${os_1.default.platform()};arch:${os_1.default.arch()}`,
|
|
29
|
+
'askui-user-id': userID,
|
|
29
30
|
};
|
|
30
31
|
const askuiInstalledAt = yield installation_timestamp_1.InstallationTimestamp.get();
|
|
31
32
|
if (askuiInstalledAt) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context object to provide additional information about the context of (test) automation.
|
|
3
|
+
*
|
|
4
|
+
* @property {boolean} isCi - Default: Determined automatically by https://github.com/watson/is-ci;
|
|
5
|
+
* see https://github.com/watson/ci-info#supported-ci-tools for all supported CI tools.
|
|
6
|
+
* Can be used for overriding the automatic detection of CI tools, e.g., if not supported by
|
|
7
|
+
* `is-ci`, so that AskUI can be optimized for the corresponding environment, e.g., adjusting
|
|
8
|
+
* caching behavior.
|
|
9
|
+
*/
|
|
10
|
+
export interface Context {
|
|
11
|
+
readonly isCi: boolean;
|
|
12
|
+
}
|