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.
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1 @@
1
- export { UiControlClient } from './ui-control-client';
1
+ export { UiControlClient, RelationsForConvenienceMethods } from './ui-control-client';
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import isCI from 'is-ci';
10
11
  import { HttpClientGot } from '../utils/http/http-client-got';
11
12
  import { UiControllerClient } from './ui-controller-client';
12
13
  import { InferenceClient } from './inference-client';
@@ -20,7 +21,7 @@ export class UiControlClientDependencyBuilder {
20
21
  var _a;
21
22
  return __awaiter(this, void 0, void 0, function* () {
22
23
  const analytics = new Analytics();
23
- const analyticsHeaders = yield analytics.getAnalyticsHeaders();
24
+ const analyticsHeaders = yield analytics.getAnalyticsHeaders(clientArgs.context);
24
25
  const analyticsCookies = yield analytics.getAnalyticsCookies();
25
26
  return new HttpClientGot((_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.token, analyticsHeaders, analyticsCookies, clientArgs.proxyAgents);
26
27
  });
@@ -47,9 +48,11 @@ export class UiControlClientDependencyBuilder {
47
48
  });
48
49
  }
49
50
  static getClientArgsWithDefaults(clientArgs) {
50
- var _a, _b, _c;
51
+ var _a, _b, _c, _d, _e;
51
52
  return __awaiter(this, void 0, void 0, function* () {
52
- return Object.assign(Object.assign({}, clientArgs), { credentials: readCredentials(clientArgs), inferenceServerUrl: (_a = clientArgs.inferenceServerUrl) !== null && _a !== void 0 ? _a : 'https://inference.askui.com', proxyAgents: (_b = clientArgs.proxyAgents) !== null && _b !== void 0 ? _b : (yield envProxyAgents()), uiControllerUrl: (_c = clientArgs.uiControllerUrl) !== null && _c !== void 0 ? _c : 'http://127.0.0.1:6769' });
53
+ return Object.assign(Object.assign({}, clientArgs), { context: {
54
+ isCi: (_b = (_a = clientArgs.context) === null || _a === void 0 ? void 0 : _a.isCi) !== null && _b !== void 0 ? _b : isCI,
55
+ }, credentials: 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 envProxyAgents()), uiControllerUrl: (_e = clientArgs.uiControllerUrl) !== null && _e !== void 0 ? _e : 'http://127.0.0.1:6769' });
53
56
  });
54
57
  }
55
58
  }
@@ -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
  }
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import ValidationError from 'yup/lib/ValidationError';
10
11
  import { CustomElement } from '../core/model/custom-element';
11
12
  import { ApiCommands, Separators, } from './dsl';
12
13
  import { AnnotationWriter } from '../core/annotation/annotation-writer';
@@ -246,16 +247,6 @@ export class UiControlClient extends ApiCommands {
246
247
  }
247
248
  });
