1
- import { async , TestBed } from '@angular/core/testing' ;
2
- import { Component , ViewChild } from '@angular/core' ;
1
+ import { async , TestBed , inject } from '@angular/core/testing' ;
2
+ import { Component , ViewChild , QueryList , ViewChildren } from '@angular/core' ;
3
3
import { By } from '@angular/platform-browser' ;
4
4
import { BrowserAnimationsModule } from '@angular/platform-browser/animations' ;
5
- import { MatExpansionModule , MatAccordion , MatExpansionPanel } from './index' ;
5
+ import {
6
+ MatExpansionModule ,
7
+ MatAccordion ,
8
+ MatExpansionPanel ,
9
+ MatExpansionPanelHeader ,
10
+ } from './index' ;
11
+ import { dispatchKeyboardEvent } from '@angular/cdk/testing' ;
12
+ import { DOWN_ARROW , UP_ARROW , HOME , END } from '@angular/cdk/keycodes' ;
13
+ import { FocusMonitor } from '@angular/cdk/a11y' ;
6
14
7
15
8
16
describe ( 'MatAccordion' , ( ) => {
17
+ let focusMonitor : FocusMonitor ;
18
+
9
19
beforeEach ( async ( ( ) => {
10
20
TestBed . configureTestingModule ( {
11
21
imports : [
@@ -18,41 +28,53 @@ describe('MatAccordion', () => {
18
28
] ,
19
29
} ) ;
20
30
TestBed . compileComponents ( ) ;
31
+
32
+ inject ( [ FocusMonitor ] , ( fm : FocusMonitor ) => {
33
+ focusMonitor = fm ;
34
+ } ) ( ) ;
21
35
} ) ) ;
22
36
23
37
it ( 'should ensure only one item is expanded at a time' , ( ) => {
24
38
const fixture = TestBed . createComponent ( SetOfItems ) ;
39
+ fixture . detectChanges ( ) ;
40
+
25
41
const items = fixture . debugElement . queryAll ( By . css ( '.mat-expansion-panel' ) ) ;
42
+ const panelInstances = fixture . componentInstance . panels . toArray ( ) ;
26
43
27
- fixture . componentInstance . firstPanelExpanded = true ;
44
+ panelInstances [ 0 ] . expanded = true ;
28
45
fixture . detectChanges ( ) ;
29
46
expect ( items [ 0 ] . classes [ 'mat-expanded' ] ) . toBeTruthy ( ) ;
30
47
expect ( items [ 1 ] . classes [ 'mat-expanded' ] ) . toBeFalsy ( ) ;
31
48
32
- fixture . componentInstance . secondPanelExpanded = true ;
49
+ panelInstances [ 1 ] . expanded = true ;
33
50
fixture . detectChanges ( ) ;
34
51
expect ( items [ 0 ] . classes [ 'mat-expanded' ] ) . toBeFalsy ( ) ;
35
52
expect ( items [ 1 ] . classes [ 'mat-expanded' ] ) . toBeTruthy ( ) ;
36
53
} ) ;
37
54
38
55
it ( 'should allow multiple items to be expanded simultaneously' , ( ) => {
39
56
const fixture = TestBed . createComponent ( SetOfItems ) ;
57
+ fixture . componentInstance . multi = true ;
58
+ fixture . detectChanges ( ) ;
59
+
40
60
const panels = fixture . debugElement . queryAll ( By . css ( '.mat-expansion-panel' ) ) ;
61
+ const panelInstances = fixture . componentInstance . panels . toArray ( ) ;
41
62
42
- fixture . componentInstance . multi = true ;
43
- fixture . componentInstance . firstPanelExpanded = true ;
44
- fixture . componentInstance . secondPanelExpanded = true ;
63
+ panelInstances [ 0 ] . expanded = true ;
64
+ panelInstances [ 1 ] . expanded = true ;
45
65
fixture . detectChanges ( ) ;
46
66
expect ( panels [ 0 ] . classes [ 'mat-expanded' ] ) . toBeTruthy ( ) ;
47
67
expect ( panels [ 1 ] . classes [ 'mat-expanded' ] ) . toBeTruthy ( ) ;
48
68
} ) ;
49
69
50
70
it ( 'should expand or collapse all enabled items' , ( ) => {
51
71
const fixture = TestBed . createComponent ( SetOfItems ) ;
72
+ fixture . detectChanges ( ) ;
73
+
52
74
const panels = fixture . debugElement . queryAll ( By . css ( '.mat-expansion-panel' ) ) ;
53
75
54
76
fixture . componentInstance . multi = true ;
55
- fixture . componentInstance . secondPanelExpanded = true ;
77
+ fixture . componentInstance . panels . toArray ( ) [ 1 ] . expanded = true ;
56
78
fixture . detectChanges ( ) ;
57
79
expect ( panels [ 0 ] . classes [ 'mat-expanded' ] ) . toBeFalsy ( ) ;
58
80
expect ( panels [ 1 ] . classes [ 'mat-expanded' ] ) . toBeTruthy ( ) ;
@@ -70,10 +92,12 @@ describe('MatAccordion', () => {
70
92
71
93
it ( 'should not expand or collapse disabled items' , ( ) => {
72
94
const fixture = TestBed . createComponent ( SetOfItems ) ;
95
+ fixture . detectChanges ( ) ;
96
+
73
97
const panels = fixture . debugElement . queryAll ( By . css ( '.mat-expansion-panel' ) ) ;
74
98
75
99
fixture . componentInstance . multi = true ;
76
- fixture . componentInstance . secondPanelDisabled = true ;
100
+ fixture . componentInstance . panels . toArray ( ) [ 1 ] . disabled = true ;
77
101
fixture . detectChanges ( ) ;
78
102
fixture . componentInstance . accordion . openAll ( ) ;
79
103
fixture . detectChanges ( ) ;
@@ -93,27 +117,107 @@ describe('MatAccordion', () => {
93
117
94
118
expect ( innerPanel . accordion ) . not . toBe ( outerPanel . accordion ) ;
95
119
} ) ;
120
+
121
+ it ( 'should move focus to the next header when pressing the down arrow' , ( ) => {
122
+ const fixture = TestBed . createComponent ( SetOfItems ) ;
123
+ fixture . detectChanges ( ) ;
124
+
125
+ const headerElements = fixture . debugElement . queryAll ( By . css ( 'mat-expansion-panel-header' ) ) ;
126
+ const headers = fixture . componentInstance . headers . toArray ( ) ;
127
+
128
+ focusMonitor . focusVia ( headerElements [ 0 ] . nativeElement , 'keyboard' ) ;
129
+ headers . forEach ( header => spyOn ( header , 'focus' ) ) ;
130
+
131
+ // Stop at the second-last header so focus doesn't wrap around.
132
+ for ( let i = 0 ; i < headerElements . length - 1 ; i ++ ) {
133
+ dispatchKeyboardEvent ( headerElements [ i ] . nativeElement , 'keydown' , DOWN_ARROW ) ;
134
+ fixture . detectChanges ( ) ;
135
+ expect ( headers [ i + 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
136
+ }
137
+ } ) ;
138
+
139
+ it ( 'should move focus to the next header when pressing the up arrow' , ( ) => {
140
+ const fixture = TestBed . createComponent ( SetOfItems ) ;
141
+ fixture . detectChanges ( ) ;
142
+
143
+ const headerElements = fixture . debugElement . queryAll ( By . css ( 'mat-expansion-panel-header' ) ) ;
144
+ const headers = fixture . componentInstance . headers . toArray ( ) ;
145
+
146
+ focusMonitor . focusVia ( headerElements [ headerElements . length - 1 ] . nativeElement , 'keyboard' ) ;
147
+ headers . forEach ( header => spyOn ( header , 'focus' ) ) ;
148
+
149
+ // Stop before the first header
150
+ for ( let i = headers . length - 1 ; i > 0 ; i -- ) {
151
+ dispatchKeyboardEvent ( headerElements [ i ] . nativeElement , 'keydown' , UP_ARROW ) ;
152
+ fixture . detectChanges ( ) ;
153
+ expect ( headers [ i - 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
154
+ }
155
+ } ) ;
156
+
157
+ it ( 'should skip disabled items when moving focus with the keyboard' , ( ) => {
158
+ const fixture = TestBed . createComponent ( SetOfItems ) ;
159
+ fixture . detectChanges ( ) ;
160
+
161
+ const headerElements = fixture . debugElement . queryAll ( By . css ( 'mat-expansion-panel-header' ) ) ;
162
+ const panels = fixture . componentInstance . panels . toArray ( ) ;
163
+ const headers = fixture . componentInstance . headers . toArray ( ) ;
164
+
165
+ focusMonitor . focusVia ( headerElements [ 0 ] . nativeElement , 'keyboard' ) ;
166
+ headers . forEach ( header => spyOn ( header , 'focus' ) ) ;
167
+ panels [ 1 ] . disabled = true ;
168
+ fixture . detectChanges ( ) ;
169
+
170
+ dispatchKeyboardEvent ( headerElements [ 0 ] . nativeElement , 'keydown' , DOWN_ARROW ) ;
171
+ fixture . detectChanges ( ) ;
172
+
173
+ expect ( headers [ 1 ] . focus ) . not . toHaveBeenCalled ( ) ;
174
+ expect ( headers [ 2 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
175
+ } ) ;
176
+
177
+ it ( 'should focus the first header when pressing the home key' , ( ) => {
178
+ const fixture = TestBed . createComponent ( SetOfItems ) ;
179
+ fixture . detectChanges ( ) ;
180
+
181
+ const headerElements = fixture . debugElement . queryAll ( By . css ( 'mat-expansion-panel-header' ) ) ;
182
+ const headers = fixture . componentInstance . headers . toArray ( ) ;
183
+
184
+ headers . forEach ( header => spyOn ( header , 'focus' ) ) ;
185
+ dispatchKeyboardEvent ( headerElements [ headerElements . length - 1 ] . nativeElement , 'keydown' , HOME ) ;
186
+ fixture . detectChanges ( ) ;
187
+
188
+ expect ( headers [ 0 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
189
+ } ) ;
190
+
191
+ it ( 'should focus the last header when pressing the end key' , ( ) => {
192
+ const fixture = TestBed . createComponent ( SetOfItems ) ;
193
+ fixture . detectChanges ( ) ;
194
+
195
+ const headerElements = fixture . debugElement . queryAll ( By . css ( 'mat-expansion-panel-header' ) ) ;
196
+ const headers = fixture . componentInstance . headers . toArray ( ) ;
197
+
198
+ headers . forEach ( header => spyOn ( header , 'focus' ) ) ;
199
+ dispatchKeyboardEvent ( headerElements [ 0 ] . nativeElement , 'keydown' , END ) ;
200
+ fixture . detectChanges ( ) ;
201
+
202
+ expect ( headers [ headers . length - 1 ] . focus ) . toHaveBeenCalledTimes ( 1 ) ;
203
+ } ) ;
204
+
96
205
} ) ;
97
206
98
207
99
208
@Component ( { template : `
100
209
<mat-accordion [multi]="multi">
101
- <mat-expansion-panel [expanded]="firstPanelExpanded">
102
- <mat-expansion-panel-header>Summary</mat-expansion-panel-header>
103
- <p>Content</p>
104
- </mat-expansion-panel>
105
- <mat-expansion-panel [expanded]="secondPanelExpanded" [disabled]="secondPanelDisabled">
106
- <mat-expansion-panel-header>Summary</mat-expansion-panel-header>
210
+ <mat-expansion-panel *ngFor="let i of [0, 1, 2, 3]">
211
+ <mat-expansion-panel-header>Summary {{i}}</mat-expansion-panel-header>
107
212
<p>Content</p>
108
213
</mat-expansion-panel>
109
214
</mat-accordion>` } )
110
215
class SetOfItems {
111
216
@ViewChild ( MatAccordion ) accordion : MatAccordion ;
217
+ @ViewChildren ( MatExpansionPanel ) panels : QueryList < MatExpansionPanel > ;
218
+ @ViewChildren ( MatExpansionPanelHeader ) headers : QueryList < MatExpansionPanelHeader > ;
112
219
113
220
multi : boolean = false ;
114
- firstPanelExpanded : boolean = false ;
115
- secondPanelExpanded : boolean = false ;
116
- secondPanelDisabled : boolean = false ;
117
221
}
118
222
119
223
@Component ( { template : `
0 commit comments