askui 0.4.0 → 0.5.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.
@@ -794,6 +794,120 @@ export class FluentFilters extends FluentBase {
794
794
  }
795
795
  // Relations
796
796
  export class FluentFiltersOrRelations extends FluentFilters {
797
+ /**
798
+ * Logic or operator
799
+ *
800
+ * **Examples:**
801
+ * ```text
802
+ * scene 1
803
+ * -------------- ---------------
804
+ * | button | | icon |
805
+ * -------------- ---------------
806
+ *
807
+ * scene 2
808
+ * -------------- ---------------
809
+ * | button | | text |
810
+ * -------------- ---------------
811
+ *
812
+ * ```
813
+ * In case, that your reference element can have multiple values, in the following example, the element right of the button can be either icon or text.
814
+ * You can use **the `or()` relation**, so your teststep is valid for both scenes
815
+ * ```typescript
816
+ * const button = await aui.get().button().rightOf().icon().or().text().exec();
817
+ * console.log(button);
818
+ * ```
819
+ * Returns the same button for both cases
820
+ * ```text
821
+ * console output: [
822
+ * DetectedElement {
823
+ * name: 'BUTTON',
824
+ * text: 'button',
825
+ * colors: [ 'red', 'black', 'red' ],
826
+ * bndbox: BoundingBox {
827
+ * xmin: 900,
828
+ * ymin: 910,
829
+ * xmax: 920,
830
+ * ymax: 930
831
+ * }
832
+ * }
833
+ * ]
834
+ * ```
835
+ *
836
+ * @return {FluentFilters}
837
+ */
838
+ or() {
839
+ this._textStr = 'or';
840
+ return new FluentFilters(this);
841
+ }
842
+ /**
843
+ * Logic and operator
844
+ *
845
+ * **Examples:**
846
+ * ```text
847
+ * example scene:
848
+ * -------------------------- --------------------------
849
+ * | icon user colored black | | icon user colored red |
850
+ * -------------------------- --------------------------
851
+ * ```
852
+ * ```typescript
853
+ * const icons = await aui.get().icon().withText('user').exec();
854
+ * console.log(icons);
855
+ * ```
856
+ * Using only the filter withText, the get command will return both icons because they share the same text
857
+ * ```text
858
+ * console output: [
859
+ * DetectedElement {
860
+ * name: 'ICON',
861
+ * text: 'user',
862
+ * colors: [ 'black', 'black', 'black' ],
863
+ * bndbox: BoundingBox {
864
+ * xmin: 1000,
865
+ * ymin: 1010,
866
+ * xmax: 1020,
867
+ * ymax: 1030
868
+ * }
869
+ * },
870
+ * DetectedElement {
871
+ * name: 'ICON',
872
+ * text: 'user',
873
+ * colors: [ 'red', 'red', 'red' ],
874
+ * bndbox: BoundingBox {
875
+ * xmin: 900,
876
+ * ymin: 910,
877
+ * xmax: 920,
878
+ * ymax: 930
879
+ * }
880
+ * }
881
+ * ]
882
+ * ```
883
+ * You can combine filters with **the `and()` relation** and specify exactly which icon you want
884
+ * ```typescript
885
+ * const icons = await aui.get().icon().withText('user').and().colored('red').exec()
886
+ * console.log(icons)
887
+ * ```
888
+ * The get command returns only the red icon although both icons have the same text
889
+ * ```text
890
+ * console output: [
891
+ * DetectedElement {
892
+ * name: 'ICON',
893
+ * text: 'user',
894
+ * colors: [ 'red', 'red', 'red' ],
895
+ * bndbox: BoundingBox {
896
+ * xmin: 900,
897
+ * ymin: 910,
898
+ * xmax: 920,
899
+ * ymax: 930
900
+ * }
901
+ * }
902
+ * ]
903
+ * ```
904
+ *
905
+ * @return {FluentFilters}
906
+ */
907
+ and() {
908
+ this._textStr = 'and';
909
+ return new FluentFilters(this);
910
+ }
797
911
  /**
798
912
  * Filters for an element inside another element.
799
913
  *
@@ -1704,6 +1818,120 @@ export class FluentFiltersCondition extends FluentBase {
1704
1818
  }
1705
1819
  // Relations
1706
1820
  export class FluentFiltersOrRelationsCondition extends FluentFiltersCondition {
1821
+ /**
1822
+ * Logic or operator
1823
+ *
1824
+ * **Examples:**
1825
+ * ```text
1826
+ * scene 1
1827
+ * -------------- ---------------
1828
+ * | button | | icon |
1829
+ * -------------- ---------------
1830
+ *
1831
+ * scene 2
1832
+ * -------------- ---------------
1833
+ * | button | | text |
1834
+ * -------------- ---------------
1835
+ *
1836
+ * ```
1837
+ * In case, that your reference element can have multiple values, in the following example, the element right of the button can be either icon or text.
1838
+ * You can use **the `or()` relation**, so your teststep is valid for both scenes
1839
+ * ```typescript
1840
+ * const button = await aui.get().button().rightOf().icon().or().text().exec();
1841
+ * console.log(button);
1842
+ * ```
1843
+ * Returns the same button for both cases
1844
+ * ```text
1845
+ * console output: [
1846
+ * DetectedElement {
1847
+ * name: 'BUTTON',
1848
+ * text: 'button',
1849
+ * colors: [ 'red', 'black', 'red' ],
1850
+ * bndbox: BoundingBox {
1851
+ * xmin: 900,
1852
+ * ymin: 910,
1853
+ * xmax: 920,
1854
+ * ymax: 930
1855
+ * }
1856
+ * }
1857
+ * ]
1858
+ * ```
1859
+ *
1860
+ * @return {FluentFiltersCondition}
1861
+ */
1862
+ or() {
1863
+ this._textStr = 'or';
1864
+ return new FluentFiltersCondition(this);
1865
+ }
1866
+ /**
1867
+ * Logic and operator
1868
+ *
1869
+ * **Examples:**
1870
+ * ```text
1871
+ * example scene:
1872
+ * -------------------------- --------------------------
1873
+ * | icon user colored black | | icon user colored red |
1874
+ * -------------------------- --------------------------
1875
+ * ```
1876
+ * ```typescript
1877
+ * const icons = await aui.get().icon().withText('user').exec();
1878
+ * console.log(icons);
1879
+ * ```
1880
+ * Using only the filter withText, the get command will return both icons because they share the same text
1881
+ * ```text
1882
+ * console output: [
1883
+ * DetectedElement {
1884
+ * name: 'ICON',
1885
+ * text: 'user',
1886
+ * colors: [ 'black', 'black', 'black' ],
1887
+ * bndbox: BoundingBox {
1888
+ * xmin: 1000,
1889
+ * ymin: 1010,
1890
+ * xmax: 1020,
1891
+ * ymax: 1030
1892
+ * }
1893
+ * },
1894
+ * DetectedElement {
1895
+ * name: 'ICON',
1896
+ * text: 'user',
1897
+ * colors: [ 'red', 'red', 'red' ],
1898
+ * bndbox: BoundingBox {
1899
+ * xmin: 900,
1900
+ * ymin: 910,
1901
+ * xmax: 920,
1902
+ * ymax: 930
1903
+ * }
1904
+ * }
1905
+ * ]
1906
+ * ```
1907
+ * You can combine filters with **the `and()` relation** and specify exactly which icon you want
1908
+ * ```typescript
1909
+ * const icons = await aui.get().icon().withText('user').and().colored('red').exec()
1910
+ * console.log(icons)
1911
+ * ```
1912
+ * The get command returns only the red icon although both icons have the same text
1913
+ * ```text
1914
+ * console output: [
1915
+ * DetectedElement {
1916
+ * name: 'ICON',
1917
+ * text: 'user',
1918
+ * colors: [ 'red', 'red', 'red' ],
1919
+ * bndbox: BoundingBox {
1920
+ * xmin: 900,
1921
+ * ymin: 910,
1922
+ * xmax: 920,
1923
+ * ymax: 930
1924
+ * }
1925
+ * }
1926
+ * ]
1927
+ * ```
1928
+ *
1929
+ * @return {FluentFiltersCondition}
1930
+ */
1931
+ and() {
1932
+ this._textStr = 'and';
1933
+ return new FluentFiltersCondition(this);
1934
+ }
1707
1935
  /**
1708
1936
  * Filters for an element inside another element.
1709
1937
  *
@@ -2922,6 +3150,120 @@ export class FluentFiltersGetter extends FluentBase {
2922
3150
  }
2923
3151
  // Relations
2924
3152
  export class FluentFiltersOrRelationsGetter extends FluentFiltersGetter {
3153
+ /**
3154
+ * Logic or operator
3155
+ *
3156
+ * **Examples:**
3157
+ * ```text
3158
+ * scene 1
3159
+ * -------------- ---------------
3160
+ * | button | | icon |
3161
+ * -------------- ---------------
3162
+ *
3163
+ * scene 2
3164
+ * -------------- ---------------
3165
+ * | button | | text |
3166
+ * -------------- ---------------
3167
+ *
3168
+ * ```
3169
+ * In case, that your reference element can have multiple values, in the following example, the element right of the button can be either icon or text.
3170
+ * You can use **the `or()` relation**, so your teststep is valid for both scenes
3171
+ * ```typescript
3172
+ * const button = await aui.get().button().rightOf().icon().or().text().exec();
3173
+ * console.log(button);
3174
+ * ```
3175
+ * Returns the same button for both cases
3176
+ * ```text
3177
+ * console output: [
3178
+ * DetectedElement {
3179
+ * name: 'BUTTON',
3180
+ * text: 'button',
3181
+ * colors: [ 'red', 'black', 'red' ],
3182
+ * bndbox: BoundingBox {
3183
+ * xmin: 900,
3184
+ * ymin: 910,
3185
+ * xmax: 920,
3186
+ * ymax: 930
3187
+ * }
3188
+ * }
3189
+ * ]
3190
+ * ```
3191
+ *
3192
+ * @return {FluentFiltersGetter}
3193
+ */
3194
+ or() {
3195
+ this._textStr = 'or';
3196
+ return new FluentFiltersGetter(this);
3197
+ }
3198
+ /**
3199
+ * Logic and operator
3200
+ *
3201
+ * **Examples:**
3202
+ * ```text
3203
+ * example scene:
3204
+ * -------------------------- --------------------------
3205
+ * | icon user colored black | | icon user colored red |
3206
+ * -------------------------- --------------------------
3207
+ * ```
3208
+ * ```typescript
3209
+ * const icons = await aui.get().icon().withText('user').exec();
3210
+ * console.log(icons);
3211
+ * ```
3212
+ * Using only the filter withText, the get command will return both icons because they share the same text
3213
+ * ```text
3214
+ * console output: [
3215
+ * DetectedElement {
3216
+ * name: 'ICON',
3217
+ * text: 'user',
3218
+ * colors: [ 'black', 'black', 'black' ],
3219
+ * bndbox: BoundingBox {
3220
+ * xmin: 1000,
3221
+ * ymin: 1010,
3222
+ * xmax: 1020,
3223
+ * ymax: 1030
3224
+ * }
3225
+ * },
3226
+ * DetectedElement {
3227
+ * name: 'ICON',
3228
+ * text: 'user',
3229
+ * colors: [ 'red', 'red', 'red' ],
3230
+ * bndbox: BoundingBox {
3231
+ * xmin: 900,
3232
+ * ymin: 910,
3233
+ * xmax: 920,
3234
+ * ymax: 930
3235
+ * }
3236
+ * }
3237
+ * ]
3238
+ * ```
3239
+ * You can combine filters with **the `and()` relation** and specify exactly which icon you want
3240
+ * ```typescript
3241
+ * const icons = await aui.get().icon().withText('user').and().colored('red').exec()
3242
+ * console.log(icons)
3243
+ * ```
3244
+ * The get command returns only the red icon although both icons have the same text
3245
+ * ```text
3246
+ * console output: [
3247
+ * DetectedElement {
3248
+ * name: 'ICON',
3249
+ * text: 'user',
3250
+ * colors: [ 'red', 'red', 'red' ],
3251
+ * bndbox: BoundingBox {
3252
+ * xmin: 900,
3253
+ * ymin: 910,
3254
+ * xmax: 920,
3255
+ * ymax: 930
3256
+ * }
3257
+ * }
3258
+ * ]
3259
+ * ```
3260
+ *
3261
+ * @return {FluentFiltersGetter}
3262
+ */
3263
+ and() {
3264
+ this._textStr = 'and';
3265
+ return new FluentFiltersGetter(this);
3266
+ }
2925
3267
  /**
2926
3268
  * Filters for an element inside another element.
2927
3269
  *
@@ -3102,7 +3444,32 @@ export class FluentFiltersOrRelationsGetter extends FluentFiltersGetter {
3102
3444
  // Commands
3103
3445
  export class Getter extends FluentCommand {
3104
3446
  /**
3105
- * Returns the filtered element
3447
+ * Returns an array with all filtered elements.
3448
+ * A detected element has the following properties:
3449
+ * - `name` of the element
3450
+ * - `text` content of element
3451
+ * - `colors` of element
3452
+ * - `bndbox`: location of element described with coordinates of a bounding box
3453
+ * **Examples:**
3454
+ * ```typescript
3455
+ * const text = await aui.get().text().withText('Sign').exec();
3456
+ * console.log(text);
3457
+ * ```
3458
+ * ```text
3459
+ * console output: [
3460
+ * DetectedElement {
3461
+ * name: 'TEXT',
3462
+ * text: 'Sign In',
3463
+ * colors: [ 'black', 'gray', 'gray' ],
3464
+ * bndbox: BoundingBox {
3465
+ * xmin: 1128.2720982142857,
3466
+ * ymin: 160.21332310267857,
3467
+ * xmax: 1178.8204241071428,
3468
+ * ymax: 180.83512834821428
3469
+ * }
3470
+ * }
3471
+ * ]
3472
+ * ```
3106
3473
  *
3107
3474
  * @return {FluentFiltersGetter}
3108
3475
  */
@@ -3111,7 +3478,43 @@ export class Getter extends FluentCommand {
3111
3478
  return new FluentFiltersGetter(this);
3112
3479
  }
3113
3480
  /**
3114
- * Returns all detected elements
3481
+ * Returns an array with all detected elements.
3482
+ * A detected element has the following properties:
3483
+ * - `name` of the element
3484
+ * - `text` content of element
3485
+ * - `colors` of element
3486
+ * - `bndbox`: location of element described with coordinates of a bounding box
3487
+ * **Examples:**
3488
+ * ```typescript
3489
+ * const detectedElements = await aui.getAll().exec();
3490
+ * console.log(detectedElements);
3491
+ * ```
3492
+ * ```text
3493
+ * console output: [
3494
+ * DetectedElement {
3495
+ * name: 'TEXT',
3496
+ * text: 'Sign In',
3497
+ * colors: [ 'black', 'gray', 'gray' ],
3498
+ * bndbox: BoundingBox {
3499
+ * xmin: 1128.2720982142857,
3500
+ * ymin: 160.21332310267857,
3501
+ * xmax: 1178.8204241071428,
3502
+ * ymax: 180.83512834821428
3503
+ * },
3504
+ * DetectedElement {
3505
+ * name: 'ICON',
3506
+ * text: 'search',
3507
+ * colors: [ 'black', 'red', 'gray' ],
3508
+ * bndbox: BoundingBox {
3509
+ * xmin: 250.8204241071428,
3510
+ * ymin: 300.21332310267857,
3511
+ * xmax: 450.6304241071428,
3512
+ * ymax: 950.47812834821428
3513
+ * },
3514
+ * ... 381 more items
3515
+ * }
3516
+ * ]
3517
+ * ```
3115
3518
  *
3116
3519
  * @return {ExecGetter}
3117
3520
  */
@@ -1,15 +1,46 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { Command } from 'commander';
2
11
  import path from 'path';
3
12
  import fs from 'fs-extra';
4
13
  import { getPathToNodeModulesRoot } from '../utils/path';
14
+ import { logger } from './logger';
5
15
  const createProgram = () => {
6
16
  const program = new Command('askui');
7
17
  program.usage('<command> [options]');
8
18
  return program;
9
19
  };
10
- function copyExampleProject() {
11
- const exampleProjectPath = path.join('example_projects_templates', 'typescript_jest');
12
- fs.copySync(path.join(getPathToNodeModulesRoot(), exampleProjectPath), '.');
20
+ function replaceStringInFile(filePath, replace, replacement) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ try {
23
+ const data = yield fs.readFile(filePath, 'utf8');
24
+ const result = data.replace(replace, replacement);
25
+ yield fs.writeFile(filePath, result, 'utf8');
26
+ }
27
+ catch (error) {
28
+ logger.error(`Could not replace '${replace}' with '${replacement}' in file '${path}'`);
29
+ logger.error(error.message);
30
+ }
31
+ });
32
+ }
33
+ function copyExampleProject(options) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ const exampleProjectPath = path.join('example_projects_templates', 'typescript_jest');
36
+ fs.copySync(path.join(getPathToNodeModulesRoot(), exampleProjectPath), '.');
37
+ if (options['workspaceId']) {
38
+ yield replaceStringInFile('./test/helper/jest.setup.ts', '<your workspace id>', options['workspaceId']);
39
+ }
40
+ if (options['accessToken']) {
41
+ yield replaceStringInFile('./test/helper/jest.setup.ts', '<your access token>', options['accessToken']);
42
+ }
43
+ });
13
44
  }
