1
+ import { CommonModule } from '@angular/common' ;
1
2
import { fakeAsync , flush } from '@angular/core/testing' ;
2
3
import { IconType } from '@hypertrace/assets-library' ;
3
- import { SearchBoxComponent } from '@hypertrace/components ' ;
4
- import { createHostFactory , SpectatorHost } from '@ngneat/spectator/jest' ;
4
+ import { NavigationService } from '@hypertrace/common ' ;
5
+ import { createHostFactory , mockProvider , SpectatorHost } from '@ngneat/spectator/jest' ;
5
6
import { MockComponent } from 'ng-mocks' ;
7
+ import { NEVER } from 'rxjs' ;
8
+ import { ButtonComponent } from '../button/button.component' ;
6
9
import { DividerComponent } from '../divider/divider.component' ;
7
10
import { LabelComponent } from '../label/label.component' ;
8
- import { LetAsyncModule } from '../let-async/let-async.module' ;
11
+ import { PopoverComponent } from '../popover/popover.component' ;
12
+ import { PopoverModule } from '../popover/popover.module' ;
13
+ import { SearchBoxComponent } from '../search-box/search-box.component' ;
9
14
import { SelectOptionComponent } from '../select/select-option.component' ;
10
15
import { MultiSelectJustify } from './multi-select-justify' ;
11
16
import { MultiSelectComponent , TriggerLabelDisplayMode } from './multi-select.component' ;
12
17
13
18
describe ( 'Multi Select Component' , ( ) => {
14
19
const hostFactory = createHostFactory < MultiSelectComponent < string > > ( {
15
20
component : MultiSelectComponent ,
16
- imports : [ LetAsyncModule ] ,
17
- entryComponents : [ SelectOptionComponent ] ,
18
- declarations : [ MockComponent ( LabelComponent ) , MockComponent ( DividerComponent ) , MockComponent ( SearchBoxComponent ) ] ,
21
+ imports : [ PopoverModule , CommonModule ] ,
22
+ providers : [
23
+ mockProvider ( NavigationService , {
24
+ navigation$ : NEVER
25
+ } )
26
+ ] ,
27
+ declarations : [
28
+ SelectOptionComponent ,
29
+ MockComponent ( LabelComponent ) ,
30
+ MockComponent ( DividerComponent ) ,
31
+ MockComponent ( SearchBoxComponent ) ,
32
+ MockComponent ( ButtonComponent )
33
+ ] ,
19
34
shallow : true
20
35
} ) ;
21
36
@@ -24,27 +39,50 @@ describe('Multi Select Component', () => {
24
39
const selectionOptions = [
25
40
{ label : 'first' , value : 'first-value' } ,
26
41
{ label : 'second' , value : 'second-value' } ,
27
- { label : 'third' , value : 'third-value' }
42
+ { label : 'third' , value : 'third-value' } ,
43
+ { label : 'fourth' , value : 'fourth-value' } ,
44
+ { label : 'fifth' , value : 'fifth-value' } ,
45
+ { label : 'sixth' , value : 'sixth-value' }
28
46
] ;
29
47
30
48
test ( 'should display initial selections' , fakeAsync ( ( ) => {
31
49
spectator = hostFactory (
32
50
`
33
- <ht-multi-select [selected]="selected">
51
+ <ht-multi-select [selected]="selected" [triggerLabelDisplayMode]="triggerLabelDisplayMode" [enableSearch]="true" >
34
52
<ht-select-option *ngFor="let option of options" [label]="option.label" [value]="option.value">
35
53
</ht-select-option>
36
54
</ht-multi-select>` ,
37
55
{
38
56
hostProps : {
39
57
options : selectionOptions ,
40
- selected : [ selectionOptions [ 1 ] . value ]
58
+ selected : [ selectionOptions [ 1 ] . value ] ,
59
+ triggerLabelDisplayMode : TriggerLabelDisplayMode . Selection
41
60
}
42
61
}
43
62
) ;
63
+
44
64
spectator . tick ( ) ;
45
65
66
+ expect ( spectator . component . triggerLabel ) . toEqual ( selectionOptions [ 1 ] . label ) ;
67
+ expect ( spectator . query ( '.trigger-content' ) ) . toExist ( ) ;
68
+ expect ( spectator . query ( '.trigger-label-container' ) ) . toExist ( ) ;
69
+ expect ( spectator . query ( '.trigger-label' ) ) . toExist ( ) ;
70
+ expect ( spectator . query ( '.trigger-icon' ) ) . toExist ( ) ;
71
+
72
+ const popoverComponent = spectator . query ( PopoverComponent ) ;
73
+ expect ( popoverComponent ?. closeOnClick ) . toEqual ( false ) ;
74
+ expect ( popoverComponent ?. closeOnNavigate ) . toEqual ( true ) ;
75
+
46
76
spectator . click ( '.trigger-content' ) ;
47
- expect ( spectator . element ) . toHaveText ( selectionOptions [ 1 ] . label ) ;
77
+
78
+ expect ( spectator . query ( '.multi-select-content' , { root : true } ) ) . toExist ( ) ;
79
+ expect ( spectator . query ( '.multi-select-content .search-bar' , { root : true } ) ) . toExist ( ) ;
80
+ expect ( spectator . query ( '.multi-select-content .multi-select-option' , { root : true } ) ) . toExist ( ) ;
81
+
82
+ expect ( spectator . query ( '.multi-select-content' , { root : true } ) ) . toExist ( ) ;
83
+ const optionElements = spectator . queryAll ( '.multi-select-option' , { root : true } ) ;
84
+
85
+ expect ( optionElements . length ) . toEqual ( 6 ) ;
48
86
49
87
spectator . setHostInput ( {
50
88
selected : [ selectionOptions [ 1 ] . value , selectionOptions [ 2 ] . value ]
@@ -79,7 +117,7 @@ describe('Multi Select Component', () => {
79
117
spectator . click ( '.trigger-content' ) ;
80
118
const optionElements = spectator . queryAll ( '.multi-select-option:not(.all-options)' , { root : true } ) ;
81
119
expect ( spectator . query ( '.multi-select-content' , { root : true } ) ) . toExist ( ) ;
82
- expect ( optionElements . length ) . toBe ( 3 ) ;
120
+ expect ( optionElements . length ) . toBe ( 6 ) ;
83
121
84
122
const selectedElements = spectator . queryAll ( 'input:checked' , { root : true } ) ;
85
123
expect ( selectedElements . length ) . toBe ( 2 ) ;
@@ -144,12 +182,12 @@ describe('Multi Select Component', () => {
144
182
flush ( ) ;
145
183
} ) ) ;
146
184
147
- test ( 'should notify and update selection when all checkbox is selected' , fakeAsync ( ( ) => {
185
+ test ( 'should show select all and clear selected buttons ' , fakeAsync ( ( ) => {
148
186
const onChange = jest . fn ( ) ;
149
187
150
188
spectator = hostFactory (
151
189
`
152
- <ht-multi-select [selected]="selected" (selectedChange)="onChange($event)" [placeholder]="placeholder" [showAllOptionControl ]="showAllOptionControl ">
190
+ <ht-multi-select [selected]="selected" (selectedChange)="onChange($event)" [placeholder]="placeholder" [enableSearch ]="enableSearch ">
153
191
<ht-select-option *ngFor="let option of options" [label]="option.label" [value]="option.value">
154
192
</ht-select-option>
155
193
</ht-multi-select>` ,
@@ -158,7 +196,7 @@ describe('Multi Select Component', () => {
158
196
options : selectionOptions ,
159
197
selected : [ selectionOptions [ 1 ] . value ] ,
160
198
placeholder : 'Select options' ,
161
- showAllOptionControl : true ,
199
+ enableSearch : true ,
162
200
onChange : onChange
163
201
}
164
202
}
@@ -167,19 +205,39 @@ describe('Multi Select Component', () => {
167
205
spectator . tick ( ) ;
168
206
spectator . click ( '.trigger-content' ) ;
169
207
170
- const allOptionElement = spectator . query ( '.all-options' , { root : true } ) ;
208
+ expect ( spectator . query ( '.search-bar' , { root : true } ) ) . toExist ( ) ;
209
+ expect ( spectator . query ( '.divider' , { root : true } ) ) . toExist ( ) ;
210
+
211
+ expect ( spectator . component . isAnyOptionSelected ( ) ) . toEqual ( true ) ;
212
+ const clearSelectedButton = spectator . query ( '.clear-selected' , { root : true } ) ;
213
+ expect ( clearSelectedButton ) . toExist ( ) ;
214
+ spectator . click ( clearSelectedButton ! ) ;
215
+
216
+ spectator . tick ( ) ;
217
+ expect ( spectator . queryAll ( 'input:checked' , { root : true } ) . length ) . toBe ( 0 ) ;
218
+ expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
219
+ expect ( onChange ) . toHaveBeenLastCalledWith ( [ ] ) ;
220
+ expect ( spectator . query ( LabelComponent ) ?. label ) . toEqual ( 'Select options' ) ;
221
+
222
+ const allOptionElement = spectator . query ( '.select-all' , { root : true } ) ;
171
223
expect ( allOptionElement ) . toExist ( ) ;
172
224
spectator . click ( allOptionElement ! ) ;
173
225
174
- expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
226
+ spectator . tick ( ) ;
227
+ const selectedElements = spectator . queryAll ( 'input:checked' , { root : true } ) ;
228
+ expect ( selectedElements . length ) . toBe ( 6 ) ;
229
+
175
230
expect ( onChange ) . toHaveBeenCalledWith ( selectionOptions . map ( option => option . value ) ) ;
176
- expect ( spectator . query ( LabelComponent ) ?. label ) . toEqual ( 'first and 2 more' ) ;
231
+ expect ( spectator . query ( LabelComponent ) ?. label ) . toEqual ( 'first and 5 more' ) ;
177
232
178
- // De select all
179
- spectator . click ( allOptionElement ! ) ;
180
- expect ( onChange ) . toHaveBeenCalledTimes ( 2 ) ;
181
- expect ( onChange ) . toHaveBeenLastCalledWith ( [ ] ) ;
182
- expect ( spectator . query ( LabelComponent ) ?. label ) . toEqual ( 'Select options' ) ;
233
+ spectator . setHostInput ( {
234
+ enableSearch : false
235
+ } ) ;
236
+
237
+ expect ( spectator . query ( '.search-bar' , { root : true } ) ) . not . toExist ( ) ;
238
+ expect ( spectator . query ( '.divider' , { root : true } ) ) . not . toExist ( ) ;
239
+ expect ( spectator . query ( '.clear-selected' , { root : true } ) ) . not . toExist ( ) ;
240
+ expect ( spectator . query ( '.select-all' , { root : true } ) ) . not . toExist ( ) ;
183
241
184
242
flush ( ) ;
185
243
} ) ) ;
@@ -234,21 +292,23 @@ describe('Multi Select Component', () => {
234
292
) ;
235
293
spectator . tick ( ) ;
236
294
237
- expect ( spectator . element ) . toHaveText ( selectionOptions [ 1 ] . label ) ;
295
+ expect ( spectator . component . triggerLabel ) . toEqual ( selectionOptions [ 1 ] . label ) ;
296
+ expect ( spectator . query ( '.trigger-content' ) ) . toExist ( ) ;
297
+ expect ( spectator . query ( '.trigger-label-container' ) ) . toExist ( ) ;
298
+ expect ( spectator . query ( '.trigger-label' ) ) . toExist ( ) ;
299
+ expect ( spectator . query ( '.trigger-icon' ) ) . toExist ( ) ;
238
300
expect ( spectator . query ( '.trigger-content' ) ! . getAttribute ( 'style' ) ) . toBe ( 'justify-content: flex-start;' ) ;
239
301
240
302
spectator . setInput ( {
241
303
justify : MultiSelectJustify . Center
242
304
} ) ;
243
305
244
- expect ( spectator . element ) . toHaveText ( selectionOptions [ 1 ] . label ) ;
245
306
expect ( spectator . query ( '.trigger-content' ) ! . getAttribute ( 'style' ) ) . toBe ( 'justify-content: center;' ) ;
246
307
247
308
spectator . setInput ( {
248
309
justify : MultiSelectJustify . Right
249
310
} ) ;
250
311
251
- expect ( spectator . element ) . toHaveText ( selectionOptions [ 1 ] . label ) ;
252
312
expect ( spectator . query ( '.trigger-content' ) ! . getAttribute ( 'style' ) ) . toBe ( 'justify-content: flex-end;' ) ;
253
313
} ) ) ;
254
314
@@ -267,24 +327,39 @@ describe('Multi Select Component', () => {
267
327
}
268
328
) ;
269
329
270
- spectator . tick ( ) ;
271
- expect ( spectator . query ( '.search-bar' ) ) . toExist ( ) ;
272
- spectator . click ( '.search-bar' ) ;
330
+ spectator . click ( '.trigger-content' ) ;
331
+
332
+ const searchBar = spectator . query ( '.search-bar' , { root : true } ) ;
333
+ expect ( searchBar ) . toExist ( ) ;
273
334
274
- spectator . triggerEventHandler ( SearchBoxComponent , 'valueChange' , 'fi' ) ;
335
+ spectator . component . searchOptions ( 'fi' ) ;
275
336
spectator . tick ( ) ;
276
337
277
338
let options = spectator . queryAll ( '.multi-select-option' , { root : true } ) ;
278
- expect ( options . length ) . toBe ( 1 ) ;
339
+ expect ( options . length ) . toBe ( 2 ) ;
279
340
expect ( options [ 0 ] ) . toContainText ( 'first' ) ;
280
341
281
- spectator . triggerEventHandler ( SearchBoxComponent , 'valueChange' , 'i' ) ;
342
+ spectator . component . searchOptions ( 'i' ) ;
282
343
spectator . tick ( ) ;
283
344
284
345
options = spectator . queryAll ( '.multi-select-option' , { root : true } ) ;
285
- expect ( options . length ) . toBe ( 2 ) ;
346
+ expect ( options . length ) . toBe ( 4 ) ;
286
347
expect ( options [ 0 ] ) . toContainText ( 'first' ) ;
287
348
expect ( options [ 1 ] ) . toContainText ( 'third' ) ;
349
+
350
+ expect ( spectator . query ( '.divider' , { root : true } ) ) . toExist ( ) ;
351
+ expect ( spectator . query ( '.clear-selected' , { root : true } ) ) . not . toExist ( ) ; // Due to initial selection
352
+ expect ( spectator . query ( '.select-all' , { root : true } ) ) . toExist ( ) ;
353
+
354
+ // Set selected options to less than 5 and search box and buttons should hide
355
+ spectator . setHostInput ( {
356
+ options : selectionOptions . slice ( 0 , 3 )
357
+ } ) ;
358
+
359
+ expect ( spectator . query ( '.search-bar' , { root : true } ) ) . not . toExist ( ) ;
360
+ expect ( spectator . query ( '.divider' , { root : true } ) ) . not . toExist ( ) ;
361
+ expect ( spectator . query ( '.clear-selected' , { root : true } ) ) . not . toExist ( ) ;
362
+ expect ( spectator . query ( '.select-all' , { root : true } ) ) . not . toExist ( ) ;
288
363
flush ( ) ;
289
364
} ) ) ;
290
365
} ) ;
0 commit comments