6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
+ import { HarnessPredicate } from '@angular/cdk/testing' ;
9
10
import {
10
- ComponentHarness ,
11
- ComponentHarnessConstructor ,
12
- HarnessPredicate ,
13
- HarnessQuery ,
14
- parallel ,
15
- TestElement
16
- } from '@angular/cdk/testing' ;
17
- import { FormFieldHarnessFilters } from '@angular/material/form-field/testing' ;
18
- import { MatFormFieldControlHarness } from '@angular/material/form-field/testing/control' ;
11
+ FormFieldHarnessFilters ,
12
+ _MatFormFieldHarnessBase ,
13
+ } from '@angular/material/form-field/testing' ;
19
14
import { MatInputHarness } from '@angular/material-experimental/mdc-input/testing' ;
20
15
import { MatSelectHarness } from '@angular/material-experimental/mdc-select/testing' ;
21
16
@@ -25,7 +20,7 @@ import {MatSelectHarness} from '@angular/material-experimental/mdc-select/testin
25
20
export type FormFieldControlHarness = MatInputHarness | MatSelectHarness ;
26
21
27
22
/** Harness for interacting with a MDC-based form-field's in tests. */
28
- export class MatFormFieldHarness extends ComponentHarness {
23
+ export class MatFormFieldHarness extends _MatFormFieldHarnessBase < FormFieldControlHarness > {
29
24
static hostSelector = '.mat-mdc-form-field' ;
30
25
31
26
/**
@@ -36,25 +31,21 @@ export class MatFormFieldHarness extends ComponentHarness {
36
31
*/
37
32
static with ( options : FormFieldHarnessFilters = { } ) : HarnessPredicate < MatFormFieldHarness > {
38
33
return new HarnessPredicate ( MatFormFieldHarness , options )
39
- . addOption (
40
- 'floatingLabelText' , options . floatingLabelText ,
34
+ . addOption ( 'floatingLabelText' , options . floatingLabelText ,
41
35
async ( harness , text ) => HarnessPredicate . stringMatches ( await harness . getLabel ( ) , text ) )
42
- . addOption (
43
- 'hasErrors' , options . hasErrors ,
36
+ . addOption ( 'hasErrors' , options . hasErrors ,
44
37
async ( harness , hasErrors ) => await harness . hasErrors ( ) === hasErrors ) ;
45
38
}
46
39
40
+ protected _prefixContainer = this . locatorForOptional ( '.mat-mdc-form-field-prefix' ) ;
41
+ protected _suffixContainer = this . locatorForOptional ( '.mat-mdc-form-field-suffix' ) ;
42
+ protected _label = this . locatorForOptional ( '.mdc-floating-label' ) ;
43
+ protected _errors = this . locatorForAll ( '.mat-mdc-form-field-error' ) ;
44
+ protected _hints = this . locatorForAll ( '.mat-mdc-form-field-hint' ) ;
45
+ protected _inputControl = this . locatorForOptional ( MatInputHarness ) ;
46
+ protected _selectControl = this . locatorForOptional ( MatSelectHarness ) ;
47
47
private _mdcTextField = this . locatorFor ( '.mat-mdc-text-field-wrapper' ) ;
48
48
49
- private _prefixContainer = this . locatorForOptional ( '.mat-mdc-form-field-prefix' ) ;
50
- private _suffixContainer = this . locatorForOptional ( '.mat-mdc-form-field-suffix' ) ;
51
- private _label = this . locatorForOptional ( '.mdc-floating-label' ) ;
52
- private _errors = this . locatorForAll ( '.mat-mdc-form-field-error' ) ;
53
- private _hints = this . locatorForAll ( '.mat-mdc-form-field-hint' ) ;
54
-
55
- private _inputControl = this . locatorForOptional ( MatInputHarness ) ;
56
- private _selectControl = this . locatorForOptional ( MatSelectHarness ) ;
57
-
58
49
/** Gets the appearance of the form-field. */
59
50
async getAppearance ( ) : Promise < 'fill' | 'outline' > {
60
51
const textFieldEl = await this . _mdcTextField ( ) ;
@@ -64,186 +55,14 @@ export class MatFormFieldHarness extends ComponentHarness {
64
55
return 'fill' ;
65
56
}
66
57
67
- /**
68
- * Gets the harness of the control that is bound to the form-field. Only
69
- * default controls such as "MatInputHarness" and "MatSelectHarness" are
70
- * supported.
71
- */
72
- async getControl ( ) : Promise < FormFieldControlHarness | null > ;
73
-
74
- /**
75
- * Gets the harness of the control that is bound to the form-field. Searches
76
- * for a control that matches the specified harness type.
77
- */
78
- async getControl < X extends MatFormFieldControlHarness > ( type : ComponentHarnessConstructor < X > ) :
79
- Promise < X | null > ;
80
-
81
- /**
82
- * Gets the harness of the control that is bound to the form-field. Searches
83
- * for a control that matches the specified harness predicate.
84
- */
85
- async getControl < X extends MatFormFieldControlHarness > ( type : HarnessPredicate < X > ) :
86
- Promise < X | null > ;
87
-
88
- // Implementation of the "getControl" method overload signatures.
89
- async getControl < X extends MatFormFieldControlHarness > ( type ?: HarnessQuery < X > ) {
90
- if ( type ) {
91
- return this . locatorForOptional ( type ) ( ) ;
92
- }
93
- const hostEl = await this . host ( ) ;
94
- const [ isInput , isSelect ] = await parallel ( ( ) => [
95
- hostEl . hasClass ( 'mat-mdc-form-field-type-mat-input' ) ,
96
- hostEl . hasClass ( 'mat-mdc-form-field-type-mat-select' ) ,
97
- ] ) ;
98
- if ( isInput ) {
99
- return this . _inputControl ( ) ;
100
- } else if ( isSelect ) {
101
- return this . _selectControl ( ) ;
102
- }
103
- return null ;
104
- }
105
-
106
58
/** Whether the form-field has a label. */
107
59
async hasLabel ( ) : Promise < boolean > {
108
60
return ( await this . _label ( ) ) !== null ;
109
61
}
110
62
111
- /** Gets the label of the form-field. */
112
- async getLabel ( ) : Promise < string | null > {
113
- const labelEl = await this . _label ( ) ;
114
- return labelEl ? labelEl . text ( ) : null ;
115
- }
116
-
117
- /** Whether the form-field has errors. */
118
- async hasErrors ( ) : Promise < boolean > {
119
- return ( await this . getTextErrors ( ) ) . length > 0 ;
120
- }
121
-
122
63
/** Whether the label is currently floating. */
123
64
async isLabelFloating ( ) : Promise < boolean > {
124
65
const labelEl = await this . _label ( ) ;
125
66
return labelEl !== null ? await labelEl . hasClass ( 'mdc-floating-label--float-above' ) : false ;
126
67
}
127
-
128
- /** Whether the form-field is disabled. */
129
- async isDisabled ( ) : Promise < boolean > {
130
- return ( await this . host ( ) ) . hasClass ( 'mat-form-field-disabled' ) ;
131
- }
132
-
133
- /** Whether the form-field is currently autofilled. */
134
- async isAutofilled ( ) : Promise < boolean > {
135
- return ( await this . host ( ) ) . hasClass ( 'mat-form-field-autofilled' ) ;
136
- }
137
-
138
- /** Gets the theme color of the form-field. */
139
- async getThemeColor ( ) : Promise < 'primary' | 'accent' | 'warn' > {
140
- const hostEl = await this . host ( ) ;
141
- const [ isAccent , isWarn ] =
142
- await parallel ( ( ) => [ hostEl . hasClass ( 'mat-accent' ) , hostEl . hasClass ( 'mat-warn' ) ] ) ;
143
- if ( isAccent ) {
144
- return 'accent' ;
145
- } else if ( isWarn ) {
146
- return 'warn' ;
147
- }
148
- return 'primary' ;
149
- }
150
-
151
- /** Gets error messages which are currently displayed in the form-field. */
152
- async getTextErrors ( ) : Promise < string [ ] > {
153
- const errors = await this . _errors ( ) ;
154
- return parallel ( ( ) => errors . map ( e => e . text ( ) ) ) ;
155
- }
156
-
157
- /** Gets hint messages which are currently displayed in the form-field. */
158
- async getTextHints ( ) : Promise < string [ ] > {
159
- const hints = await this . _hints ( ) ;
160
- return parallel ( ( ) => hints . map ( e => e . text ( ) ) ) ;
161
- }
162
-
163
- /**
164
- * Gets a reference to the container element which contains all projected
165
- * prefixes of the form-field.
166
- * @deprecated Use `getPrefixText` instead.
167
- * @breaking -change 11.0.0
168
- */
169
- async getHarnessLoaderForPrefix ( ) : Promise < TestElement | null > {
170
- return this . _prefixContainer ( ) ;
171
- }
172
-
173
- /** Gets the text inside the prefix element. */
174
- async getPrefixText ( ) : Promise < string > {
175
- const prefix = await this . _prefixContainer ( ) ;
176
- return prefix ? prefix . text ( ) : '' ;
177
- }
178
-
179
- /**
180
- * Gets a reference to the container element which contains all projected
181
- * suffixes of the form-field.
182
- * @deprecated Use `getSuffixText` instead.
183
- * @breaking -change 11.0.0
184
- */
185
- async getHarnessLoaderForSuffix ( ) : Promise < TestElement | null > {
186
- return this . _suffixContainer ( ) ;
187
- }
188
-
189
- /** Gets the text inside the suffix element. */
190
- async getSuffixText ( ) : Promise < string > {
191
- const suffix = await this . _suffixContainer ( ) ;
192
- return suffix ? suffix . text ( ) : '' ;
193
- }
194
-
195
- /**
196
- * Whether the form control has been touched. Returns "null"
197
- * if no form control is set up.
198
- */
199
- async isControlTouched ( ) : Promise < boolean | null > {
200
- if ( ! await this . _hasFormControl ( ) ) {
201
- return null ;
202
- }
203
- return ( await this . host ( ) ) . hasClass ( 'ng-touched' ) ;
204
- }
205
-
206
- /**
207
- * Whether the form control is dirty. Returns "null"
208
- * if no form control is set up.
209
- */
210
- async isControlDirty ( ) : Promise < boolean | null > {
211
- if ( ! await this . _hasFormControl ( ) ) {
212
- return null ;
213
- }
214
- return ( await this . host ( ) ) . hasClass ( 'ng-dirty' ) ;
215
- }
216
-
217
- /**
218
- * Whether the form control is valid. Returns "null"
219
- * if no form control is set up.
220
- */
221
- async isControlValid ( ) : Promise < boolean | null > {
222
- if ( ! await this . _hasFormControl ( ) ) {
223
- return null ;
224
- }
225
- return ( await this . host ( ) ) . hasClass ( 'ng-valid' ) ;
226
- }
227
-
228
- /**
229
- * Whether the form control is pending validation. Returns "null"
230
- * if no form control is set up.
231
- */
232
- async isControlPending ( ) : Promise < boolean | null > {
233
- if ( ! await this . _hasFormControl ( ) ) {
234
- return null ;
235
- }
236
- return ( await this . host ( ) ) . hasClass ( 'ng-pending' ) ;
237
- }
238
-
239
- /** Checks whether the form-field control has set up a form control. */
240
- private async _hasFormControl ( ) : Promise < boolean > {
241
- const hostEl = await this . host ( ) ;
242
- // If no form "NgControl" is bound to the form-field control, the form-field
243
- // is not able to forward any control status classes. Therefore if either the
244
- // "ng-touched" or "ng-untouched" class is set, we know that it has a form control
245
- const [ isTouched , isUntouched ] =
246
- await parallel ( ( ) => [ hostEl . hasClass ( 'ng-touched' ) , hostEl . hasClass ( 'ng-untouched' ) ] ) ;
247
- return isTouched || isUntouched ;
248
- }
249
68
}
0 commit comments