6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
- import { HarnessPredicate , parallel } from '@angular/cdk/testing' ;
9
+ import {
10
+ HarnessPredicate ,
11
+ parallel ,
12
+ ComponentHarness ,
13
+ BaseHarnessFilters ,
14
+ ComponentHarnessConstructor ,
15
+ } from '@angular/cdk/testing' ;
10
16
import { MatFormFieldControlHarness } from '@angular/material/form-field/testing/control' ;
11
17
import {
12
18
MatOptionHarness ,
@@ -16,29 +22,25 @@ import {
16
22
} from '@angular/material/core/testing' ;
17
23
import { SelectHarnessFilters } from './select-harness-filters' ;
18
24
19
-
20
- /** Harness for interacting with a standard mat-select in tests. */
21
- export class MatSelectHarness extends MatFormFieldControlHarness {
25
+ export abstract class _MatSelectHarnessBase <
26
+ OptionType extends ( ComponentHarnessConstructor < Option > & {
27
+ with : ( options ?: OptionFilters ) => HarnessPredicate < Option > } ) ,
28
+ Option extends ComponentHarness & { click ( ) : Promise < void > } ,
29
+ OptionFilters extends BaseHarnessFilters ,
30
+ OptionGroupType extends ( ComponentHarnessConstructor < OptionGroup > & {
31
+ with : ( options ?: OptionGroupFilters ) => HarnessPredicate < OptionGroup > } ) ,
32
+ OptionGroup extends ComponentHarness ,
33
+ OptionGroupFilters extends BaseHarnessFilters
34
+ > extends MatFormFieldControlHarness {
35
+ protected abstract _prefix : string ;
36
+ protected abstract _optionClass : OptionType ;
37
+ protected abstract _optionGroupClass : OptionGroupType ;
22
38
private _documentRootLocator = this . documentRootLocatorFactory ( ) ;
23
39
private _backdrop = this . _documentRootLocator . locatorFor ( '.cdk-overlay-backdrop' ) ;
24
- private _trigger = this . locatorFor ( '.mat-select-trigger' ) ;
25
- private _value = this . locatorFor ( '.mat-select-value' ) ;
26
-
27
- static hostSelector = '.mat-select' ;
28
-
29
- /**
30
- * Gets a `HarnessPredicate` that can be used to search for a `MatSelectHarness` that meets
31
- * certain criteria.
32
- * @param options Options for filtering which select instances are considered a match.
33
- * @return a `HarnessPredicate` configured with the given options.
34
- */
35
- static with ( options : SelectHarnessFilters = { } ) : HarnessPredicate < MatSelectHarness > {
36
- return new HarnessPredicate ( MatSelectHarness , options ) ;
37
- }
38
40
39
41
/** Gets a boolean promise indicating if the select is disabled. */
40
42
async isDisabled ( ) : Promise < boolean > {
41
- return ( await this . host ( ) ) . hasClass ( 'mat -select-disabled' ) ;
43
+ return ( await this . host ( ) ) . hasClass ( ` ${ this . _prefix } -select-disabled` ) ;
42
44
}
43
45
44
46
/** Gets a boolean promise indicating if the select is valid. */
@@ -48,22 +50,23 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
48
50
49
51
/** Gets a boolean promise indicating if the select is required. */
50
52
async isRequired ( ) : Promise < boolean > {
51
- return ( await this . host ( ) ) . hasClass ( 'mat -select-required' ) ;
53
+ return ( await this . host ( ) ) . hasClass ( ` ${ this . _prefix } -select-required` ) ;
52
54
}
53
55
54
56
/** Gets a boolean promise indicating if the select is empty (no value is selected). */
55
57
async isEmpty ( ) : Promise < boolean > {
56
- return ( await this . host ( ) ) . hasClass ( 'mat -select-empty' ) ;
58
+ return ( await this . host ( ) ) . hasClass ( ` ${ this . _prefix } -select-empty` ) ;
57
59
}
58
60
59
61
/** Gets a boolean promise indicating if the select is in multi-selection mode. */
60
62
async isMultiple ( ) : Promise < boolean > {
61
- return ( await this . host ( ) ) . hasClass ( 'mat -select-multiple' ) ;
63
+ return ( await this . host ( ) ) . hasClass ( ` ${ this . _prefix } -select-multiple` ) ;
62
64
}
63
65
64
66
/** Gets a promise for the select's value text. */
65
67
async getValueText ( ) : Promise < string > {
66
- return ( await this . _value ( ) ) . text ( ) ;
68
+ const value = await this . locatorFor ( `.${ this . _prefix } -select-value` ) ( ) ;
69
+ return value . text ( ) ;
67
70
}
68
71
69
72
/** Focuses the select and returns a void promise that indicates when the action is complete. */
@@ -82,21 +85,19 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
82
85
}
83
86
84
87
/** Gets the options inside the select panel. */
85
- async getOptions ( filter : Omit < OptionHarnessFilters , 'ancestor' > = { } ) :
86
- Promise < MatOptionHarness [ ] > {
87
- return this . _documentRootLocator . locatorForAll ( MatOptionHarness . with ( {
88
- ...filter ,
88
+ async getOptions ( filter ?: Omit < OptionFilters , 'ancestor' > ) : Promise < Option [ ] > {
89
+ return this . _documentRootLocator . locatorForAll ( this . _optionClass . with ( {
90
+ ...( filter || { } ) ,
89
91
ancestor : await this . _getPanelSelector ( )
90
- } ) ) ( ) ;
92
+ } as OptionFilters ) ) ( ) ;
91
93
}
92
94
93
95
/** Gets the groups of options inside the panel. */
94
- async getOptionGroups ( filter : Omit < OptgroupHarnessFilters , 'ancestor' > = { } ) :
95
- Promise < MatOptgroupHarness [ ] > {
96
- return this . _documentRootLocator . locatorForAll ( MatOptgroupHarness . with ( {
97
- ...filter ,
96
+ async getOptionGroups ( filter ?: Omit < OptionGroupFilters , 'ancestor' > ) : Promise < OptionGroup [ ] > {
97
+ return this . _documentRootLocator . locatorForAll ( this . _optionGroupClass . with ( {
98
+ ...( filter || { } ) ,
98
99
ancestor : await this . _getPanelSelector ( )
99
- } ) ) ( ) ;
100
+ } as OptionGroupFilters ) ) ( ) as Promise < OptionGroup [ ] > ;
100
101
}
101
102
102
103
/** Gets whether the select is open. */
@@ -107,20 +108,20 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
107
108
/** Opens the select's panel. */
108
109
async open ( ) : Promise < void > {
109
110
if ( ! await this . isOpen ( ) ) {
110
- return ( await this . _trigger ( ) ) . click ( ) ;
111
+ const trigger = await this . locatorFor ( `.${ this . _prefix } -select-trigger` ) ( ) ;
112
+ return trigger . click ( ) ;
111
113
}
112
114
}
113
115
114
116
/**
115
117
* Clicks the options that match the passed-in filter. If the select is in multi-selection
116
118
* mode all options will be clicked, otherwise the harness will pick the first matching option.
117
119
*/
118
- async clickOptions ( filter : OptionHarnessFilters = { } ) : Promise < void > {
120
+ async clickOptions ( filter ?: OptionFilters ) : Promise < void > {
119
121
await this . open ( ) ;
120
122
121
- const [ isMultiple , options ] = await parallel ( ( ) => {
122
- return [ this . isMultiple ( ) , this . getOptions ( filter ) ] ;
123
- } ) ;
123
+ const [ isMultiple , options ] =
124
+ await parallel ( ( ) => [ this . isMultiple ( ) , this . getOptions ( filter ) ] ) ;
124
125
125
126
if ( options . length === 0 ) {
126
127
throw Error ( 'Select does not have options matching the specified filter' ) ;
@@ -149,3 +150,24 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
149
150
return `#${ id } -panel` ;
150
151
}
151
152
}
153
+
154
+ /** Harness for interacting with a standard mat-select in tests. */
155
+ export class MatSelectHarness extends _MatSelectHarnessBase <
156
+ typeof MatOptionHarness , MatOptionHarness , OptionHarnessFilters ,
157
+ typeof MatOptgroupHarness , MatOptgroupHarness , OptgroupHarnessFilters
158
+ > {
159
+ static hostSelector = '.mat-select' ;
160
+ protected _prefix = 'mat' ;
161
+ protected _optionClass = MatOptionHarness ;
162
+ protected _optionGroupClass = MatOptgroupHarness ;
163
+
164
+ /**
165
+ * Gets a `HarnessPredicate` that can be used to search for a `MatSelectHarness` that meets
166
+ * certain criteria.
167
+ * @param options Options for filtering which select instances are considered a match.
168
+ * @return a `HarnessPredicate` configured with the given options.
169
+ */
170
+ static with ( options : SelectHarnessFilters = { } ) : HarnessPredicate < MatSelectHarness > {
171
+ return new HarnessPredicate ( MatSelectHarness , options ) ;
172
+ }
173
+ }
0 commit comments