1+ import { CommonModule } from '@angular/common' ;
12import { fakeAsync , flush } from '@angular/core/testing' ;
23import { 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' ;
56import { MockComponent } from 'ng-mocks' ;
7+ import { NEVER } from 'rxjs' ;
8+ import { ButtonComponent } from '../button/button.component' ;
69import { DividerComponent } from '../divider/divider.component' ;
710import { 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' ;
914import { SelectOptionComponent } from '../select/select-option.component' ;
1015import { MultiSelectJustify } from './multi-select-justify' ;
1116import { MultiSelectComponent , TriggerLabelDisplayMode } from './multi-select.component' ;
1217
1318describe ( 'Multi Select Component' , ( ) => {
1419 const hostFactory = createHostFactory < MultiSelectComponent < string > > ( {
1520 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+ ] ,
1934 shallow : true
2035 } ) ;
2136
@@ -24,27 +39,50 @@ describe('Multi Select Component', () => {
2439 const selectionOptions = [
2540 { label : 'first' , value : 'first-value' } ,
2641 { 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' }
2846 ] ;
2947
3048 test ( 'should display initial selections' , fakeAsync ( ( ) => {
3149 spectator = hostFactory (
3250 `
33- <ht-multi-select [selected]="selected">
51+ <ht-multi-select [selected]="selected" [triggerLabelDisplayMode]="triggerLabelDisplayMode" [enableSearch]="true" >
3452 <ht-select-option *ngFor="let option of options" [label]="option.label" [value]="option.value">
3553 </ht-select-option>
3654 </ht-multi-select>` ,
3755 {
3856 hostProps : {
3957 options : selectionOptions ,
40- selected : [ selectionOptions [ 1 ] . value ]
58+ selected : [ selectionOptions [ 1 ] . value ] ,
59+ triggerLabelDisplayMode : TriggerLabelDisplayMode . Selection
4160 }
4261 }
4362 ) ;
63+
4464 spectator . tick ( ) ;
4565
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+
4676 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 ) ;
4886
4987 spectator . setHostInput ( {
5088 selected : [ selectionOptions [ 1 ] . value , selectionOptions [ 2 ] . value ]
@@ -79,7 +117,7 @@ describe('Multi Select Component', () => {
79117 spectator . click ( '.trigger-content' ) ;
80118 const optionElements = spectator . queryAll ( '.multi-select-option:not(.all-options)' , { root : true } ) ;
81119 expect ( spectator . query ( '.multi-select-content' , { root : true } ) ) . toExist ( ) ;
82- expect ( optionElements . length ) . toBe ( 3 ) ;
120+ expect ( optionElements . length ) . toBe ( 6 ) ;
83121
84122 const selectedElements = spectator . queryAll ( 'input:checked' , { root : true } ) ;
85123 expect ( selectedElements . length ) . toBe ( 2 ) ;
@@ -144,12 +182,12 @@ describe('Multi Select Component', () => {
144182 flush ( ) ;
145183 } ) ) ;
146184
147- test ( 'should notify and update selection when all checkbox is selected' , fakeAsync ( ( ) => {
185+ test ( 'should show select all and clear selected buttons ' , fakeAsync ( ( ) => {
148186 const onChange = jest . fn ( ) ;
149187
150188 spectator = hostFactory (
151189 `
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 ">
153191 <ht-select-option *ngFor="let option of options" [label]="option.label" [value]="option.value">
154192 </ht-select-option>
155193 </ht-multi-select>` ,
@@ -158,7 +196,7 @@ describe('Multi Select Component', () => {
158196 options : selectionOptions ,
159197 selected : [ selectionOptions [ 1 ] . value ] ,
160198 placeholder : 'Select options' ,
161- showAllOptionControl : true ,
199+ enableSearch : true ,
162200 onChange : onChange
163201 }
164202 }
@@ -167,19 +205,39 @@ describe('Multi Select Component', () => {
167205 spectator . tick ( ) ;
168206 spectator . click ( '.trigger-content' ) ;
169207
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 } ) ;
171223 expect ( allOptionElement ) . toExist ( ) ;
172224 spectator . click ( allOptionElement ! ) ;
173225
174- expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
226+ spectator . tick ( ) ;
227+ const selectedElements = spectator . queryAll ( 'input:checked' , { root : true } ) ;
228+ expect ( selectedElements . length ) . toBe ( 6 ) ;
229+
175230 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' ) ;
177232
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 ( ) ;
183241
184242 flush ( ) ;
185243 } ) ) ;
@@ -234,21 +292,23 @@ describe('Multi Select Component', () => {
234292 ) ;
235293 spectator . tick ( ) ;
236294
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 ( ) ;
238300 expect ( spectator . query ( '.trigger-content' ) ! . getAttribute ( 'style' ) ) . toBe ( 'justify-content: flex-start;' ) ;
239301
240302 spectator . setInput ( {
241303 justify : MultiSelectJustify . Center
242304 } ) ;
243305
244- expect ( spectator . element ) . toHaveText ( selectionOptions [ 1 ] . label ) ;
245306 expect ( spectator . query ( '.trigger-content' ) ! . getAttribute ( 'style' ) ) . toBe ( 'justify-content: center;' ) ;
246307
247308 spectator . setInput ( {
248309 justify : MultiSelectJustify . Right
249310 } ) ;
250311
251- expect ( spectator . element ) . toHaveText ( selectionOptions [ 1 ] . label ) ;
252312 expect ( spectator . query ( '.trigger-content' ) ! . getAttribute ( 'style' ) ) . toBe ( 'justify-content: flex-end;' ) ;
253313 } ) ) ;
254314
@@ -267,24 +327,39 @@ describe('Multi Select Component', () => {
267327 }
268328 ) ;
269329
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 ( ) ;
273334
274- spectator . triggerEventHandler ( SearchBoxComponent , 'valueChange' , 'fi' ) ;
335+ spectator . component . searchOptions ( 'fi' ) ;
275336 spectator . tick ( ) ;
276337
277338 let options = spectator . queryAll ( '.multi-select-option' , { root : true } ) ;
278- expect ( options . length ) . toBe ( 1 ) ;
339+ expect ( options . length ) . toBe ( 2 ) ;
279340 expect ( options [ 0 ] ) . toContainText ( 'first' ) ;
280341
281- spectator . triggerEventHandler ( SearchBoxComponent , 'valueChange' , 'i' ) ;
342+ spectator . component . searchOptions ( 'i' ) ;
282343 spectator . tick ( ) ;
283344
284345 options = spectator . queryAll ( '.multi-select-option' , { root : true } ) ;
285- expect ( options . length ) . toBe ( 2 ) ;
346+ expect ( options . length ) . toBe ( 4 ) ;
286347 expect ( options [ 0 ] ) . toContainText ( 'first' ) ;
287348 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 ( ) ;
288363 flush ( ) ;
289364 } ) ) ;
290365} ) ;
0 commit comments