@@ -63,7 +63,7 @@ describe('IgxInput', () => {
6363 expect ( inputElement . classList . contains ( TEXTAREA_CSS_CLASS ) ) . toBe ( true ) ;
6464 } ) ;
6565
66- it ( 'Should apply focused style.' , ( ) => {
66+ it ( 'should apply focused style.' , ( ) => {
6767 const fixture = TestBed . createComponent ( InputComponent ) ;
6868 fixture . detectChanges ( ) ;
6969
@@ -83,7 +83,7 @@ describe('IgxInput', () => {
8383 expect ( igxInput . focused ) . toBe ( false ) ;
8484 } ) ;
8585
86- it ( 'Should have a placeholder style. Placeholder API.' , ( ) => {
86+ it ( 'should have a placeholder style. Placeholder API.' , ( ) => {
8787 const fixture = TestBed . createComponent ( InputWithPlaceholderComponent ) ;
8888 fixture . detectChanges ( ) ;
8989
@@ -95,7 +95,7 @@ describe('IgxInput', () => {
9595 expect ( igxInput . placeholder ) . toBe ( 'Test' ) ;
9696 } ) ;
9797
98- it ( 'Should have an initial filled style when data bound.' , fakeAsync ( ( ) => {
98+ it ( 'should have an initial filled style when data bound.' , fakeAsync ( ( ) => {
9999 const fixture = TestBed . createComponent ( InitiallyFilledInputComponent ) ;
100100 fixture . detectChanges ( ) ;
101101
@@ -127,7 +127,7 @@ describe('IgxInput', () => {
127127 expect ( filledDate . classList . contains ( INPUT_GROUP_FILLED_CSS_CLASS ) ) . toBe ( true ) ;
128128 } ) ) ;
129129
130- it ( 'Should have a filled style. Value API.' , ( ) => {
130+ it ( 'should have a filled style. Value API.' , ( ) => {
131131 const fixture = TestBed . createComponent ( FilledInputComponent ) ;
132132 fixture . detectChanges ( ) ;
133133
@@ -148,7 +148,7 @@ describe('IgxInput', () => {
148148 expect ( igxInput . value ) . toBe ( 'test' ) ;
149149 } ) ;
150150
151- it ( 'Should have a disabled style. Disabled API.' , ( ) => {
151+ it ( 'should have a disabled style. Disabled API.' , ( ) => {
152152 const fixture = TestBed . createComponent ( DisabledInputComponent ) ;
153153 fixture . detectChanges ( ) ;
154154
@@ -167,7 +167,7 @@ describe('IgxInput', () => {
167167 expect ( igxInput . disabled ) . toBe ( false ) ;
168168 } ) ;
169169
170- it ( 'Should have a disabled style via binding' , ( ) => {
170+ it ( 'should have a disabled style via binding' , ( ) => {
171171 const fixture = TestBed . createComponent ( DataBoundDisabledInputComponent ) ;
172172 fixture . detectChanges ( ) ;
173173
@@ -186,15 +186,15 @@ describe('IgxInput', () => {
186186 expect ( igxInput . disabled ) . toBe ( true ) ;
187187 } ) ;
188188
189- it ( 'Should style required input correctly.' , ( ) => {
189+ it ( 'should style required input correctly.' , ( ) => {
190190 const fixture = TestBed . createComponent ( RequiredInputComponent ) ;
191191 fixture . detectChanges ( ) ;
192192
193193 const inputElement = fixture . debugElement . query ( By . directive ( IgxInputDirective ) ) . nativeElement ;
194194 testRequiredValidation ( inputElement , fixture ) ;
195195 } ) ;
196196
197- it ( 'Should update style when required input\'s value is set.' , ( ) => {
197+ it ( 'should update style when required input\'s value is set.' , ( ) => {
198198 const fixture = TestBed . createComponent ( RequiredInputComponent ) ;
199199 fixture . detectChanges ( ) ;
200200
@@ -225,15 +225,15 @@ describe('IgxInput', () => {
225225 expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
226226 } ) ;
227227
228- it ( 'Should style required input with two-way databinding correctly.' , ( ) => {
228+ it ( 'should style required input with two-way databinding correctly.' , ( ) => {
229229 const fixture = TestBed . createComponent ( RequiredTwoWayDataBoundInputComponent ) ;
230230 fixture . detectChanges ( ) ;
231231
232232 const inputElement = fixture . debugElement . query ( By . directive ( IgxInputDirective ) ) . nativeElement ;
233233 testRequiredValidation ( inputElement , fixture ) ;
234234 } ) ;
235235
236- it ( 'Should work properly with reactive forms validation.' , ( ) => {
236+ it ( 'should work properly with reactive forms validation.' , ( ) => {
237237 const fixture = TestBed . createComponent ( ReactiveFormComponent ) ;
238238 fixture . detectChanges ( ) ;
239239
@@ -271,7 +271,7 @@ describe('IgxInput', () => {
271271 } ) ;
272272 } ) ) ;
273273
274- it ( 'When value is changed only via ngModel' , fakeAsync ( ( ) => {
274+ it ( 'should not draw input as invalid when updated through ngModel and input is pristine and untouched ' , fakeAsync ( ( ) => {
275275 const fix = TestBed . createComponent ( RequiredTwoWayDataBoundInputComponent ) ;
276276 fix . detectChanges ( ) ;
277277
@@ -293,10 +293,10 @@ describe('IgxInput', () => {
293293 fix . detectChanges ( ) ;
294294 tick ( ) ;
295295 fix . detectChanges ( ) ;
296- expect ( inputGroup . nativeElement . classList . contains ( 'igx-input-group--invalid' ) ) . toBe ( true ) ;
296+ expect ( inputGroup . nativeElement . classList . contains ( 'igx-input-group--invalid' ) ) . toBe ( false ) ;
297297 } ) ) ;
298298
299- it ( 'When value is changed via reactive form' , fakeAsync ( ( ) => {
299+ it ( 'should not draw input as invalid when value is changed via reactive form and input is pristine and untouched ' , ( ) => {
300300 const fix = TestBed . createComponent ( ReactiveFormComponent ) ;
301301 fix . detectChanges ( ) ;
302302
@@ -305,24 +305,196 @@ describe('IgxInput', () => {
305305
306306 fix . componentInstance . form . patchValue ( { str : 'test' } ) ;
307307 fix . detectChanges ( ) ;
308- tick ( ) ;
309- fix . detectChanges ( ) ;
310308 expect ( firstInputGroup . nativeElement . classList . contains ( 'igx-input-group--filled' ) ) . toBe ( true ) ;
311309
312310 fix . componentInstance . form . patchValue ( { str : undefined } ) ;
313311 fix . detectChanges ( ) ;
314- tick ( ) ;
315- fix . detectChanges ( ) ;
316312 expect ( firstInputGroup . nativeElement . classList . contains ( 'igx-input-group--invalid' ) ) . toBe ( false ) ;
317313
318314 fix . componentInstance . form . patchValue ( { str : '' } ) ;
319315 fix . detectChanges ( ) ;
316+ expect ( firstInputGroup . nativeElement . classList . contains ( 'igx-input-group--invalid' ) ) . toBe ( false ) ;
317+ } ) ;
318+
319+ it ( 'should correctly update state of input without model when updated trough code' , fakeAsync ( ( ) => {
320+ const fixture = TestBed . createComponent ( RequiredInputComponent ) ;
321+ fixture . detectChanges ( ) ;
322+
323+ const igxInput = fixture . componentInstance . igxInput ;
324+
325+ const inputGroupElement = fixture . debugElement . query ( By . css ( 'igx-input-group' ) ) . nativeElement ;
326+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
327+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
328+
329+ igxInput . value = 'test' ;
330+ fixture . detectChanges ( ) ;
331+
332+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
333+ expect ( igxInput . valid ) . toBe ( IgxInputState . VALID ) ;
334+
335+
336+ igxInput . value = '' ;
337+ fixture . detectChanges ( ) ;
338+
339+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
340+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
341+ } ) ) ;
342+
343+ it ( 'should correctly update state of input when updated through ngModel, no user interactions' , fakeAsync ( ( ) => {
344+ const fixture = TestBed . createComponent ( RequiredTwoWayDataBoundInputComponent ) ;
345+ fixture . detectChanges ( ) ;
346+
347+ const inputGroupElement = fixture . componentInstance . igxInputGroup . element . nativeElement ;
348+ const igxInput = fixture . componentInstance . igxInput ;
349+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
350+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
351+
352+ fixture . componentInstance . user . firstName = 'Bobby' ;
353+
354+ fixture . detectChanges ( ) ;
320355 tick ( ) ;
321- fix . detectChanges ( ) ;
322- expect ( firstInputGroup . nativeElement . classList . contains ( 'igx-input-group--invalid' ) ) . toBe ( true ) ;
356+ fixture . detectChanges ( ) ;
357+
358+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
359+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
360+
361+ igxInput . value = '' ;
362+ fixture . detectChanges ( ) ;
363+ tick ( ) ;
364+ fixture . detectChanges ( ) ;
365+
366+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
367+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
368+
369+ igxInput . value = undefined ;
370+ fixture . detectChanges ( ) ;
371+ tick ( ) ;
372+ fixture . detectChanges ( ) ;
373+
374+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
375+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
376+ } ) ) ;
377+
378+ it ( 'should correctly update state of input when value is changed via reactive, no user interactions' , fakeAsync ( ( ) => {
379+ const fixture = TestBed . createComponent ( ReactiveFormComponent ) ;
380+ fixture . detectChanges ( ) ;
381+
382+ const igxInputGroups = fixture . debugElement . queryAll ( By . css ( 'igx-input-group' ) ) ;
383+ const inputGroupElement = igxInputGroups [ 0 ] . nativeElement ;
384+ const igxInput = fixture . componentInstance . strIgxInput ;
385+
386+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
387+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
388+
389+ fixture . componentInstance . form . patchValue ( { str : 'Bobby' } ) ;
390+ fixture . detectChanges ( ) ;
391+
392+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
393+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
394+
395+ fixture . componentInstance . form . patchValue ( { str : '' } ) ;
396+ fixture . detectChanges ( ) ;
397+
398+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
399+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
400+
401+ fixture . componentInstance . form . patchValue ( { str : undefined } ) ;
402+ fixture . detectChanges ( ) ;
403+
404+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
405+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
406+
407+ fixture . componentInstance . form . reset ( ) ;
408+ fixture . detectChanges ( ) ;
409+
410+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
411+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
323412 } ) ) ;
324413
325- it ( 'Should style input when required is toggled dynamically.' , ( ) => {
414+ it ( 'should correctly update state of input when updated through ngModel, with user interactions' , fakeAsync ( ( ) => {
415+ const fixture = TestBed . createComponent ( RequiredTwoWayDataBoundInputComponent ) ;
416+ fixture . detectChanges ( ) ;
417+
418+ const inputGroupElement = fixture . componentInstance . igxInputGroup . element . nativeElement ;
419+ const igxInput = fixture . componentInstance . igxInput ;
420+ const inputElement = igxInput . nativeElement ;
421+
422+ dispatchInputEvent ( 'focus' , inputElement , fixture ) ;
423+ dispatchInputEvent ( 'blur' , inputElement , fixture ) ;
424+
425+ tick ( ) ;
426+ fixture . detectChanges ( ) ;
427+
428+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
429+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
430+
431+ fixture . componentInstance . user . firstName = 'Bobby' ;
432+
433+ fixture . detectChanges ( ) ;
434+ tick ( ) ;
435+ fixture . detectChanges ( ) ;
436+
437+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
438+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
439+
440+ fixture . componentInstance . user . firstName = '' ;
441+ fixture . detectChanges ( ) ;
442+ tick ( ) ;
443+ fixture . detectChanges ( ) ;
444+
445+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
446+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
447+
448+ fixture . componentInstance . user . firstName = undefined ;
449+ fixture . detectChanges ( ) ;
450+ tick ( ) ;
451+ fixture . detectChanges ( ) ;
452+
453+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
454+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
455+ } ) ) ;
456+
457+ it ( 'should correctly update state of input when value is changed via reactive, with user interactions' , fakeAsync ( ( ) => {
458+ const fixture = TestBed . createComponent ( ReactiveFormComponent ) ;
459+ fixture . detectChanges ( ) ;
460+
461+ const igxInputGroups = fixture . debugElement . queryAll ( By . css ( 'igx-input-group' ) ) ;
462+ const inputGroupElement = igxInputGroups [ 0 ] . nativeElement ;
463+ const igxInput = fixture . componentInstance . strIgxInput ;
464+ const input = igxInput . nativeElement ;
465+
466+ dispatchInputEvent ( 'focus' , input , fixture ) ;
467+ dispatchInputEvent ( 'blur' , input , fixture ) ;
468+
469+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
470+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
471+
472+ fixture . componentInstance . form . patchValue ( { str : 'Bobby' } ) ;
473+ fixture . detectChanges ( ) ;
474+
475+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
476+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
477+
478+ fixture . componentInstance . form . patchValue ( { str : '' } ) ;
479+ fixture . detectChanges ( ) ;
480+
481+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
482+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
483+
484+ fixture . componentInstance . form . patchValue ( { str : undefined } ) ;
485+ fixture . detectChanges ( ) ;
486+
487+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( true ) ;
488+ expect ( igxInput . valid ) . toBe ( IgxInputState . INVALID ) ;
489+
490+ fixture . componentInstance . form . reset ( ) ;
491+ fixture . detectChanges ( ) ;
492+
493+ expect ( inputGroupElement . classList . contains ( INPUT_GROUP_INVALID_CSS_CLASS ) ) . toBe ( false ) ;
494+ expect ( igxInput . valid ) . toBe ( IgxInputState . INITIAL ) ;
495+ } ) ) ;
496+
497+ it ( 'should style input when required is toggled dynamically.' , ( ) => {
326498 const fixture = TestBed . createComponent ( ToggleRequiredWithNgModelInputComponent ) ;
327499 fixture . detectChanges ( ) ;
328500
@@ -377,7 +549,7 @@ describe('IgxInput', () => {
377549 expect ( inputGroup . element . nativeElement . classList . contains ( INPUT_GROUP_VALID_CSS_CLASS ) ) . toBe ( false ) ;
378550 } ) ;
379551
380- it ( 'Should style input with ngModel when required is toggled dynamically.' , ( ) => {
552+ it ( 'should style input with ngModel when required is toggled dynamically.' , ( ) => {
381553 const fixture = TestBed . createComponent ( ToggleRequiredWithNgModelInputComponent ) ;
382554 fixture . detectChanges ( ) ;
383555
@@ -620,6 +792,8 @@ class DataBoundDisabledInputComponent {
620792 </form>`
621793} )
622794class ReactiveFormComponent {
795+ @ViewChild ( IgxInputDirective , { static : true } ) public strIgxInput : IgxInputDirective ;
796+
623797 form = this . fb . group ( {
624798 str : [ '' , Validators . required ] ,
625799 textarea : [ '' , Validators . required ] ,
0 commit comments