14
45
  export function init(argv) {
15
46
  const args = argv || process.argv;
@@ -17,6 +48,11 @@ export function init(argv) {
17
48
  program
18
49
  .command('init')
19
50
  .description('creates a typescript example project')
20
- .action(() => { copyExampleProject(); });
51
+ .option('-w, --workspace-id <value>', 'a workspace id')
52
+ .option('-a, --access-token <value>', 'an access token for the workspace with the id')
53
+ .usage('[-w workspace_id] [-a access_token]')
54
+ .action((opts) => __awaiter(this, void 0, void 0, function* () {
55
+ yield copyExampleProject(opts);
56
+ }));
21
57
  return program.parse(args);
22
58
  }
@@ -20,7 +20,12 @@ beforeAll(async () => {
20
20
 
21
21
  await uiController.start();
22
22
 
23
- aui = await UiControlClient.build();
23
+ aui = await UiControlClient.build({
24
+ credentials: {
25
+ workspaceId: '<your workspace id>',
26
+ token: '<your access token>',
27
+ },
28
+ });
24
29
 
25
30
  await aui.connect();
26
31
  });
@@ -2,9 +2,14 @@ import { aui } from './helper/jest.setup';
2
2
 
3
3
  describe('jest with askui', () => {
4
4
  it('should click on text', async () => {
5
+ // Run this to see what askui annotates
6
+ await aui.annotateInteractively();
7
+
8
+ await aui.moveMouse(0, 0).exec();
5
9
  await aui
6
10
  .click()
7
11
  .text()
12
+ .withText('Click on this text right here!')
8
13
  .exec();
9
14
  });
10
15
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "askui",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "license": "MIT",
5
5
  "author": "askui GmbH <info@askui.com> (http://www.askui.com/)",
6
6
  "description": "Reliable, automated end-to-end-testing that depends on what is shown on your screen instead of the technology you are running on",
@@ -1,5 +0,0 @@
1
- import { DetectedElement } from '../model/annotation-result/detected-element';
2
- export interface AnnotationJson {
3
- image: string;
4
- objects: DetectedElement[];
5
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +0,0 @@
1
- import { DetectedElement } from '../model/annotation-result/detected-element';
2
- export interface AnnotationJson {
3
- image: string;
4
- objects: DetectedElement[];
5
- }
@@ -1 +0,0 @@
1
- export {};