248
249
  }
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
250
  /**
260
251
  * Searches for text elements and clicks them
261
252
  * one after another when found.
@@ -270,17 +261,6 @@ export class UiControlClient extends ApiCommands {
270
261
  }
271
262
  });
272
263
  }
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
264
  /**
285
265
  * Searches for an element of type textfield with a specific placeholder text.
286
266
  * If found, clicks it.
@@ -343,4 +323,219 @@ export class UiControlClient extends ApiCommands {
343
323
  }
344
324
  });
345
325
  }
326
+ // eslint-disable-next-line class-methods-use-this
327
+ evaluateRelation(command, relation, text) {
328
+ let commando = command;
329
+ switch (relation) {
330
+ case 'nearestTo':
331
+ commando = command.nearestTo().text(text);
332
+ break;
333
+ case 'leftOf':
334
+ commando = command.leftOf().text(text);
335
+ break;
336
+ case 'above':
337
+ commando = command.above().text(text);
338
+ break;
339
+ case 'rightOf':
340
+ commando = command.rightOf().text(text);
341
+ break;
342
+ case 'below':
343
+ commando = command.below().text(text);
344
+ break;
345
+ case 'contains':
346
+ commando = command.contains().text(text);
347
+ break;
348
+ default:
349
+ throw new ValidationError('No valid Relation.Type was passed.');
350
+ }
351
+ return commando;
352
+ }
353
+ /**
354
+ * Click a button with a specific label.
355
+ * Optional relation identifies the button in relation to another element.
356
+ *
357
+ * **Examples:**
358
+ * ```typescript
359
+ * await aui.clickButton({})
360
+ * await aui.clickButton({label: 'Checkout here'})
361
+ * await aui.clickButton({relation: {type: 'leftOf', text: 'Choose a ticket'}})
362
+ * await aui.clickButton({label: 'Click', {relation: {type: 'leftOf', text: 'Choose a ticket'}})
363
+ * ```
364
+ *
365
+ * @param {Object} params - Object containing properties.
366
+ * @property {string} [params.label] - The text label of the button. Defaults to an empty string.
367
+ * @property {Object} [params.relation] - Object describing the relationship between
368
+ * the clicked button and another element.
369
+ * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
370
+ * @property {string} params.relation.text - The text element the relation is based on.
371
+ */
372
+ clickButton(params) {
373
+ return __awaiter(this, void 0, void 0, function* () {
374
+ let command = this.click().button();
375
+ if (params.label) {
376
+ command = command.withText(params.label);
377
+ }
378
+ if (params.relation) {
379
+ command = this.evaluateRelation(command, params.relation.type, params.relation.text);
380
+ }
381
+ yield command.exec();
382
+ });
383
+ }
384
+ /**
385
+ * Click a checkbox with a specific label.
386
+ * You can also specify where the label is placed relationally.
387
+ *
388
+ * **Examples:**
389
+ * ```typescript
390
+ * await aui.clickCheckbox({label: 'Toggle'})
391
+ * await aui.clickCheckbox({label: 'Toggle', relation: {type: 'leftOf'}})
392
+ * ```
393
+ *
394
+ * @param {Object} params - Object containing required `label` property and
395
+ * optional `relation` property.
396
+ * @property {string} params.label - The label for the checkbox.
397
+ * @property {Object} params.relation - Object describing the relationship between
398
+ * the clicked checkbox and another element.
399
+ * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
400
+ */
401
+ clickCheckbox(params) {
402
+ return __awaiter(this, void 0, void 0, function* () {
403
+ let command = this.click().checkbox();
404
+ if (!params.relation) {
405
+ command = command.nearestTo().text(params.label);
406
+ }
407
+ else {
408
+ command = this.evaluateRelation(command, params.relation.type, params.label);
409
+ }
410
+ yield command.exec();
411
+ });
412
+ }
413
+ /**
414
+ * Click a switch with a specific label.
415
+ * You can also specify where the label is placed relationally.
416
+ *
417
+ * **Examples:**
418
+ * ```typescript
419
+ * await aui.clickSwitch({label: 'Toggle'})
420
+ * await aui.clickSwitch({label: 'Toggle', relation: {type: 'leftOf'}})
421
+ * ```
422
+ *
423
+ * @param {Object} params - Object containing required `label` property and
424
+ * optional `relation` property.
425
+ * @property {string} params.label - The label for the checkbox.
426
+ * @property {Object} params.relation - Object describing the relationship between
427
+ * the clicked checkbox and another element.
428
+ * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
429
+ */
430
+ clickSwitch(params) {
431
+ return __awaiter(this, void 0, void 0, function* () {
432
+ let command = this.click().switch();
433
+ if (!params.relation) {
434
+ command = command.nearestTo().text(params.label);
435
+ }
436
+ else {
437
+ command = this.evaluateRelation(command, params.relation.type, params.label);
438
+ }
439
+ yield command.exec();
440
+ });
441
+ }
442
+ /**
443
+ * Types a given text into a textfield.
444
+ * Use a relation to specify how to find
445
+ * the textfield in relation to a specific label.
446
+ *
447
+ * **Examples:**
448
+ * ```typescript
449
+ * // Finds the textfield nearest to the label 'Email'
450
+ * await aui.typeIntoTextfield({textToWrite: 'Hello World', relation: {label: 'Email'}});
451
+ *
452
+ * // Finds the textfield above/below a label 'Password'
453
+ * await aui.typeIntoTextfield(
454
+ * {textToWrite: 'Hello World', relation: {type: 'above', label: 'Password'}}
455
+ * );
456
+ * await aui.typeIntoTextfield(
457
+ * {textToWrite: 'Hello World', relation: {type: 'below', label: 'Password'}}
458
+ * );
459
+ *
460
+ * // If there is no label but a placeholder, the label is contained in the textfield
461
+ * await aui.typeIntoTextfield(
462
+ * {textToWrite: 'Hello World', relation: {type: 'contains', label: 'Enter email'}}
463
+ * );
464
+ * ```
465
+ *
466
+ * @param {Object} params - Object containing required `textToWrite` property and
467
+ * optional `relation` property.
468
+ * @property {string} params.textToWrite - The text to be typed into the textfield.
469
+ * @property {Object} params.relation - Object describing the relationship between the
470
+ * textfield being interacted with and another element.
471
+ * @property {RelationsForConvenienceMethods} params.relation.type - The type of
472
+ * relation, optional.
473
+ * @property {string} params.relation.label - The label associated with the related
474
+ * element, optional.
475
+ */
476
+ typeIntoTextfield(params) {
477
+ return __awaiter(this, void 0, void 0, function* () {
478
+ let command = this.typeIn(params.textToWrite).textfield();
479
+ if (!params.relation.type) {
480
+ command = command.nearestTo().text(params.relation.label);
481
+ }
482
+ else {
483
+ command = this.evaluateRelation(command, params.relation.type, params.relation.label);
484
+ }
485
+ yield command.exec();
486
+ });
487
+ }
488
+ /**
489
+ * Click on a specific text.
490
+ * You can also use a RegEx or match the text exactly by specifyicing the specific flag.
491
+ * Use a relation to find the text in relation to a specific text.
492
+ *
493
+ * **Examples:**
494
+ * ```typescript
495
+ * // Click text that matches exactly
496
+ * await aui.clickText({text: 'askui', type: 'similar'})
497
+ *
498
+ * // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
499
+ * await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', type: 'regex'})
500
+ *
501
+ * // Click the text 'TERMINAL' that is left of the text 'Ports'
502
+ * await aui.clickText({
503
+ * text: 'TERMINAL',
504
+ * type: "exact",
505
+ * relation: { type: 'leftOf', text: 'PORTS' }
506
+ * })
507
+ * ```
508
+ * @param {Object} params - Object containing required `text` property and optional properties
509
+ * for regular expression matching and relation.
510
+ * @property {string} params.text - The text to be clicked.
511
+ * @property {string} params.type - Whether the text is matched using similarity,
512
+ * exact match or a regular expression.
513
+ * @property {Object} params.relation - Object describing the relationship between the
514
+ * clicked text and another element.
515
+ * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
516
+ * @property {string} params.relation.text - The label or text associated with the
517
+ * related element or state.
518
+ */
519
+ clickText(params) {
520
+ return __awaiter(this, void 0, void 0, function* () {
521
+ let command = this.click().text();
522
+ switch (params.type) {
523
+ case 'similar':
524
+ command = command.withText(params.text);
525
+ break;
526
+ case 'exact':
527
+ command = command.withExactText(params.text);
528
+ break;
529
+ case 'regex':
530
+ command = command.withTextRegex(params.text);
531
+ break;
532
+ default:
533
+ throw new ValidationError('"type" must be "similar", "exact" or "regex"');
534
+ }
535
+ if (params.relation) {
536
+ command = this.evaluateRelation(command, params.relation.type, params.relation.text);
537
+ }
538
+ yield command.exec();
539
+ });
540
+ }
346
541
  }
