@@ -2,12 +2,12 @@ import {DOWN_ARROW, SPACE, UP_ARROW} from '@angular/cdk/keycodes';
2
2
import { Platform } from '@angular/cdk/platform' ;
3
3
import { createKeyboardEvent , dispatchFakeEvent } from '@angular/cdk/testing' ;
4
4
import { Component , DebugElement } from '@angular/core' ;
5
- import { async , ComponentFixture , inject , TestBed } from '@angular/core/testing' ;
5
+ import { async , ComponentFixture , fakeAsync , inject , TestBed , tick } from '@angular/core/testing' ;
6
6
import { By } from '@angular/platform-browser' ;
7
- import { MatListModule , MatListOption , MatSelectionList } from './index' ;
7
+ import { MatListModule , MatListOption , MatSelectionList , MatSelectionListChange } from './index' ;
8
+ import { FormControl , FormsModule , NgModel , ReactiveFormsModule } from '@angular/forms' ;
8
9
9
-
10
- describe ( 'MatSelectionList' , ( ) => {
10
+ describe ( 'MatSelectionList without forms' , ( ) => {
11
11
describe ( 'with list option' , ( ) => {
12
12
let fixture : ComponentFixture < SelectionListWithListOptions > ;
13
13
let listOptions : DebugElement [ ] ;
@@ -61,6 +61,28 @@ describe('MatSelectionList', () => {
61
61
} ) ;
62
62
} ) ;
63
63
64
+ it ( 'should not emit a change event if an option changed programmatically' , ( ) => {
65
+ spyOn ( fixture . componentInstance , 'onValueChange' ) ;
66
+
67
+ expect ( fixture . componentInstance . onValueChange ) . toHaveBeenCalledTimes ( 0 ) ;
68
+
69
+ listOptions [ 2 ] . componentInstance . toggle ( ) ;
70
+ fixture . detectChanges ( ) ;
71
+
72
+ expect ( fixture . componentInstance . onValueChange ) . toHaveBeenCalledTimes ( 0 ) ;
73
+ } ) ;
74
+
75
+ it ( 'should not emit a change event if an option got clicked' , ( ) => {
76
+ spyOn ( fixture . componentInstance , 'onValueChange' ) ;
77
+
78
+ expect ( fixture . componentInstance . onValueChange ) . toHaveBeenCalledTimes ( 0 ) ;
79
+
80
+ dispatchFakeEvent ( listOptions [ 2 ] . nativeElement , 'click' ) ;
81
+ fixture . detectChanges ( ) ;
82
+
83
+ expect ( fixture . componentInstance . onValueChange ) . toHaveBeenCalledTimes ( 1 ) ;
84
+ } ) ;
85
+
64
86
it ( 'should be able to dispatch one selected item' , ( ) => {
65
87
let testListItem = listOptions [ 2 ] . injector . get < MatListOption > ( MatListOption ) ;
66
88
let selectList =
@@ -442,9 +464,165 @@ describe('MatSelectionList', () => {
442
464
} ) ;
443
465
} ) ;
444
466
467
+ describe ( 'MatSelectionList with forms' , ( ) => {
468
+
469
+ beforeEach ( async ( ( ) => {
470
+ TestBed . configureTestingModule ( {
471
+ imports : [ MatListModule , FormsModule , ReactiveFormsModule ] ,
472
+ declarations : [
473
+ SelectionListWithModel ,
474
+ SelectionListWithFormControl
475
+ ]
476
+ } ) ;
477
+
478
+ TestBed . compileComponents ( ) ;
479
+ } ) ) ;
480
+
481
+ describe ( 'and ngModel' , ( ) => {
482
+ let fixture : ComponentFixture < SelectionListWithModel > ;
483
+ let selectionListDebug : DebugElement ;
484
+ let selectionList : MatSelectionList ;
485
+ let listOptions : MatListOption [ ] ;
486
+ let ngModel : NgModel ;
487
+
488
+ beforeEach ( ( ) => {
489
+ fixture = TestBed . createComponent ( SelectionListWithModel ) ;
490
+ fixture . detectChanges ( ) ;
491
+
492
+ selectionListDebug = fixture . debugElement . query ( By . directive ( MatSelectionList ) ) ;
493
+ selectionList = selectionListDebug . componentInstance ;
494
+ ngModel = selectionListDebug . injector . get < NgModel > ( NgModel ) ;
495
+ listOptions = fixture . debugElement . queryAll ( By . directive ( MatListOption ) )
496
+ . map ( optionDebugEl => optionDebugEl . componentInstance ) ;
497
+ } ) ;
498
+
499
+ it ( 'should update the model if an option got selected' , fakeAsync ( ( ) => {
500
+ expect ( fixture . componentInstance . selectedOptions . length )
501
+ . toBe ( 0 , 'Expected no options to be selected by default' ) ;
502
+
503
+ listOptions [ 0 ] . toggle ( ) ;
504
+ fixture . detectChanges ( ) ;
505
+
506
+ tick ( ) ;
507
+
508
+ expect ( fixture . componentInstance . selectedOptions . length )
509
+ . toBe ( 1 , 'Expected first list option to be selected' ) ;
510
+ } ) ) ;
511
+
512
+ it ( 'should update the model if an option got clicked' , fakeAsync ( ( ) => {
513
+ expect ( fixture . componentInstance . selectedOptions . length )
514
+ . toBe ( 0 , 'Expected no options to be selected by default' ) ;
515
+
516
+ dispatchFakeEvent ( listOptions [ 0 ] . _getHostElement ( ) , 'click' ) ;
517
+ fixture . detectChanges ( ) ;
518
+
519
+ tick ( ) ;
520
+
521
+ expect ( fixture . componentInstance . selectedOptions . length )
522
+ . toBe ( 1 , 'Expected first list option to be selected' ) ;
523
+ } ) ) ;
524
+
525
+ it ( 'should update the options if a model value is set' , fakeAsync ( ( ) => {
526
+ expect ( fixture . componentInstance . selectedOptions . length )
527
+ . toBe ( 0 , 'Expected no options to be selected by default' ) ;
528
+
529
+ fixture . componentInstance . selectedOptions = [ 'opt3' ] ;
530
+ fixture . detectChanges ( ) ;
531
+
532
+ tick ( ) ;
533
+
534
+ expect ( fixture . componentInstance . selectedOptions . length )
535
+ . toBe ( 1 , 'Expected first list option to be selected' ) ;
536
+ } ) ) ;
537
+
538
+ it ( 'should set the selection-list to touched on blur' , fakeAsync ( ( ) => {
539
+ expect ( ngModel . touched )
540
+ . toBe ( false , 'Expected the selection-list to be untouched by default.' ) ;
541
+
542
+ dispatchFakeEvent ( selectionListDebug . nativeElement , 'blur' ) ;
543
+ fixture . detectChanges ( ) ;
544
+
545
+ tick ( ) ;
546
+
547
+ expect ( ngModel . touched ) . toBe ( true , 'Expected the selection-list to be touched after blur' ) ;
548
+ } ) ) ;
549
+
550
+ it ( 'should be pristine by default' , fakeAsync ( ( ) => {
551
+ fixture = TestBed . createComponent ( SelectionListWithModel ) ;
552
+ fixture . componentInstance . selectedOptions = [ 'opt2' ] ;
553
+ fixture . detectChanges ( ) ;
554
+
555
+ ngModel =
556
+ fixture . debugElement . query ( By . directive ( MatSelectionList ) ) . injector . get < NgModel > ( NgModel ) ;
557
+ listOptions = fixture . debugElement . queryAll ( By . directive ( MatListOption ) )
558
+ . map ( optionDebugEl => optionDebugEl . componentInstance ) ;
559
+
560
+ // Flush the initial tick to ensure that every action from the ControlValueAccessor
561
+ // happened before the actual test starts.
562
+ tick ( ) ;
563
+
564
+ expect ( ngModel . pristine )
565
+ . toBe ( true , 'Expected the selection-list to be pristine by default.' ) ;
566
+
567
+ listOptions [ 1 ] . toggle ( ) ;
568
+ fixture . detectChanges ( ) ;
569
+
570
+ tick ( ) ;
571
+
572
+ expect ( ngModel . pristine )
573
+ . toBe ( false , 'Expected the selection-list to be dirty after state change.' ) ;
574
+ } ) ) ;
575
+ } ) ;
576
+
577
+ describe ( 'and formControl' , ( ) => {
578
+ let fixture : ComponentFixture < SelectionListWithFormControl > ;
579
+ let selectionListDebug : DebugElement ;
580
+ let selectionList : MatSelectionList ;
581
+ let listOptions : MatListOption [ ] ;
582
+
583
+ beforeEach ( ( ) => {
584
+ fixture = TestBed . createComponent ( SelectionListWithFormControl ) ;
585
+ fixture . detectChanges ( ) ;
586
+
587
+ selectionListDebug = fixture . debugElement . query ( By . directive ( MatSelectionList ) ) ;
588
+ selectionList = selectionListDebug . componentInstance ;
589
+ listOptions = fixture . debugElement . queryAll ( By . directive ( MatListOption ) )
590
+ . map ( optionDebugEl => optionDebugEl . componentInstance ) ;
591
+ } ) ;
592
+
593
+ it ( 'should be able to disable options from the control' , ( ) => {
594
+ expect ( listOptions . every ( option => ! option . disabled ) )
595
+ . toBe ( true , 'Expected every list option to be enabled.' ) ;
596
+
597
+ fixture . componentInstance . formControl . disable ( ) ;
598
+ fixture . detectChanges ( ) ;
599
+
600
+ expect ( listOptions . every ( option => option . disabled ) )
601
+ . toBe ( true , 'Expected every list option to be disabled.' ) ;
602
+ } ) ;
603
+
604
+ it ( 'should be able to set the value through the form control' , ( ) => {
605
+ expect ( listOptions . every ( option => ! option . selected ) )
606
+ . toBe ( true , 'Expected every list option to be unselected.' ) ;
607
+
608
+ fixture . componentInstance . formControl . setValue ( [ 'opt2' , 'opt3' ] ) ;
609
+ fixture . detectChanges ( ) ;
610
+
611
+ expect ( listOptions [ 1 ] . selected ) . toBe ( true , 'Expected option to be selected.' ) ;
612
+ expect ( listOptions [ 2 ] . selected ) . toBe ( true , 'Expected option to be selected.' ) ;
613
+
614
+ fixture . componentInstance . formControl . setValue ( null ) ;
615
+ fixture . detectChanges ( ) ;
616
+
617
+ expect ( listOptions . every ( option => ! option . selected ) )
618
+ . toBe ( true , 'Expected every list option to be unselected.' ) ;
619
+ } ) ;
620
+ } ) ;
621
+ } ) ;
622
+
445
623
446
624
@Component ( { template : `
447
- <mat-selection-list id="selection-list-1">
625
+ <mat-selection-list id="selection-list-1" (change)="onValueChange($event)" >
448
626
<mat-list-option checkboxPosition="before" disabled="true" value="inbox">
449
627
Inbox (disabled selection-option)
450
628
</mat-list-option>
@@ -461,20 +639,22 @@ describe('MatSelectionList', () => {
461
639
</mat-selection-list>` } )
462
640
class SelectionListWithListOptions {
463
641
showLastOption : boolean = true ;
642
+
643
+ onValueChange ( _change : MatSelectionListChange ) { }
464
644
}
465
645
466
646
@Component ( { template : `
467
- <mat-selection-list id = "selection-list-2">
468
- <mat-list-option checkboxPosition = "after">
647
+ <mat-selection-list id= "selection-list-2">
648
+ <mat-list-option checkboxPosition= "after">
469
649
Inbox (disabled selection-option)
470
650
</mat-list-option>
471
- <mat-list-option id = "testSelect" checkboxPosition = "after">
651
+ <mat-list-option id= "testSelect" checkboxPosition= "after">
472
652
Starred
473
653
</mat-list-option>
474
- <mat-list-option checkboxPosition = "after">
654
+ <mat-list-option checkboxPosition= "after">
475
655
Sent Mail
476
656
</mat-list-option>
477
- <mat-list-option checkboxPosition = "after">
657
+ <mat-list-option checkboxPosition= "after">
478
658
Drafts
479
659
</mat-list-option>
480
660
</mat-selection-list>` } )
@@ -523,3 +703,28 @@ class SelectionListWithSelectedOption {
523
703
</mat-selection-list>` } )
524
704
class SelectionListWithOnlyOneOption {
525
705
}
706
+
707
+ @Component ( {
708
+ template : `
709
+ <mat-selection-list [(ngModel)]="selectedOptions">
710
+ <mat-list-option value="opt1">Option 1</mat-list-option>
711
+ <mat-list-option value="opt2">Option 2</mat-list-option>
712
+ <mat-list-option value="opt3">Option 3</mat-list-option>
713
+ </mat-selection-list>`
714
+ } )
715
+ class SelectionListWithModel {
716
+ selectedOptions : string [ ] = [ ] ;
717
+ }
718
+
719
+ @Component ( {
720
+ template : `
721
+ <mat-selection-list [formControl]="formControl">
722
+ <mat-list-option value="opt1">Option 1</mat-list-option>
723
+ <mat-list-option value="opt2">Option 2</mat-list-option>
724
+ <mat-list-option value="opt3">Option 3</mat-list-option>
725
+ </mat-selection-list>
726
+ `
727
+ } )
728
+ class SelectionListWithFormControl {
729
+ formControl = new FormControl ( ) ;
730
+ }
0 commit comments