@sumaris-net/ngx-components 21.0.0-rc2 → 21.0.0-rc21
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/doc/changelog.md +89 -1
- package/fesm2022/sumaris-net-ngx-components-testing.mjs +502 -0
- package/fesm2022/sumaris-net-ngx-components-testing.mjs.map +1 -0
- package/fesm2022/sumaris-net.ngx-components.mjs +5179 -3014
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +32 -23
- package/src/assets/i18n/en-US.json +20 -1
- package/src/assets/i18n/en.json +20 -1
- package/src/assets/i18n/fr.json +21 -2
- package/src/assets/icons-ref.json +21381 -0
- package/src/assets/manifest.json +1 -1
- package/src/theme/_functions.scss +2 -2
- package/src/theme/_icons.scss +1 -1
- package/src/theme/_ionic.globals.scss +11 -5
- package/src/theme/_material.globals.scss +2 -0
- package/src/theme/_mixins.scss +26 -19
- package/src/theme/_ngx-components.globals.scss +3 -0
- package/src/theme/_ngx-components.scss +16 -6
- package/src/theme/_ngx-components.table.scss +11 -0
- package/src/theme/_theme.scss +7 -6
- package/src/theme/_theme.variables.scss +11 -5
- package/src/theme/ionic/ionic.globals.scss +1 -2
- package/types/sumaris-net-ngx-components-testing.d.ts +287 -0
- package/types/sumaris-net.ngx-components.d.ts +901 -279
package/src/assets/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "ngx-sumaris-components",
|
|
3
3
|
"short_name": "ngx-sumaris-components",
|
|
4
4
|
"manifest_version": 1,
|
|
5
|
-
"version": "21.0.0-
|
|
5
|
+
"version": "21.0.0-rc21",
|
|
6
6
|
"default_locale": "fr",
|
|
7
7
|
"description": "Angular components for building beautiful and responsive Apps",
|
|
8
8
|
"icons": [{
|
package/src/theme/_icons.scss
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// --------------------------------------------------
|
|
4
4
|
// Import material icons
|
|
5
5
|
// --------------------------------------------------
|
|
6
|
-
@
|
|
6
|
+
@forward 'material-design-icons-iconfont/src/material-design-icons' with (
|
|
7
7
|
$material-design-icons-font-directory-path: '../dist/fonts/'
|
|
8
8
|
);
|
|
9
9
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// Color functions (get-color-shade/tint, color-to-rgb-list) must be in scope here,
|
|
2
|
+
// otherwise the $colors map below (and the mixins in _mixins.scss) would emit them as
|
|
3
|
+
// literal, unevaluated CSS functions (e.g. `get-color-tint(#3880ff)`), producing invalid
|
|
4
|
+
// values for --ion-color-*-tint/-shade/-rgb. With Sass modules, `@use ... as *` is NOT
|
|
5
|
+
// transitive, so we must use/forward this module explicitly (the legacy @import made it global).
|
|
6
|
+
@use 'ionic/ionic.functions.color' as *;
|
|
3
7
|
|
|
4
8
|
// --------------------------------------------------
|
|
5
9
|
// Define Ionic defaults
|
|
6
10
|
// --------------------------------------------------
|
|
7
|
-
@forward 'ionic/ionic.globals';
|
|
8
|
-
@forward 'ionic/ionic.theme.default';
|
|
9
|
-
|
|
10
11
|
$ionicons-font-path: '~ionicons/dist/fonts';
|
|
11
12
|
|
|
12
13
|
// --------------------------------------------------
|
|
@@ -140,4 +141,9 @@ $colors: (
|
|
|
140
141
|
dark: (base: $dark, contrast: #fff, shade: get-color-shade($dark), tint: get-color-tint($dark)),
|
|
141
142
|
/* transparent */
|
|
142
143
|
transparent: (base: $transparent, contrast: $dark, shade: $transparent, tint: $transparent)
|
|
144
|
+
) !default;
|
|
145
|
+
|
|
146
|
+
@forward 'ionic/ionic.functions.color';
|
|
147
|
+
@forward 'ionic/ionic.globals' with (
|
|
148
|
+
$colors: $colors
|
|
143
149
|
);
|
|
@@ -80,3 +80,5 @@ $mat-toolbar-height-mobile: 56px !default;
|
|
|
80
80
|
$mat-toolbar-background-color: var(--ion-toolbar-background, var(--ion-background-color, whitesmoke)) !default;
|
|
81
81
|
$mat-option-min-height: 48px !default;
|
|
82
82
|
$mat-option-max-height: 48px !default;
|
|
83
|
+
$mat-expansion-container-background-color: var(--ion-color-secondary100) !default;
|
|
84
|
+
$mat-expansion-container-text-color: var(--ion-text-color) !default;
|
package/src/theme/_mixins.scss
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
@use 'ngx-components.globals' as *;
|
|
5
5
|
@use '@angular/material' as mat;
|
|
6
6
|
|
|
7
|
-
@forward "functions";
|
|
8
|
-
|
|
9
7
|
@mixin font-size($size) {
|
|
10
8
|
font-size: calculateRem($size);
|
|
11
9
|
}
|
|
@@ -44,12 +42,20 @@
|
|
|
44
42
|
/**
|
|
45
43
|
* Define CSS theme colors
|
|
46
44
|
*/
|
|
47
|
-
@mixin generate-color($color-name) {
|
|
48
|
-
$value: map-get($colors, $color-name);
|
|
45
|
+
@mixin generate-color($color-name, $value) {
|
|
49
46
|
$base: map-get($value, base);
|
|
50
47
|
$contrast: map-get($value, contrast);
|
|
48
|
+
@if not $contrast {
|
|
49
|
+
$contrast: get-color-contrast($base);
|
|
50
|
+
}
|
|
51
51
|
$shade: map-get($value, shade);
|
|
52
|
+
@if not $shade {
|
|
53
|
+
$shade: get-color-shade($base);
|
|
54
|
+
}
|
|
52
55
|
$tint: map-get($value, tint);
|
|
56
|
+
@if not $tint {
|
|
57
|
+
$tint: get-color-tint($base);
|
|
58
|
+
}
|
|
53
59
|
--ion-color-base: var(--ion-color-#{""+$color-name}, #{$base}) !important;
|
|
54
60
|
--ion-color-base-rgb: var(--ion-color-#{""+$color-name}-rgb, #{color-to-rgb-list($base)});
|
|
55
61
|
--ion-color-contrast: var(--ion-color-#{""+$color-name}-contrast, #{$contrast}) !important;
|
|
@@ -58,10 +64,12 @@
|
|
|
58
64
|
--ion-color-tint: var(--ion-color-#{""+$color-name}-tint, #{$tint}) !important;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
@mixin generate-color-list($color-name) {
|
|
62
|
-
$value: map-get($colors, $color-name);
|
|
67
|
+
@mixin generate-color-list($color-name, $value) {
|
|
63
68
|
$base: map-get($value, base);
|
|
64
69
|
$contrast: map-get($value, contrast);
|
|
70
|
+
@if not $contrast {
|
|
71
|
+
$contrast: get-color-contrast($base);
|
|
72
|
+
}
|
|
65
73
|
$shade: map-get($value, shade);
|
|
66
74
|
$tint: map-get($value, tint);
|
|
67
75
|
--ion-color-#{""+$color-name} : #{$base};
|
|
@@ -72,8 +80,7 @@
|
|
|
72
80
|
--ion-color-#{""+$color-name}-tint: #{$tint};
|
|
73
81
|
}
|
|
74
82
|
|
|
75
|
-
@mixin generate-dark-color-list($color-name) {
|
|
76
|
-
$value: map-get($colors, $color-name);
|
|
83
|
+
@mixin generate-dark-color-list($color-name, $value) {
|
|
77
84
|
$base: mix(map-get($value, base), #000, 50%);
|
|
78
85
|
$contrast: get-color-contrast($base, true);
|
|
79
86
|
$shade: lighten($base, 10%);
|
|
@@ -95,19 +102,19 @@
|
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
|
|
98
|
-
@mixin css-variables-to-root() {
|
|
99
|
-
@each $color-name,
|
|
100
|
-
$value in $colors {
|
|
105
|
+
@mixin css-variables-to-root($colors) {
|
|
106
|
+
@each $color-name, $value in $colors {
|
|
101
107
|
.ion-color-#{""+$color-name} {
|
|
102
|
-
@include generate-color($color-name);
|
|
108
|
+
@include generate-color($color-name, $value);
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
@each $color-name,
|
|
107
113
|
$value in $colors {
|
|
108
|
-
@include generate-color-list($color-name);
|
|
114
|
+
@include generate-color-list($color-name, $value);
|
|
109
115
|
}
|
|
110
116
|
|
|
117
|
+
|
|
111
118
|
--ion-text-color: #{$text-color-value};
|
|
112
119
|
--ion-text-color-rgb: #{$text-color-rgb-value};
|
|
113
120
|
--ion-grid-column-padding: #{$ion-grid-column-padding};
|
|
@@ -122,10 +129,10 @@
|
|
|
122
129
|
--ion-backdrop-opacity: 0.32;
|
|
123
130
|
--ion-card-background-color: #{$card-background-color};
|
|
124
131
|
|
|
125
|
-
--expansion-panel-padding: var(--ion-padding);
|
|
126
|
-
--expansion-panel-header-padding: var(--ion-padding);
|
|
127
|
-
--mat-expansion-container-background-color: var(--ion-background-color);
|
|
128
|
-
--mat-expansion-container-text-color: var(--ion-text-color);
|
|
132
|
+
--expansion-panel-padding: var($app-expansion-panel-padding, var(--ion-padding));
|
|
133
|
+
--expansion-panel-header-padding: var($app-expansion-panel-header-padding, var(--ion-padding));
|
|
134
|
+
--mat-expansion-container-background-color:var($mat-expansion-container-background-color, var(--ion-background-color));
|
|
135
|
+
--mat-expansion-container-text-color: var($mat-expansion-container-text-color, var(--ion-text-color));
|
|
129
136
|
|
|
130
137
|
--mat-tab-link-height: #{$mat-tab-link-height};
|
|
131
138
|
--mat-tab-bar-height: #{$mat-tab-bar-height};
|
|
@@ -193,7 +200,7 @@
|
|
|
193
200
|
|
|
194
201
|
}
|
|
195
202
|
|
|
196
|
-
@mixin css-variables-to-root-dark() {
|
|
203
|
+
@mixin css-variables-to-root-dark($colors) {
|
|
197
204
|
|
|
198
205
|
@include mat.all-component-colors($candy-dark-theme);
|
|
199
206
|
|
|
@@ -202,7 +209,7 @@
|
|
|
202
209
|
|
|
203
210
|
@each $color-name,
|
|
204
211
|
$value in $colors {
|
|
205
|
-
@include generate-dark-color-list($color-name);
|
|
212
|
+
@include generate-dark-color-list($color-name, $value);
|
|
206
213
|
}
|
|
207
214
|
|
|
208
215
|
// Inverse background/text color
|
|
@@ -13,6 +13,9 @@ $app-table-cell-focus-background-color: transparent !default;
|
|
|
13
13
|
$app-paginator-height: 34px !default;
|
|
14
14
|
$app-form-buttons-bar-height: 56px !default;
|
|
15
15
|
|
|
16
|
+
$app-expansion-panel-padding: 0 !default;
|
|
17
|
+
$app-expansion-panel-header-padding: 0 !default;
|
|
18
|
+
|
|
16
19
|
// Form's field text and label
|
|
17
20
|
$app-form-color: #{$text-color} !default;
|
|
18
21
|
$app-form-color-rgb: #{$text-color-rgb} !default;
|
|
@@ -209,6 +209,12 @@ mat-option {
|
|
|
209
209
|
padding: 0 !important;
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
+
|
|
213
|
+
/* hide pseudo checkbox, in the footer*/
|
|
214
|
+
&.mat-pseudo-checkbox-hidden mat-pseudo-checkbox {
|
|
215
|
+
visibility: hidden;
|
|
216
|
+
display: none;
|
|
217
|
+
}
|
|
212
218
|
}
|
|
213
219
|
|
|
214
220
|
mat-option:not(:last-of-type) {
|
|
@@ -296,7 +302,7 @@ mat-option:not(:last-of-type) {
|
|
|
296
302
|
}
|
|
297
303
|
|
|
298
304
|
&:has(.min-width-80vw),
|
|
299
|
-
&:has(.mat-mdc-autocomplete-panel-80vw-size){
|
|
305
|
+
&:has(.mat-mdc-autocomplete-panel-80vw-size) {
|
|
300
306
|
--min-width: 80vw;
|
|
301
307
|
}
|
|
302
308
|
|
|
@@ -404,12 +410,14 @@ ion-list,
|
|
|
404
410
|
/* Offset due to mat-pseudo-checkbox */
|
|
405
411
|
padding-left: 32px;
|
|
406
412
|
}
|
|
407
|
-
&.
|
|
413
|
+
&.sticky {
|
|
408
414
|
/* Set header as sticky*/
|
|
409
415
|
position: -webkit-sticky;
|
|
410
416
|
position: sticky;
|
|
411
|
-
top: 0;
|
|
417
|
+
top: var(--top, 0);
|
|
412
418
|
z-index: 1001;
|
|
419
|
+
}
|
|
420
|
+
&.column {
|
|
413
421
|
background-color: var(--ion-color-secondary);
|
|
414
422
|
border-bottom: 1px solid #{$app-select-option-border-color};
|
|
415
423
|
color: var(--ion-color-secondary-contrast);
|
|
@@ -417,16 +425,16 @@ ion-list,
|
|
|
417
425
|
@include font-size(12px);
|
|
418
426
|
font-weight: 500;
|
|
419
427
|
height: 20px;
|
|
428
|
+
--top: var(--header-column-top, 0);
|
|
420
429
|
ion-col {
|
|
421
430
|
white-space: nowrap;
|
|
422
431
|
text-overflow: ellipsis;
|
|
423
432
|
}
|
|
424
433
|
&.mat-select-searchbar-sticky {
|
|
425
434
|
/* offset because of the searchbar height */
|
|
426
|
-
top: var(--ion-searchbar-height, 58px);
|
|
435
|
+
--header-column-top: var(--ion-searchbar-height, 58px);
|
|
427
436
|
}
|
|
428
437
|
}
|
|
429
|
-
|
|
430
438
|
}
|
|
431
439
|
|
|
432
440
|
ion-row.ion-list-footer,
|
|
@@ -437,7 +445,7 @@ ion-list,
|
|
|
437
445
|
/* Set footer as sticky*/
|
|
438
446
|
position: -webkit-sticky;
|
|
439
447
|
position: sticky;
|
|
440
|
-
bottom: 0;
|
|
448
|
+
bottom: var(--footer-bottom, 0);
|
|
441
449
|
z-index: 1001;
|
|
442
450
|
border-top: 1px solid #{$app-select-option-border-color};
|
|
443
451
|
background-color: var(--ion-toolbar-background, #{$ion-toolbar-background});
|
|
@@ -453,6 +461,8 @@ ion-list,
|
|
|
453
461
|
white-space: nowrap;
|
|
454
462
|
text-overflow: ellipsis;
|
|
455
463
|
}
|
|
464
|
+
|
|
465
|
+
|
|
456
466
|
}
|
|
457
467
|
|
|
458
468
|
ion-row {
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
.dark .mat-mdc-table {
|
|
17
|
+
// Pre-migration dark-theme sort arrow color (see light value in .mat-mdc-table below)
|
|
18
|
+
--mat-sort-arrow-color: #c6c6c6;
|
|
17
19
|
--mat-checkbox-selected-checkmark-color: var(--ion-text-color);
|
|
18
20
|
--mat-checkbox-unselected-icon-color: var(--ion-text-color);
|
|
19
21
|
--mat-checkbox-selected-icon-color: var(--ion-color-accent);
|
|
@@ -28,6 +30,10 @@
|
|
|
28
30
|
--mat-table-background-color: var(--background, var(--ion-background-color));
|
|
29
31
|
--mat-table-header-color: var(--ion-color-primary);
|
|
30
32
|
--mat-table-header-background-color: var(--mat-table-background-color);
|
|
33
|
+
// Restore the sort arrow color. The Angular Material M2 theme used to emit this token
|
|
34
|
+
// (#757575 light / #c6c6c6 dark); after the M3 migration it is no longer set, so the arrow
|
|
35
|
+
// falls back to --mat-sys-on-surface (black). Keep the pre-migration grey for consistency.
|
|
36
|
+
--mat-sort-arrow-color: #757575;
|
|
31
37
|
--mat-table-row-item-label-text-color: var(--ion-text-color);
|
|
32
38
|
--mat-table-row-item-outline-color: var(--ion-border-color);
|
|
33
39
|
--mat-table-row-item-label-text-size: 14px;
|
|
@@ -120,6 +126,8 @@
|
|
|
120
126
|
.mat-mdc-footer-cell {
|
|
121
127
|
// Remove default padding
|
|
122
128
|
padding-inline: 0;
|
|
129
|
+
padding-inline-start: 0; // Compat Chrome < 87 (padding-inline not exists yet)
|
|
130
|
+
padding-inline-end: 0; // Compat Chrome < 87 (padding-inline not exists yet)
|
|
123
131
|
|
|
124
132
|
&.ion-padding-start {
|
|
125
133
|
padding-inline-start: var(--mat-cell-horizontal-padding);
|
|
@@ -357,7 +365,10 @@
|
|
|
357
365
|
}
|
|
358
366
|
|
|
359
367
|
.mdc-text-field {
|
|
368
|
+
// Remove default padding
|
|
360
369
|
padding-inline: 0;
|
|
370
|
+
padding-inline-start: 0; // Compat Chrome < 87 (padding-inline not exists yet)
|
|
371
|
+
padding-inline-end: 0; // Compat Chrome < 87 (padding-inline not exists yet)
|
|
361
372
|
}
|
|
362
373
|
|
|
363
374
|
// Prefix
|
package/src/theme/_theme.scss
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
@
|
|
2
|
-
@
|
|
3
|
-
@
|
|
1
|
+
@forward 'ionic.globals';
|
|
2
|
+
@forward 'material.globals';
|
|
3
|
+
@forward 'ngx-components.globals';
|
|
4
4
|
|
|
5
5
|
// --------------------------------------------------
|
|
6
6
|
// Import Ionic style
|
|
7
7
|
// --------------------------------------------------
|
|
8
8
|
@use "ionic";
|
|
9
9
|
// --------------------------------------------------
|
|
10
|
-
// Import
|
|
10
|
+
// Import Icons
|
|
11
11
|
// --------------------------------------------------
|
|
12
12
|
$ionicons-font-path: '~ionicons/dist/fonts';
|
|
13
13
|
@use "icons";
|
|
14
14
|
// --------------------------------------------------
|
|
15
15
|
// Import Fonts
|
|
16
16
|
// --------------------------------------------------
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
@use "roboto" as * with (
|
|
18
|
+
$roboto-font-path: '~roboto-fontface/fonts/roboto'
|
|
19
|
+
);
|
|
19
20
|
// --------------------------------------------------
|
|
20
21
|
// Import responsive style
|
|
21
22
|
// --------------------------------------------------
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
+
@use 'ionic.globals' as *;
|
|
1
2
|
@use "mixins" as *;
|
|
2
3
|
|
|
4
|
+
|
|
3
5
|
* {
|
|
4
6
|
@include font-roboto();
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
/** Inject all CSS Variables **/
|
|
8
|
-
html
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// NOTE: must use ':root' (not 'html') to match the specificity of Ionic 8's
|
|
11
|
+
// default palette, which is now declared on ':root' in @ionic/angular/css/core.css.
|
|
12
|
+
// A 'html' selector has a lower specificity than ':root' and would always be
|
|
13
|
+
// overridden by Ionic's defaults (e.g. --ion-color-primary: #0054e9).
|
|
14
|
+
:root {
|
|
15
|
+
@include css-variables-to-root($colors);
|
|
16
|
+
|
|
17
|
+
&:has(html.plt-mobile) {
|
|
12
18
|
@include css-variables-to-root-mobile();
|
|
13
19
|
}
|
|
14
20
|
|
|
@@ -19,7 +25,7 @@ html {
|
|
|
19
25
|
* -------------------------------------------
|
|
20
26
|
*/
|
|
21
27
|
html.dark {
|
|
22
|
-
@include css-variables-to-root-dark();
|
|
28
|
+
@include css-variables-to-root-dark($colors);
|
|
23
29
|
|
|
24
30
|
--ion-color-primary: #428cff;
|
|
25
31
|
--ion-color-primary-rgb: 66, 140, 255;
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Page, Locator, PlaywrightTestArgs } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
declare const STARTUP_DATA_STORAGE_KEY = "__appStartupData";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Utility selectors and helpers for Ionic components in e2e tests.
|
|
7
|
+
*/
|
|
8
|
+
declare const IonicSelectors: {
|
|
9
|
+
/** Ionic button */
|
|
10
|
+
button: string;
|
|
11
|
+
/** Ionic modal */
|
|
12
|
+
modal: string;
|
|
13
|
+
/** Ionic content area */
|
|
14
|
+
content: string;
|
|
15
|
+
/** Ionic item */
|
|
16
|
+
item: string;
|
|
17
|
+
/** Ionic label */
|
|
18
|
+
label: string;
|
|
19
|
+
/** Ionic spinner */
|
|
20
|
+
spinner: string;
|
|
21
|
+
/** Ionic skeleton text (loading placeholder) */
|
|
22
|
+
skeletonText: string;
|
|
23
|
+
/** Ionic back button */
|
|
24
|
+
backButton: string;
|
|
25
|
+
/** Ionic toolbar */
|
|
26
|
+
toolbar: string;
|
|
27
|
+
/** Ionic footer */
|
|
28
|
+
footer: string;
|
|
29
|
+
/** Ionic header */
|
|
30
|
+
header: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Helper functions for interacting with Ionic components.
|
|
34
|
+
*/
|
|
35
|
+
declare class IonicHelper {
|
|
36
|
+
private page;
|
|
37
|
+
constructor(page: Page);
|
|
38
|
+
/** Get an Ionic button by text content */
|
|
39
|
+
buttonByText(text: string | RegExp): Locator;
|
|
40
|
+
/** Get an Ionic button by CSS selector */
|
|
41
|
+
button(selector?: string, options?: {
|
|
42
|
+
hasText?: string | RegExp;
|
|
43
|
+
}): Locator;
|
|
44
|
+
/**
|
|
45
|
+
* Get an Ionic modal by its inner component selector (e.g. 'app-auth-form').
|
|
46
|
+
* Automatically wraps the selector in `ion-modal:has(...)` so callers
|
|
47
|
+
* only need to provide the component tag name.
|
|
48
|
+
*/
|
|
49
|
+
modal(selector: string): Locator;
|
|
50
|
+
/** Wait for the Ionic app to be ready */
|
|
51
|
+
waitForAppReady(timeout?: number): Promise<void>;
|
|
52
|
+
/** Wait for loading spinners to disappear */
|
|
53
|
+
waitForLoadingComplete(timeout?: number): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Utility selectors and helpers for Angular Material components in e2e tests.
|
|
58
|
+
*/
|
|
59
|
+
declare const MaterialSelectors: {
|
|
60
|
+
/** Material table row */
|
|
61
|
+
row: string;
|
|
62
|
+
/** Material header row */
|
|
63
|
+
headerRow: string;
|
|
64
|
+
/** Material cell */
|
|
65
|
+
cell: string;
|
|
66
|
+
/** Material form field */
|
|
67
|
+
formField: string;
|
|
68
|
+
/** Material input */
|
|
69
|
+
input: string;
|
|
70
|
+
/** Material tab group */
|
|
71
|
+
tabGroup: string;
|
|
72
|
+
/** Material tab label */
|
|
73
|
+
tabLabel: string;
|
|
74
|
+
/** Material paginator */
|
|
75
|
+
paginator: string;
|
|
76
|
+
/** Material icon */
|
|
77
|
+
icon: string;
|
|
78
|
+
/** Material autocomplete panel */
|
|
79
|
+
autocompletePanel: string;
|
|
80
|
+
/** Material autocomplete option */
|
|
81
|
+
autocompleteOption: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Helper functions for interacting with Angular Material components.
|
|
85
|
+
*/
|
|
86
|
+
declare class MaterialHelper {
|
|
87
|
+
private page;
|
|
88
|
+
constructor(page: Page);
|
|
89
|
+
/** Get all visible table rows, optionally scoped to a parent locator */
|
|
90
|
+
tableRows(scope?: Locator): Locator;
|
|
91
|
+
/** Get a single table row by index (0-based), optionally scoped to a parent locator */
|
|
92
|
+
tableRow(index: number, scope?: Locator): Locator;
|
|
93
|
+
/** Click on a table row by index (0-based), optionally scoped to a parent locator */
|
|
94
|
+
clickRow(index: number, scope?: Locator): Promise<void>;
|
|
95
|
+
/** Get a tab by its label text */
|
|
96
|
+
tabByLabel(text: string | RegExp): Locator;
|
|
97
|
+
/** Click a tab by its label text */
|
|
98
|
+
clickTab(text: string | RegExp): Promise<void>;
|
|
99
|
+
/** Fill a mat-form-field input identified by its formControlName.
|
|
100
|
+
* Supports both native inputs with formcontrolname and custom components (e.g. mat-autocomplete-field) wrapping an input. */
|
|
101
|
+
fillFormControl(formControlName: string, value: string): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Select an option from a mat-select dropdown by formControlName.
|
|
104
|
+
* Opens the dropdown, waits for options to render, clicks the matching option, then waits for the dropdown to close.
|
|
105
|
+
*/
|
|
106
|
+
selectMatSelectOption(formControlName: string, optionText: string | RegExp): Promise<void>;
|
|
107
|
+
/** Select an autocomplete option by text after typing in a form control */
|
|
108
|
+
selectAutocompleteOption(formControlName: string, searchText: string, optionText: string | RegExp): Promise<void>;
|
|
109
|
+
/** Wait for table rows to be loaded (at least one row visible), optionally scoped to a parent locator */
|
|
110
|
+
waitForTableRows(timeout?: number, scope?: Locator): Promise<void>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Common UI helper functions to improve readability of e2e tests.
|
|
115
|
+
* This helper centralizes access to Ionic and Material specific helpers.
|
|
116
|
+
*/
|
|
117
|
+
declare class UiHelper {
|
|
118
|
+
protected page: Page;
|
|
119
|
+
protected ionic: IonicHelper;
|
|
120
|
+
protected mat: MaterialHelper;
|
|
121
|
+
constructor(page: Page);
|
|
122
|
+
/**
|
|
123
|
+
* Click an element and wait for it to be ready.
|
|
124
|
+
* @param locator The locator to click.
|
|
125
|
+
* @param timeout The maximum time to wait.
|
|
126
|
+
*/
|
|
127
|
+
click(locator: Locator, timeout?: number): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Fill an input and wait for it to be ready.
|
|
130
|
+
* @param locator The locator to fill.
|
|
131
|
+
* @param value The value to enter.
|
|
132
|
+
* @param timeout The maximum time to wait.
|
|
133
|
+
*/
|
|
134
|
+
fill(locator: Locator, value: string, timeout?: number): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Wait for an element to be visible.
|
|
137
|
+
* @param locator The locator to wait for.
|
|
138
|
+
* @param timeout The maximum time to wait.
|
|
139
|
+
*/
|
|
140
|
+
waitForVisible(locator: Locator, timeout?: number): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Wait for an element to be hidden.
|
|
143
|
+
* @param locator The locator to wait for.
|
|
144
|
+
* @param timeout The maximum time to wait.
|
|
145
|
+
*/
|
|
146
|
+
waitForHidden(locator: Locator, timeout?: number): Promise<void>;
|
|
147
|
+
/**
|
|
148
|
+
* Get a button by its text content.
|
|
149
|
+
* Supports both Ionic and Material buttons.
|
|
150
|
+
* @param text The text content to match.
|
|
151
|
+
* @param scope Optional locator to scope the search within.
|
|
152
|
+
*/
|
|
153
|
+
button(text: string | RegExp, scope?: Locator): Locator;
|
|
154
|
+
/**
|
|
155
|
+
* Get an icon button by its icon name.
|
|
156
|
+
* Supports both Ionic and Material icon buttons.
|
|
157
|
+
* @param iconName The icon name (e.g. 'mail', 'search', 'ellipsis-horizontal').
|
|
158
|
+
* @param scope Optional locator to scope the search within.
|
|
159
|
+
*/
|
|
160
|
+
iconButton(iconName: string, scope?: Locator): Locator;
|
|
161
|
+
/**
|
|
162
|
+
* Access to the underlying Playwright Page object.
|
|
163
|
+
*/
|
|
164
|
+
get pageObj(): Page;
|
|
165
|
+
/** Get a modal by its selector */
|
|
166
|
+
modal(selector: string): Locator;
|
|
167
|
+
/** Get a tab by its label text */
|
|
168
|
+
tab(text: string | RegExp): Locator;
|
|
169
|
+
/** Wait for the app to be ready */
|
|
170
|
+
waitForAppReady(timeout?: number): Promise<void>;
|
|
171
|
+
/** Wait for loading spinners to disappear */
|
|
172
|
+
waitForLoadingComplete(timeout?: number): Promise<void>;
|
|
173
|
+
/** Wait for table rows to be loaded, optionally scoped to a parent locator */
|
|
174
|
+
waitForTableRows(timeout?: number, scope?: Locator): Promise<void>;
|
|
175
|
+
/** Get a single table row by index (0-based), optionally scoped to a parent locator */
|
|
176
|
+
tableRow(index: number, scope?: Locator): Locator;
|
|
177
|
+
/** Click on a table row by index, optionally scoped to a parent locator */
|
|
178
|
+
clickRow(index: number, scope?: Locator): Promise<void>;
|
|
179
|
+
/** Fill a mat-form-field input identified by its formControlName */
|
|
180
|
+
fillFormControl(formControlName: string, value: string): Promise<void>;
|
|
181
|
+
/** Select an autocomplete option */
|
|
182
|
+
selectAutocompleteOption(formControlName: string, searchText: string, optionText: string | RegExp): Promise<void>;
|
|
183
|
+
/**
|
|
184
|
+
* Select an option from a mat-select dropdown.
|
|
185
|
+
* Opens the dropdown, waits for options, clicks the matching one, then waits for the dropdown to close.
|
|
186
|
+
*/
|
|
187
|
+
selectOption(formControlName: string, optionText: string | RegExp): Promise<void>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Helper for authentication in e2e tests.
|
|
192
|
+
*/
|
|
193
|
+
declare class AuthHelper {
|
|
194
|
+
private page;
|
|
195
|
+
protected ui: UiHelper;
|
|
196
|
+
constructor(page: Page, ui?: UiHelper);
|
|
197
|
+
/** Login with given test credentials */
|
|
198
|
+
login(username: string, password: string): Promise<void>;
|
|
199
|
+
/** Wait until the user is logged in and return the email shown in the side menu */
|
|
200
|
+
waitForLoggedIn(): Promise<string | null>;
|
|
201
|
+
/** Setup startup data with provided credentials or environment variables */
|
|
202
|
+
loginByEnv(opts?: {
|
|
203
|
+
username?: string;
|
|
204
|
+
password?: string;
|
|
205
|
+
offline?: boolean;
|
|
206
|
+
peerUrl?: string;
|
|
207
|
+
}): Promise<void>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Search environments based on provided criteria.
|
|
212
|
+
*
|
|
213
|
+
* Use when you need to run tests with one or more environments.
|
|
214
|
+
* Test can use `testWithEnv` to run tests with a specific environment.
|
|
215
|
+
* Example :
|
|
216
|
+
*
|
|
217
|
+
* ```
|
|
218
|
+
* test.describe('Sample test with environment', () => {
|
|
219
|
+
* withEnvs({
|
|
220
|
+
* peerTags: ['local'],
|
|
221
|
+
* userTags: ['admin'],
|
|
222
|
+
* }).forEach((env) => {
|
|
223
|
+
* testWithEnv(env)(`Some test with environment ${env.id}`, async ({ page }) => {
|
|
224
|
+
* // Test implementation
|
|
225
|
+
* });
|
|
226
|
+
* });
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* Environments are loaded from a JSON config file located at one of four paths :
|
|
231
|
+
* - `LOGIN_ENVS_PATH` environment variable
|
|
232
|
+
* - `.environments.json` in the current directory (e.g. `.environments.json`)
|
|
233
|
+
* - `.environments.json` in the `.local` directory (e.g. `.local/environments.json`)
|
|
234
|
+
* - `.environments.json` in the `e2e` directory (e.g. `e2e/.environments.json`)
|
|
235
|
+
*
|
|
236
|
+
* Example of JSON :
|
|
237
|
+
*
|
|
238
|
+
* ```
|
|
239
|
+
* {
|
|
240
|
+
* "peers": [
|
|
241
|
+
* {
|
|
242
|
+
* "id": "local",
|
|
243
|
+
* "tags": ["local"],
|
|
244
|
+
* "url": "http://localhost:8080",
|
|
245
|
+
* "users": [
|
|
246
|
+
* {
|
|
247
|
+
* "tags": ["admin"],
|
|
248
|
+
* "username": "admin@sumaris.net",
|
|
249
|
+
* "password": "admin"
|
|
250
|
+
* }
|
|
251
|
+
* ]
|
|
252
|
+
* }
|
|
253
|
+
* ]
|
|
254
|
+
* }
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* @see testWithEnv
|
|
258
|
+
* @param filter Search criteria.
|
|
259
|
+
*/
|
|
260
|
+
declare function withEnvs(filter: EnvFilter): LoginEnv[];
|
|
261
|
+
/**
|
|
262
|
+
* Currying function that returns a test function that can be used to run tests with a specific environment.
|
|
263
|
+
*
|
|
264
|
+
* ```
|
|
265
|
+
* testWithEnv(env)(`Some test with environment ${env.id}`, async ({ page }) => {
|
|
266
|
+
* // Test implementation
|
|
267
|
+
* })
|
|
268
|
+
* ```
|
|
269
|
+
*
|
|
270
|
+
* @see withEnvs
|
|
271
|
+
* @param env Environment to use for the test.
|
|
272
|
+
*/
|
|
273
|
+
declare function testWithEnv(env: LoginEnv): (title: string, testFn: (args: PlaywrightTestArgs) => Promise<void>) => void;
|
|
274
|
+
interface EnvFilter {
|
|
275
|
+
peerId?: string;
|
|
276
|
+
peerTags?: string[];
|
|
277
|
+
userTags?: string[];
|
|
278
|
+
}
|
|
279
|
+
interface LoginEnv {
|
|
280
|
+
id?: string;
|
|
281
|
+
peerUrl: string;
|
|
282
|
+
username: string;
|
|
283
|
+
password: string;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export { AuthHelper, IonicHelper, IonicSelectors, MaterialHelper, MaterialSelectors, STARTUP_DATA_STORAGE_KEY, UiHelper, testWithEnv, withEnvs };
|
|
287
|
+
export type { EnvFilter, LoginEnv };
|