askui 0.18.0 → 0.19.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.
Files changed (61) hide show
  1. package/dist/cjs/core/ai-element/ai-element-collection.d.ts +10 -0
  2. package/dist/cjs/core/ai-element/ai-element-collection.js +78 -0
  3. package/dist/cjs/core/ai-element/ai-element-error.d.ts +2 -0
  4. package/dist/cjs/core/ai-element/ai-element-error.js +6 -0
  5. package/dist/cjs/core/ai-element/ai-element.d.ts +27 -0
  6. package/dist/cjs/core/ai-element/ai-element.js +31 -0
  7. package/dist/cjs/core/model/custom-element-json.d.ts +32 -15
  8. package/dist/cjs/core/model/custom-element.d.ts +3 -2
  9. package/dist/cjs/core/model/custom-element.js +4 -2
  10. package/dist/cjs/core/reporting/step-reporter.js +15 -6
  11. package/dist/cjs/execution/dsl.d.ts +488 -113
  12. package/dist/cjs/execution/dsl.js +519 -113
  13. package/dist/cjs/execution/index.d.ts +1 -1
  14. package/dist/cjs/execution/index.js +11 -3
  15. package/dist/cjs/execution/inference-client.js +9 -4
  16. package/dist/cjs/execution/ui-control-client-dependency-builder.d.ts +1 -0
  17. package/dist/cjs/execution/ui-control-client-dependency-builder.js +6 -3
  18. package/dist/cjs/execution/ui-control-client.d.ts +101 -16
  19. package/dist/cjs/execution/ui-control-client.js +142 -52
  20. package/dist/cjs/execution/ui-controller-client-interface.d.ts +2 -0
  21. package/dist/cjs/execution/ui-controller-client.d.ts +1 -0
  22. package/dist/cjs/execution/ui-controller-client.js +11 -1
  23. package/dist/cjs/execution/ui-controller-not-connected-error.d.ts +4 -0
  24. package/dist/cjs/execution/ui-controller-not-connected-error.js +12 -0
  25. package/dist/cjs/main.d.ts +1 -1
  26. package/dist/cjs/main.js +12 -3
  27. package/dist/cjs/utils/analytics/analytics.d.ts +3 -1
  28. package/dist/cjs/utils/analytics/analytics.js +5 -0
  29. package/dist/cjs/utils/http/custom-errors/index.js +1 -1
  30. package/dist/cjs/utils/http/http-client-got.js +46 -20
  31. package/dist/esm/core/ai-element/ai-element-collection.d.ts +10 -0
  32. package/dist/esm/core/ai-element/ai-element-collection.js +71 -0
  33. package/dist/esm/core/ai-element/ai-element-error.d.ts +2 -0
  34. package/dist/esm/core/ai-element/ai-element-error.js +2 -0
  35. package/dist/esm/core/ai-element/ai-element.d.ts +27 -0
  36. package/dist/esm/core/ai-element/ai-element.js +28 -0
  37. package/dist/esm/core/model/custom-element-json.d.ts +32 -15
  38. package/dist/esm/core/model/custom-element.d.ts +3 -2
  39. package/dist/esm/core/model/custom-element.js +4 -2
  40. package/dist/esm/core/reporting/step-reporter.js +15 -6
  41. package/dist/esm/execution/dsl.d.ts +488 -113
  42. package/dist/esm/execution/dsl.js +519 -113
  43. package/dist/esm/execution/index.d.ts +1 -1
  44. package/dist/esm/execution/index.js +1 -1
  45. package/dist/esm/execution/inference-client.js +9 -4
  46. package/dist/esm/execution/ui-control-client-dependency-builder.d.ts +1 -0
  47. package/dist/esm/execution/ui-control-client-dependency-builder.js +6 -3
  48. package/dist/esm/execution/ui-control-client.d.ts +101 -16
  49. package/dist/esm/execution/ui-control-client.js +142 -49
  50. package/dist/esm/execution/ui-controller-client-interface.d.ts +2 -0
  51. package/dist/esm/execution/ui-controller-client.d.ts +1 -0
  52. package/dist/esm/execution/ui-controller-client.js +11 -1
  53. package/dist/esm/execution/ui-controller-not-connected-error.d.ts +4 -0
  54. package/dist/esm/execution/ui-controller-not-connected-error.js +8 -0
  55. package/dist/esm/main.d.ts +1 -1
  56. package/dist/esm/main.js +1 -1
  57. package/dist/esm/utils/analytics/analytics.d.ts +3 -1
  58. package/dist/esm/utils/analytics/analytics.js +5 -0
  59. package/dist/esm/utils/http/custom-errors/index.js +1 -1
  60. package/dist/esm/utils/http/http-client-got.js +46 -20
  61. package/package.json +1 -1
