15
15
*/
16
16
17
17
import { assert } from 'chai' ;
18
+ import bel from 'bel' ;
19
+ import lolex from 'lolex' ;
18
20
import td from 'testdouble' ;
19
21
20
22
import { verifyDefaultAdapter } from '../helpers/foundation' ;
@@ -23,6 +25,37 @@ import MDCTextfieldFoundation from '../../../packages/mdc-textfield/foundation';
23
25
24
26
const { cssClasses} = MDCTextfieldFoundation ;
25
27
28
+ const DESC_UNDEFINED = {
29
+ get : undefined ,
30
+ set : undefined ,
31
+ enumerable : false ,
32
+ configurable : true ,
33
+ } ;
34
+
35
+ function setupHookTest ( ) {
36
+ const { foundation, mockAdapter} = setupFoundationTest ( MDCTextfieldFoundation ) ;
37
+ const nativeInput = bel `<input type="text">` ;
38
+ td . when ( mockAdapter . getNativeInput ( ) ) . thenReturn ( nativeInput ) ;
39
+ return { foundation, mockAdapter, nativeInput} ;
40
+ }
41
+
42
+ // Shims Object.getOwnPropertyDescriptor for the checkbox's WebIDL attributes. Used to test
43
+ // the behavior of overridding WebIDL properties in different browser environments. For example,
44
+ // in Safari WebIDL attributes don't return get/set in descriptors.
45
+ function withMockCheckboxDescriptorReturning ( descriptor , runTests ) {
46
+ const originalDesc = Object . getOwnPropertyDescriptor ( Object , 'getOwnPropertyDescriptor' ) ;
47
+ const mockGetOwnPropertyDescriptor = td . func ( '.getOwnPropertyDescriptor' ) ;
48
+
49
+ td . when ( mockGetOwnPropertyDescriptor ( HTMLInputElement . prototype , 'value' ) )
50
+ . thenReturn ( descriptor ) ;
51
+
52
+ Object . defineProperty ( Object , 'getOwnPropertyDescriptor' , Object . assign ( { } , originalDesc , {
53
+ value : mockGetOwnPropertyDescriptor ,
54
+ } ) ) ;
55
+ runTests ( mockGetOwnPropertyDescriptor ) ;
56
+ Object . defineProperty ( Object , 'getOwnPropertyDescriptor' , originalDesc ) ;
57
+ }
58
+
26
59
suite ( 'MDCTextfieldFoundation' ) ;
27
60
28
61
test ( 'exports strings' , ( ) => {
@@ -137,6 +170,12 @@ test('#init adds event listeners', () => {
137
170
td . verify ( mockAdapter . registerTransitionEndHandler ( td . matchers . isA ( Function ) ) ) ;
138
171
} ) ;
139
172
173
+ test ( '#destroy removes mdc-textfield--upgraded class' , ( ) => {
174
+ const { foundation, mockAdapter} = setupTest ( ) ;
175
+ foundation . destroy ( ) ;
176
+ td . verify ( mockAdapter . removeClass ( cssClasses . UPGRADED ) ) ;
177
+ } ) ;
178
+
140
179
test ( '#destroy removes event listeners' , ( ) => {
141
180
const { foundation, mockAdapter} = setupTest ( ) ;
142
181
foundation . destroy ( ) ;
@@ -173,6 +212,31 @@ test('#init does not add mdc-textfield__label--float-above class if the input do
173
212
td . verify ( mockAdapter . addClassToLabel ( cssClasses . LABEL_FLOAT_ABOVE ) , { times : 0 } ) ;
174
213
} ) ;
175
214
215
+ test ( '#init handles case when WebIDL attrs cannot be overridden (Safari)' , ( ) => {
216
+ const { foundation, nativeInput} = setupHookTest ( ) ;
217
+ withMockCheckboxDescriptorReturning ( DESC_UNDEFINED , ( ) => {
218
+ assert . doesNotThrow ( ( ) => {
219
+ foundation . init ( ) ;
220
+ nativeInput . value = nativeInput . value + '_' ;
221
+ } ) ;
222
+ } ) ;
223
+ } ) ;
224
+
225
+ test ( '#init handles case when property descriptors are not returned at all (Android Browser)' , ( ) => {
226
+ const { foundation} = setupHookTest ( ) ;
227
+ withMockCheckboxDescriptorReturning ( undefined , ( ) => {
228
+ assert . doesNotThrow ( ( ) => foundation . init ( ) ) ;
229
+ } ) ;
230
+ } ) ;
231
+
232
+ test ( '#destroy handles case when WebIDL attrs cannot be overridden (Safari)' , ( ) => {
233
+ const { foundation} = setupHookTest ( ) ;
234
+ withMockCheckboxDescriptorReturning ( DESC_UNDEFINED , ( ) => {
235
+ assert . doesNotThrow ( ( ) => foundation . init ( ) , 'init sanity check' ) ;
236
+ assert . doesNotThrow ( ( ) => foundation . destroy ( ) ) ;
237
+ } ) ;
238
+ } ) ;
239
+
176
240
test ( 'on input focuses if input event occurs without any other events' , ( ) => {
177
241
const { foundation, mockAdapter} = setupTest ( ) ;
178
242
let input ;
@@ -478,3 +542,45 @@ test('interacting with text field does not emit custom events if input is disabl
478
542
479
543
td . verify ( mockAdapter . notifyIconAction ( ) , { times : 0 } ) ;
480
544
} ) ;
545
+
546
+ test ( '"value" property change hook removes mdc-textfield__label--float-above class' , ( ) => {
547
+ const { foundation, mockAdapter, nativeInput} = setupHookTest ( ) ;
548
+ const clock = lolex . install ( ) ;
549
+
550
+ withMockCheckboxDescriptorReturning ( {
551
+ get : ( ) => { } ,
552
+ set : ( ) => { } ,
553
+ enumerable : false ,
554
+ configurable : true ,
555
+ } , ( ) => {
556
+ nativeInput . value = '_' ;
557
+ foundation . init ( ) ;
558
+ nativeInput . value = '' ;
559
+ td . verify ( mockAdapter . removeClassFromLabel ( cssClasses . LABEL_FLOAT_ABOVE ) ) ;
560
+ } ) ;
561
+
562
+ clock . uninstall ( ) ;
563
+ } ) ;
564
+
565
+ test ( '"value" property change hook does nothing if input is focused' , ( ) => {
566
+ const { foundation, mockAdapter, nativeInput} = setupHookTest ( ) ;
567
+ const clock = lolex . install ( ) ;
568
+
569
+ withMockCheckboxDescriptorReturning ( {
570
+ get : ( ) => { } ,
571
+ set : ( ) => { } ,
572
+ enumerable : false ,
573
+ configurable : true ,
574
+ } , ( ) => {
575
+ let focus ;
576
+ td . when ( mockAdapter . registerInputInteractionHandler ( 'focus' , td . matchers . isA ( Function ) ) ) . thenDo ( ( type , handler ) => {
577
+ focus = handler ;
578
+ } ) ;
579
+ foundation . init ( ) ;
580
+ focus ( ) ;
581
+ nativeInput . value = '' ;
582
+ td . verify ( mockAdapter . removeClassFromLabel ( td . matchers . anything ( ) ) , { times : 0 } ) ;
583
+ } ) ;
584
+
585
+ clock . uninstall ( ) ;
586
+ } ) ;
0 commit comments