@@ -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
- * Configuration options for the askui UI Control Client
7
+ * Context object to provide additional information about the context of (test) automation.
7
8
  *
8
- * @param {string} uiControllerUrl - Default: http://127.0.0.1:6769
9
- * The adress of the askui UI Controller server.
10
- * @param {(number | undefined)} resize - Default: undefined
11
- * The resizing will be skipped if it's undefined.
12
- * The side length of the target image to resize to in px.
13
- * Your screenshot image will be resized with the original aspect ratio,
14
- * and the lengths image side will be equal to this number.
15
- * This can be used to reduce the inference time by reducing
16
- * the request size in case of a bad internet connection.
17
- * But it can cause a decrease in the prediction quality.
18
- * @param {string} inferenceServerUrl - Default: https://inference.askui.com`
19
- * Address of the askui Inference server.
20
- * @param {CredentialArgs} credentials - We need to provide credentials for
21
- * the authentication of the askui Inference Server.
22
- * You have three options: `DISABLED`, `ON_FAILURE`, `ALL`.
23
- * @param {ProxyAgentArgs} proxyAgents - To configure the proxy agents for http(s) requests.
24
- * @param {Reporter | Reporter[]} reporter - To configure the reporter(s)
25
- * to report on step runs/executions.
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
  }
@@ -182,7 +182,7 @@ export class CreateExampleProject {
182
182
  return __awaiter(this, void 0, void 0, function* () {
183
183
  const runCommand = promisify(exec);
184
184
  const frameworkDependencies = {
185
- 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',
185
+ 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',
186
186
  };
187
187
  yield runCommand(frameworkDependencies.jest);
188
188
  });
@@ -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,3 +1,4 @@
1
+ import { Context } from '@/execution/context';
1
2
  export interface AnalyticsInterface {
2
- getAnalyticsHeaders(): Promise<Record<string, string>>;
3
+ getAnalyticsHeaders(context: Context): Promise<Record<string, string>>;
3
4
  }
@@ -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
  }
@@ -14,12 +14,13 @@ export class Analytics {
14
14
  constructor() {
15
15
  this.userIdentifier = new UserIdentifier();
16
16
  }
17
- getAnalyticsHeaders() {
17
+ getAnalyticsHeaders(context) {
18
18
  return __awaiter(this, void 0, void 0, function* () {
19
19
  const userID = yield this.userIdentifier.userId();
20
20
  const headers = {
21
- 'askui-user-id': userID,
21
+ 'askui-is-ci': String(context.isCi),
22
22
  'askui-user-agent': `os:${os.platform()};arch:${os.arch()}`,
23
+ 'askui-user-id': userID,
23
24
  };
24
25
  const askuiInstalledAt = yield InstallationTimestamp.get();
25
26
  if (askuiInstalledAt) {
@@ -12,9 +12,10 @@
12
12
  },
13
13
  "plugins": [
14
14
  "import",
15
- "askui"
15
+ "@askui/askui"
16
16
  ],
17
17
  "rules": {
18
- "askui/no-missing-askui-exec": "error"
18
+ "@askui/askui/no-missing-exec": "error",
19
+ "@askui/askui/expect": "error"
19
20
  }
20
21
  }