@@ -1 +1 @@
1
- export { UiControlClient, RelationsForConvenienceMethods } from './ui-control-client';
1
+ export * from './ui-control-client';
@@ -1,5 +1,13 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
2
12
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UiControlClient = void 0;
4
- var ui_control_client_1 = require("./ui-control-client");
5
- Object.defineProperty(exports, "UiControlClient", { enumerable: true, get: function () { return ui_control_client_1.UiControlClient; } });
13
+ __exportStar(require("./ui-control-client"), exports);
@@ -62,12 +62,17 @@ class InferenceClient {
62
62
  inference(customElements = [], image, instruction) {
63
63
  return __awaiter(this, void 0, void 0, function* () {
64
64
  const resizedImage = yield this.resizeIfNeeded(customElements, image);
65
- const response = yield this.httpClient.post(this.urls.inference, {
66
- customElements,
65
+ const response = yield this.httpClient.post(this.urls.inference, this.urls.inference.includes('v4-experimental') ? {
67
66
  image: resizedImage.base64Image,
68
67
  instruction,
69
- modelComposition: this.modelComposition,
70
- });
68
+ tasks: ['OCR'],
69
+ }
70
+ : {
71
+ customElements,
72
+ image: resizedImage.base64Image,
73
+ instruction,
74
+ modelComposition: this.modelComposition,
75
+ });
71
76
  InferenceClient.logMetaInformation(response);
72
77
  return ui_control_commands_1.InferenceResponse.fromJson(response.body, resizedImage.resizeRatio, image);
73
78
  });
@@ -8,6 +8,7 @@ export declare class UiControlClientDependencyBuilder {
8
8
  static build(clientArgs: ClientArgsWithDefaults): Promise<{
9
9
  executionRuntime: ExecutionRuntime;
10
10
  stepReporter: StepReporter;
11
+ workspaceId: string | undefined;
11
12
  }>;
12
13
  static getClientArgsWithDefaults(clientArgs: ClientArgs): Promise<ClientArgsWithDefaults>;
13
14
  }
@@ -36,29 +36,32 @@ class UiControlClientDependencyBuilder {
36
36
  var _a;
37
37
  return __awaiter(this, void 0, void 0, function* () {
38
38
  const httpClient = yield UiControlClientDependencyBuilder.buildHttpClient(clientArgs);
39
- return new inference_client_1.InferenceClient(clientArgs.inferenceServerUrl, httpClient, clientArgs.resize, (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId, clientArgs.modelComposition);
39
+ return new inference_client_1.InferenceClient(clientArgs.inferenceServerUrl, httpClient, clientArgs.resize, (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId, clientArgs.modelComposition, clientArgs.inferenceServerApiVersion);
40
40
  });
41
41
  }
42
42
  static buildUiControllerClient(clientArgs) {
43
43
  return new ui_controller_client_1.UiControllerClient(clientArgs.uiControllerUrl);
44
44
  }
45
45
  static build(clientArgs) {
46
+ var _a;
46
47
  return __awaiter(this, void 0, void 0, function* () {
47
48
  const uiControllerClient = UiControlClientDependencyBuilder.buildUiControllerClient(clientArgs);
48
49
  const inferenceClient = yield UiControlClientDependencyBuilder.buildInferenceClient(clientArgs);
49
50
  const stepReporter = new reporting_1.StepReporter(clientArgs.reporter);
51
+ const workspaceId = (_a = clientArgs.credentials) === null || _a === void 0 ? void 0 : _a.workspaceId;
50
52
  return {
51
53
  executionRuntime: new execution_runtime_1.ExecutionRuntime(uiControllerClient, inferenceClient, stepReporter),
52
54
  stepReporter,
55
+ workspaceId,
53
56
  };
54
57
  });
55
58
  }
56
59
  static getClientArgsWithDefaults(clientArgs) {
57
- var _a, _b, _c, _d, _e;
60
+ var _a, _b, _c, _d, _e, _f;
58
61
  return __awaiter(this, void 0, void 0, function* () {
59
62
  return Object.assign(Object.assign({}, clientArgs), { context: {
60
63
  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' });
64
+ }, credentials: (0, read_credentials_1.readCredentials)(clientArgs), inferenceServerApiVersion: (_c = clientArgs.inferenceServerApiVersion) !== null && _c !== void 0 ? _c : 'v3', inferenceServerUrl: (_d = clientArgs.inferenceServerUrl) !== null && _d !== void 0 ? _d : 'https://inference.askui.com', proxyAgents: (_e = clientArgs.proxyAgents) !== null && _e !== void 0 ? _e : (yield (0, proxy_builder_1.envProxyAgents)()), uiControllerUrl: (_f = clientArgs.uiControllerUrl) !== null && _f !== void 0 ? _f : 'http://127.0.0.1:6769' });
62
65
  });
63
66
  }
64
67
  }
@@ -1,12 +1,34 @@
1
- import { CustomElementJson } from '../core/model/custom-element-json';
2
- import { Exec, Executable, FluentFilters, ApiCommands, PC_AND_MODIFIER_KEY } from './dsl';
1
+ import { Exec, Executable, FluentFilters, ApiCommands, PC_AND_MODIFIER_KEY, CommandExecutorContext } from './dsl';
3
2
  import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
4
3
  import { Annotation } from '../core/annotation/annotation';
5
4
  import { AnnotationRequest } from '../core/model/annotation-result/annotation-interface';
6
5
  import { DetectedElement } from '../core/model/annotation-result/detected-element';
7
6
  import { ClientArgs } from './ui-controller-client-interface';
8
7
  export declare type RelationsForConvenienceMethods = 'nearestTo' | 'leftOf' | 'above' | 'rightOf' | 'below' | 'contains';
8
+ export declare type TextMatchingOption = 'similar' | 'exact' | 'regex';
9
+ export declare type ElementExistsQueryType = 'otherElement' | 'switch' | 'element' | 'container' | 'checkbox' | 'element' | 'button' | 'table' | 'text' | 'icon' | 'image' | 'textfield';
10
+ export interface ElementExistsQueryText {
11
+ value: string;
12
+ matching?: TextMatchingOption;
13
+ }
14
+ export interface ElementExistsQueryRelation {
15
+ type: RelationsForConvenienceMethods;
16
+ text: string;
17
+ }
18
+ export interface ElementExistsQuery {
19
+ type: keyof Pick<FluentFilters, ElementExistsQueryType>;
20
+ text?: ElementExistsQueryText;
21
+ relation?: ElementExistsQueryRelation;
22
+ }
23
+ export interface ExpectExistenceElement extends ElementExistsQuery {
24
+ exists: boolean;
25
+ }
26
+ export interface ExpectAllExistResult {
27
+ allExist: boolean;
28
+ elements: ExpectExistenceElement[];
29
+ }
9
30
  export declare class UiControlClient extends ApiCommands {
31
+ private workspaceId;
10
32
  private executionRuntime;
11
33
  private stepReporter;
12
34
  private constructor();
@@ -34,8 +56,9 @@ export declare class UiControlClient extends ApiCommands {
34
56
  annotateInteractively(): Promise<void>;
35
57
  private escapeSeparatorString;
36
58
  private buildInstruction;
37
- fluentCommandExecutor(instructionString: string, customElementJson?: CustomElementJson[]): Promise<void>;
38
- getterExecutor(instruction: string, customElementJson?: CustomElementJson[]): Promise<DetectedElement[]>;
59
+ private getAIElementsByNames;
60
+ fluentCommandExecutor(instructionString: string, context?: CommandExecutorContext): Promise<void>;
61
+ getterExecutor(instruction: string, context?: CommandExecutorContext): Promise<DetectedElement[]>;
39
62
  private secretText;
40
63
  private getAndResetSecretText;
41
64
  /**
@@ -190,8 +213,8 @@ export declare class UiControlClient extends ApiCommands {
190
213
  * @param {Object} params - Object containing required `label` property and
191
214
  * optional `relation` property.
192
215
  * @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.
216
+ * @property {Object} [params.relation] - Object describing the relationship between
217
+ * the clicked checkbox and another element.
195
218
  * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
196
219
  */
197
220
  clickCheckbox(params: {
@@ -213,7 +236,7 @@ export declare class UiControlClient extends ApiCommands {
213
236
  * @param {Object} params - Object containing required `label` property and
214
237
  * optional `relation` property.
215
238
  * @property {string} params.label - The label for the checkbox.
216
- * @property {Object} params.relation - Object describing the relationship between
239
+ * @property {Object} [params.relation] - Object describing the relationship between
217
240
  * the clicked checkbox and another element.
218
241
  * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
219
242
  */
@@ -266,41 +289,103 @@ export declare class UiControlClient extends ApiCommands {
266
289
  }): Promise<void>;
267
290
  /**
268
291
  * Click on a specific text.
269
- * You can also use a RegEx or match the text exactly by specifyicing the specific flag.
292
+ * You can also use a RegEx or match the text exactly by specifying the specific flag.
270
293
  * Use a relation to find the text in relation to a specific text.
271
294
  *
272
295
  * **Examples:**
273
296
  * ```typescript
274
297
  * // Click text that matches exactly
275
- * await aui.clickText({text: 'askui', type: 'similar'})
298
+ * await aui.clickText({text: 'askui', matching: 'similar'})
276
299
  *
277
300
  * // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
278
- * await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', type: 'regex'})
301
+ * await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', matching: 'regex'})
279
302
  *
280
303
  * // Click the text 'TERMINAL' that is left of the text 'Ports'
281
304
  * await aui.clickText({
282
305
  * text: 'TERMINAL',
283
- * type: "exact",
306
+ * matching: "exact",
284
307
  * relation: { type: 'leftOf', text: 'PORTS' }
285
308
  * })
286
309
  * ```
310
+ *
287
311
  * @param {Object} params - Object containing required `text` property and optional properties
288
312
  * for regular expression matching and relation.
289
313
  * @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.
314
+ * @property {string} params.matching - Whether the text is matched using similarity,
315
+ * exact match or a regular expression.
316
+ * @property {Object} [params.relation] - Object describing the relationship between the
317
+ * clicked text and another element.
294
318
  * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
295
319
  * @property {string} params.relation.text - The label or text associated with the
296
320
  * related element or state.
297
321
  */
298
322
  clickText(params: {
299
323
  text: string;
300
- type: 'similar' | 'exact' | 'regex';
324
+ matching: TextMatchingOption;
301
325
  relation?: {
302
326
  type: RelationsForConvenienceMethods;
303
327
  text: string;
304
328
  };
305
329
  }): Promise<void>;
330
+ private evaluateMatchingProperty;
331
+ /**
332
+ * Check if one or multiple elements are detected.
333
+ *
334
+ * **Examples:**
335
+ * ```typescript
336
+ * await aui.expectAllExist([
337
+ * {
338
+ * type: 'text',
339
+ * text: {
340
+ * value: 'Switch to Dark',
341
+ * matching: 'similar'
342
+ * }
343
+ * },
344
+ * ]);
345
+ *
346
+ * // Check for existence of multiple elements
347
+ * await aui.expectAllExist([
348
+ * {
349
+ * type: 'textfield',
350
+ * relation: {
351
+ * type: 'rightOf',
352
+ * text: 'Email:'
353
+ * }
354
+ * },
355
+ * {
356
+ * type: 'element',
357
+ * text: {
358
+ * value: 'Switch to Dark'
359
+ * }
360
+ * },
361
+ * ]);
362
+ *
363
+ * // Validate existence
364
+ * const exists = await aui.expectAllExist([...]);
365
+ * exists.allExist // true when every element exists
366
+ *
367
+ * // Check which elements do not exist
368
+ * // with the elements property
369
+ * const nonExistentElements = exists.elements.filter((e) => e.exists===false)
370
+ * ```
371
+ *
372
+ * @param {ElementExistsQuery[]} query - Objects containing the required property
373
+ * 'type' and the optional properties
374
+ * 'text' and 'relation'.
375
+ * @property {string} query.type - The type of the element: 'otherElement' | 'switch' |
376
+ * 'element' | 'container' | 'checkbox' | 'element' |
377
+ * 'button' | 'table' | 'text' | 'icon' | 'image' | 'textfield'
378
+ * @property {Object} [query.text] - Object containing value and matching strategy.
379
+ * @property {string} query.text.value - The text to match for.
380
+ * @property {string} [query.text.matching] - Whether the text is matched using similarity,
381
+ * exact match or a regular expression.
382
+ * @property {Object} [query.relation] - Object describing the relationship between the
383
+ * clicked text and another element.
384
+ * @property {RelationsForConvenienceMethods} query.relation.type - The type of relation.
385
+ * @property {string} query.relation.text - The label or text associated with the
386
+ * related element or state.
387
+ * @returns {ExpectAllExistResult.allExist} - If every element exists.
388
+ * @returns {ExpectAllExistResult.elements} - ExpectExistenceElement[].
389
+ */
390
+ expectAllExist(query: ElementExistsQuery[]): Promise<ExpectAllExistResult>;
306
391
  }
@@ -8,20 +8,19 @@ 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
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
12
  exports.UiControlClient = void 0;
16
- const ValidationError_1 = __importDefault(require("yup/lib/ValidationError"));
13
+ const yup_1 = require("yup");
17
14
  const custom_element_1 = require("../core/model/custom-element");
18
15
  const dsl_1 = require("./dsl");
19
16
  const annotation_writer_1 = require("../core/annotation/annotation-writer");
20
17
  const logger_1 = require("../lib/logger");
21
18
  const ui_control_client_dependency_builder_1 = require("./ui-control-client-dependency-builder");
19
+ const ai_element_collection_1 = require("../core/ai-element/ai-element-collection");
22
20
  class UiControlClient extends dsl_1.ApiCommands {
23
- constructor(executionRuntime, stepReporter) {
21
+ constructor(workspaceId, executionRuntime, stepReporter) {
24
22
  super();
23
+ this.workspaceId = workspaceId;
25
24
  this.executionRuntime = executionRuntime;
26
25
  this.stepReporter = stepReporter;
27
26
  this.secretText = undefined;
@@ -30,8 +29,8 @@ class UiControlClient extends dsl_1.ApiCommands {
30
29
  return __awaiter(this, void 0, void 0, function* () {
31
30
  const builder = ui_control_client_dependency_builder_1.UiControlClientDependencyBuilder;
32
31
  const clientArgsWithDefaults = yield builder.getClientArgsWithDefaults(clientArgs);
33
- const { executionRuntime, stepReporter } = yield builder.build(clientArgsWithDefaults);
34
- return new UiControlClient(executionRuntime, stepReporter);
32
+ const { workspaceId, executionRuntime, stepReporter, } = yield builder.build(clientArgsWithDefaults);
33
+ return new UiControlClient(workspaceId, executionRuntime, stepReporter);
35
34
  });
36
35
  }
37
36
  /**
@@ -125,9 +124,20 @@ class UiControlClient extends dsl_1.ApiCommands {
125
124
  };
126
125
  });
127
126
  }
128
- fluentCommandExecutor(instructionString, customElementJson = []) {
127
+ getAIElementsByNames(names) {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ // eslint-disable-next-line max-len
130
+ const workspaceAIElementCollection = yield ai_element_collection_1.AIElementCollection.collectForWorkspaceId(this.workspaceId);
131
+ return workspaceAIElementCollection.getByNames(names);
132
+ });
133
+ }
134
+ fluentCommandExecutor(instructionString, context = { customElementsJson: [], aiElementNames: [] }) {
129
135
  return __awaiter(this, void 0, void 0, function* () {
130
- const instruction = yield this.buildInstruction(instructionString, customElementJson);
136
+ const aiElements = yield this.getAIElementsByNames(context.aiElementNames);
137
+ const instruction = yield this.buildInstruction(instructionString, [
138
+ ...context.customElementsJson,
139
+ ...aiElements,
140
+ ]);
131
141
  logger_1.logger.debug(instruction);
132
142
  try {
133
143
  yield this.stepReporter.resetStep(instruction);
@@ -141,12 +151,16 @@ class UiControlClient extends dsl_1.ApiCommands {
141
151
  }
142
152
  });
143
153
  }
144
- getterExecutor(instruction, customElementJson = []) {
154
+ getterExecutor(instruction, context = { customElementsJson: [], aiElementNames: [] }) {
145
155
  return __awaiter(this, void 0, void 0, function* () {
146
- const customElements = yield custom_element_1.CustomElement.fromJsonListWithImagePathOrImage(customElementJson);
156
+ const aiElements = yield this.getAIElementsByNames(context.aiElementNames);
157
+ const customElements = yield custom_element_1.CustomElement.fromJsonListWithImagePathOrImage(context.customElementsJson);
147
158
  const stringWithoutSeparators = this.escapeSeparatorString(instruction);
148
159
  logger_1.logger.debug(stringWithoutSeparators);
149
- return this.executionRuntime.getDetectedElements(instruction, customElements);
160
+ return this.executionRuntime.getDetectedElements(instruction, [
161
+ ...customElements,
162
+ ...aiElements,
163
+ ]);
150
164
  });
151
165
  }
152
166
  getAndResetSecretText() {
@@ -331,30 +345,22 @@ class UiControlClient extends dsl_1.ApiCommands {
331
345
  }
332
346
  // eslint-disable-next-line class-methods-use-this
333
347
  evaluateRelation(command, relation, text) {
334
- let commando = command;
335
348
  switch (relation) {
336
- case 'nearestTo':
337
- commando = command.nearestTo().text(text);
338
- break;
339
349
  case 'leftOf':
340
- commando = command.leftOf().text(text);
341
- break;
350
+ return command.leftOf().text(text);
342
351
  case 'above':
343
- commando = command.above().text(text);
344
- break;
352
+ return command.above().text(text);
345
353
  case 'rightOf':
346
- commando = command.rightOf().text(text);
347
- break;
354
+ return command.rightOf().text(text);
348
355
  case 'below':
349
- commando = command.below().text(text);
350
- break;
356
+ return command.below().text(text);
351
357
  case 'contains':
352
- commando = command.contains().text(text);
353
- break;
358
+ return command.contains().text(text);
359
+ case 'nearestTo':
360
+ return command.nearestTo().text(text);
354
361
  default:
355
- throw new ValidationError_1.default('No valid Relation.Type was passed.');
362
+ throw new yup_1.ValidationError(`'relation' has to be 'nearestTo', 'leftOf', 'above', 'rightOf', 'below' or 'contains' but was '${relation}'`);
356
363
  }
357
- return commando;
358
364
  }
359
365
  /**
360
366
  * Click a button with a specific label.
@@ -400,8 +406,8 @@ class UiControlClient extends dsl_1.ApiCommands {
400
406
  * @param {Object} params - Object containing required `label` property and
401
407
  * optional `relation` property.
402
408
  * @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.
409
+ * @property {Object} [params.relation] - Object describing the relationship between
410
+ * the clicked checkbox and another element.
405
411
  * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
406
412
  */
407
413
  clickCheckbox(params) {
@@ -429,7 +435,7 @@ class UiControlClient extends dsl_1.ApiCommands {
429
435
  * @param {Object} params - Object containing required `label` property and
430
436
  * optional `relation` property.
431
437
  * @property {string} params.label - The label for the checkbox.
432
- * @property {Object} params.relation - Object describing the relationship between
438
+ * @property {Object} [params.relation] - Object describing the relationship between
433
439
  * the clicked checkbox and another element.
434
440
  * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
435
441
  */
@@ -493,31 +499,32 @@ class UiControlClient extends dsl_1.ApiCommands {
493
499
  }
494
500
  /**
495
501
  * Click on a specific text.
496
- * You can also use a RegEx or match the text exactly by specifyicing the specific flag.
502
+ * You can also use a RegEx or match the text exactly by specifying the specific flag.
497
503
  * Use a relation to find the text in relation to a specific text.
498
504
  *
499
505
  * **Examples:**
500
506
  * ```typescript
501
507
  * // Click text that matches exactly
502
- * await aui.clickText({text: 'askui', type: 'similar'})
508
+ * await aui.clickText({text: 'askui', matching: 'similar'})
503
509
  *
504
510
  * // Click text that contains 'pie' or 'cake' or 'Pie' or 'Cake'
505
- * await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', type: 'regex'})
511
+ * await aui.clickText({text: '.*([Pp]ie|[Cc]ake).*', matching: 'regex'})
506
512
  *
507
513
  * // Click the text 'TERMINAL' that is left of the text 'Ports'
508
514
  * await aui.clickText({
509
515
  * text: 'TERMINAL',
510
- * type: "exact",
516
+ * matching: "exact",
511
517
  * relation: { type: 'leftOf', text: 'PORTS' }
512
518
  * })
513
519
  * ```
520
+ *
514
521
  * @param {Object} params - Object containing required `text` property and optional properties
515
522
  * for regular expression matching and relation.
516
523
  * @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.
524
+ * @property {string} params.matching - Whether the text is matched using similarity,
525
+ * exact match or a regular expression.
526
+ * @property {Object} [params.relation] - Object describing the relationship between the
527
+ * clicked text and another element.
521
528
  * @property {RelationsForConvenienceMethods} params.relation.type - The type of relation.
522
529
  * @property {string} params.relation.text - The label or text associated with the
523
530
  * related element or state.
@@ -525,24 +532,107 @@ class UiControlClient extends dsl_1.ApiCommands {
525
532
  clickText(params) {
526
533
  return __awaiter(this, void 0, void 0, function* () {
527
534
  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
- }
535
+ command = this.evaluateMatchingProperty(command, { value: params.text, matching: params.matching });
541
536
  if (params.relation) {
542
537
  command = this.evaluateRelation(command, params.relation.type, params.relation.text);
543
538
  }
544
539
  yield command.exec();
545
540
  });
546
541
  }
542
+ // eslint-disable-next-line class-methods-use-this
543
+ evaluateMatchingProperty(command, text) {
544
+ var _a;
545
+ switch ((_a = text.matching) !== null && _a !== void 0 ? _a : 'similar') {
546
+ case 'exact':
547
+ return command.withExactText(text.value);
548
+ case 'regex':
549
+ return command.withTextRegex(text.value);
550
+ case 'similar':
551
+ return command.withText(text.value);
552
+ default:
553
+ throw new yup_1.ValidationError(`'text.matching' property has to be 'similar', 'exact' or 'regex' but was '${text.matching}'`);
554
+ }
555
+ }
556
+ /**
557
+ * Check if one or multiple elements are detected.
558
+ *
559
+ * **Examples:**
560
+ * ```typescript
561
+ * await aui.expectAllExist([
562
+ * {
563
+ * type: 'text',
564
+ * text: {
565
+ * value: 'Switch to Dark',
566
+ * matching: 'similar'
567
+ * }
568
+ * },
569
+ * ]);
570
+ *
571
+ * // Check for existence of multiple elements
572
+ * await aui.expectAllExist([
573
+ * {
574
+ * type: 'textfield',
575
+ * relation: {
576
+ * type: 'rightOf',
577
+ * text: 'Email:'
578
+ * }
579
+ * },
580
+ * {
581
+ * type: 'element',
582
+ * text: {
583
+ * value: 'Switch to Dark'
584
+ * }
585
+ * },
586
+ * ]);
587
+ *
588
+ * // Validate existence
589
+ * const exists = await aui.expectAllExist([...]);
590
+ * exists.allExist // true when every element exists
591
+ *
592
+ * // Check which elements do not exist
593
+ * // with the elements property
594
+ * const nonExistentElements = exists.elements.filter((e) => e.exists===false)
595
+ * ```
596
+ *
597
+ * @param {ElementExistsQuery[]} query - Objects containing the required property
598
+ * 'type' and the optional properties
599
+ * 'text' and 'relation'.
600
+ * @property {string} query.type - The type of the element: 'otherElement' | 'switch' |
601
+ * 'element' | 'container' | 'checkbox' | 'element' |
602
+ * 'button' | 'table' | 'text' | 'icon' | 'image' | 'textfield'
603
+ * @property {Object} [query.text] - Object containing value and matching strategy.
604
+ * @property {string} query.text.value - The text to match for.
605
+ * @property {string} [query.text.matching] - Whether the text is matched using similarity,
606
+ * exact match or a regular expression.
607
+ * @property {Object} [query.relation] - Object describing the relationship between the
608
+ * clicked text and another element.
609
+ * @property {RelationsForConvenienceMethods} query.relation.type - The type of relation.
610
+ * @property {string} query.relation.text - The label or text associated with the
611
+ * related element or state.
612
+ * @returns {ExpectAllExistResult.allExist} - If every element exists.
613
+ * @returns {ExpectAllExistResult.elements} - ExpectExistenceElement[].
614
+ */
615
+ expectAllExist(query) {
616
+ return __awaiter(this, void 0, void 0, function* () {
617
+ const elements = yield query.reduce((accumulatorPromise, subquery) => __awaiter(this, void 0, void 0, function* () {
618
+ const acc = yield accumulatorPromise;
619
+ const command = this.get()[subquery.type]();
620
+ let finalCommand = subquery.text !== undefined
621
+ ? this.evaluateMatchingProperty(command, subquery.text)
622
+ : command;
623
+ if (subquery.relation) {
624
+ finalCommand = this.evaluateRelation(finalCommand, subquery.relation.type, subquery.relation.text);
625
+ }
626
+ return [
627
+ ...acc,
628
+ Object.assign(Object.assign({}, subquery), { exists: (yield finalCommand.exec()).length > 0 }),
629
+ ];
630
+ }), Promise.resolve([]));
631
+ return {
632
+ elements,
633
+ allExist: elements.every((el) => el.exists),
634
+ };
635
+ });
636
+ }
547
637
  }
548
638
  exports.UiControlClient = UiControlClient;
@@ -53,9 +53,11 @@ export interface ClientArgs {
53
53
  readonly modelComposition?: ModelCompositionBranch[];
54
54
  readonly reporter?: Reporter | Reporter[] | undefined;
55
55
  readonly context?: ContextArgs | undefined;
56
+ readonly inferenceServerApiVersion?: string;
56
57
  }
57
58
  export interface ClientArgsWithDefaults extends ClientArgs {
58
59
  readonly uiControllerUrl: string;
59
60
  readonly inferenceServerUrl: string;
60
61
  readonly context: Context;
62
+ readonly inferenceServerApiVersion: string;
61
63
  }
@@ -18,6 +18,7 @@ export declare class UiControllerClient {
18
18
  private onMessage;
19
19
  connect(): Promise<UiControllerClientConnectionState>;
20
20
  disconnect(): void;
21
+ private checkConnection;
21
22
  private sendAndReceive;
22
23
  private send;
23
24
  requestScreenshot(): Promise<CaptureScreenshotResponse>;
@@ -10,6 +10,7 @@ const logger_1 = require("../lib/logger");
10
10
  const ui_controller_client_connection_state_1 = require("./ui-controller-client-connection-state");
11
11
  const read_recording_response_stream_handler_1 = require("./read-recording-response-stream-handler");
12
12
  const ui_controller_client_error_1 = require("./ui-controller-client-error");
13
+ const ui_controller_not_connected_error_1 = require("./ui-controller-not-connected-error");
13
14
  class UiControllerClient {
14
15
  constructor(url) {
15
16
  this.url = url;
@@ -40,7 +41,9 @@ class UiControllerClient {
40
41
  return new Promise((resolve, reject) => {
41
42
  try {
42
43
  this.ws = new ws_1.default(this.url);
43
- this.ws.on('message', (data) => { this.onMessage(data); });
44
+ this.ws.on('message', (data) => {
45
+ this.onMessage(data);
46
+ });
44
47
  this.ws.on('open', () => {
45
48
  this.connectionState = ui_controller_client_connection_state_1.UiControllerClientConnectionState.CONNECTED;
46
49
  resolve(this.connectionState);
@@ -61,7 +64,13 @@ class UiControllerClient {
61
64
  var _a;
62
65
  (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
63
66
  }
67
+ checkConnection() {
68
+ if (this.connectionState !== ui_controller_client_connection_state_1.UiControllerClientConnectionState.CONNECTED) {
69
+ throw new ui_controller_not_connected_error_1.UiControllerNotConnectedError();
70
+ }
71
+ }
64
72
  sendAndReceive(msg, requestTimeout = UiControllerClient.REQUEST_TIMEOUT_IN_MS) {
73
+ this.checkConnection();
65
74
  return new Promise((resolve, reject) => {
66
75
  this.currentResolve = resolve;
67
76
  this.currentReject = reject;
@@ -75,6 +84,7 @@ class UiControllerClient {
75
84
  });
76
85
  }
77
86
  send(msg, _requestTimeout = UiControllerClient.REQUEST_TIMEOUT_IN_MS) {
87
+ this.checkConnection();
78
88
  if (!this.currentReject || !this.currentResolve) {
79
89
  throw new ui_controller_client_error_1.UiControllerClientError('Request is not finished! It is not possible to have multiple requests at the same time.');
80
90
  }
@@ -0,0 +1,4 @@
1
+ import { UiControllerClientError } from './ui-controller-client-error';
2
+ export declare class UiControllerNotConnectedError extends UiControllerClientError {
3
+ constructor();
4
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UiControllerNotConnectedError = void 0;
4
+ const ui_controller_client_error_1 = require("./ui-controller-client-error");
5
+ class UiControllerNotConnectedError extends ui_controller_client_error_1.UiControllerClientError {
6
+ constructor() {
7
+ super('UI Controller is not connected. Did you call `UiControlClient.connect()`'
8
+ + ' before trying to interact with the UI Controller / OS?');
9
+ this.name = 'UiControllerNotConnectedError';
10
+ }
11
+ }
12
+ exports.UiControllerNotConnectedError = UiControllerNotConnectedError;