diff --git a/lib/content-services/src/lib/mock/public-api.ts b/lib/content-services/src/lib/mock/public-api.ts index a6e0b31d4e..0ee68b00a0 100644 --- a/lib/content-services/src/lib/mock/public-api.ts +++ b/lib/content-services/src/lib/mock/public-api.ts @@ -19,3 +19,4 @@ export * from './document-library.model.mock'; export * from './document-list.component.mock'; export * from './search.component.mock'; export * from './search.service.mock'; +export * from './search-filter-mock'; diff --git a/lib/content-services/src/lib/mock/search-filter-mock.ts b/lib/content-services/src/lib/mock/search-filter-mock.ts new file mode 100644 index 0000000000..361fbc171e --- /dev/null +++ b/lib/content-services/src/lib/mock/search-filter-mock.ts @@ -0,0 +1,611 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const expandableCategories = [ + { + id: 'cat-1', + name: 'category-1', + expanded: false, + enabled: false, + component: { + selector: 'cat-1-component', + settings: null + } + } +]; + +export const disabledCategories = [ + { + id: 'queryType', + name: 'Type', + expanded: true, + enabled: false, + component: { + selector: 'check-list', + settings: { + 'field': null, + 'pageSize': 5, + 'options': [ + { 'name': 'Folder', 'value': "TYPE:'cm:folder'" }, + { 'name': 'Document', 'value': "TYPE:'cm:content'" } + ] + } + } + } +]; + +export const expandedCategories = [ + { + id: 'queryType', + name: 'Type', + expanded: true, + enabled: true, + component: { + selector: 'check-list', + settings: { + 'field': null, + 'pageSize': 5, + 'options': [ + { 'name': 'Folder', 'value': "TYPE:'cm:folder'" }, + { 'name': 'Document', 'value': "TYPE:'cm:content'" } + ] + } + } + } +]; + +export const simpleCategories = [ + { + id: 'queryName', + name: 'Name', + expanded: false, + enabled: true, + component: { + selector: 'text', + settings: {} + } + }, + { + id: 'queryType', + name: 'Type', + expanded: false, + enabled: true, + component: { + selector: 'check-list', + settings: { + 'field': null, + 'pageSize': 5, + 'options': [ + { 'name': 'Folder', 'value': "TYPE:'cm:folder'" }, + { 'name': 'Document', 'value': "TYPE:'cm:content'" } + ] + } + } + } + +]; + +export const searchFilter = { + 'app:fields': [ + 'cm:name' + ], + 'include': [ + 'allowableOperations' + ], + 'sorting': { + 'options': [ + { + 'key': 'name', + 'label': 'Name', + 'type': 'FIELD', + 'field': 'cm:name', + 'ascending': true + } + ], + 'defaults': [ + { + 'key': 'score', + 'type': 'FIELD', + 'field': 'score', + 'ascending': false + } + ] + }, + 'resetButton': true, + 'filterQueries': [ + { + 'query': "TYPE:'cm:folder' OR TYPE:'cm:content'" + }, + { + 'query': 'NOT cm:creator:System' + } + ], + 'facetFields': { + 'expanded': true, + 'fields': [ + { + 'field': 'content.mimetype', + 'mincount': 1, + 'label': 'SEARCH.FACET_FIELDS.TYPE' + }, + { + 'field': 'content.size', + 'mincount': 1, + 'label': 'SEARCH.FACET_FIELDS.SIZE' + }, + { + 'field': 'creator', + 'mincount': 1, + 'label': 'SEARCH.FACET_FIELDS.CREATOR' + }, + { + 'field': 'modifier', + 'mincount': 1, + 'label': 'SEARCH.FACET_FIELDS.MODIFIER' + }, + { + 'field': 'created', + 'mincount': 1, + 'label': 'SEARCH.FACET_FIELDS.CREATED' + } + ] + }, + 'facetQueries': { + 'label': 'SEARCH.FACET_QUERIES.MY_FACET_QUERIES', + 'pageSize': 5, + 'expanded': true, + 'mincount': 1, + 'queries': [ + { + 'query': 'created:2019', + 'label': 'SEARCH.FACET_QUERIES.CREATED_THIS_YEAR' + }, + { + 'query': 'content.mimetype:text/html', + 'label': 'SEARCH.FACET_QUERIES.MIMETYPE', + 'group': 'Type facet queries' + }, + { + 'query': 'content.size:[0 TO 10240]', + 'label': 'Extra Small', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[10240 TO 102400]', + 'label': 'SEARCH.FACET_QUERIES.SMALL', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[102400 TO 1048576]', + 'label': 'SEARCH.FACET_QUERIES.MEDIUM', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[1048576 TO 16777216]', + 'label': 'SEARCH.FACET_QUERIES.LARGE', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[16777216 TO 134217728]', + 'label': 'SEARCH.FACET_QUERIES.XTRALARGE', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[134217728 TO MAX]', + 'label': 'SEARCH.FACET_QUERIES.XXTRALARGE', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[111111 TO MAX]', + 'label': 'my1', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[222222 TO MAX]', + 'label': 'my2', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[333333 TO MAX]', + 'label': 'my3', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[444444 TO MAX]', + 'label': 'my4', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[5555 TO MAX]', + 'label': 'my5', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[666666 TO MAX]', + 'label': 'my6', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[777777 TO MAX]', + 'label': 'my7', + 'group': 'Size facet queries' + }, + { + 'query': 'content.size:[888888 TO MAX]', + 'label': 'my8', + 'group': 'Size facet queries' + } + ] + }, + 'facetIntervals': { + 'expanded': true, + 'intervals': [ + { + 'label': 'The Created', + 'field': 'cm:created', + 'sets': [ + { + 'label': 'lastYear', + 'start': '2018', + 'end': '2019', + 'endInclusive': false + }, + { + 'label': 'currentYear', + 'start': 'NOW/YEAR', + 'end': 'NOW/YEAR+1YEAR' + }, + { + 'label': 'earlier', + 'start': '*', + 'end': '2018', + 'endInclusive': false + } + ] + }, + { + 'label': 'TheModified', + 'field': 'cm:modified', + 'sets': [ + { + 'label': '2017', + 'start': '2017', + 'end': '2018', + 'endInclusive': false + }, + { + 'label': '2017-2018', + 'start': '2017', + 'end': '2018', + 'endInclusive': true + }, + { + 'label': 'currentYear', + 'start': 'NOW/YEAR', + 'end': 'NOW/YEAR+1YEAR' + }, + { + 'label': 'earlierThan2017', + 'start': '*', + 'end': '2017', + 'endInclusive': false + } + ] + } + ] + }, + 'categories': [ + { + 'id': 'queryName', + 'name': 'Name', + 'enabled': true, + 'expanded': true, + 'component': { + 'selector': 'text', + 'settings': { + 'pattern': "cm:name:'(.*?)'", + 'field': 'cm:name', + 'placeholder': 'Enter the name' + } + } + }, + { + 'id': 'checkList', + 'name': 'Check List', + 'enabled': true, + 'component': { + 'selector': 'check-list', + 'settings': { + 'pageSize': 5, + 'operator': 'OR', + 'options': [] + } + } + }, + { + 'id': 'contentSize', + 'name': 'Content Size', + 'enabled': true, + 'component': { + 'selector': 'slider', + 'settings': { + 'field': 'cm:content.size', + 'min': 0, + 'max': 18, + 'step': 1, + 'thumbLabel': true + } + } + }, + { + 'id': 'contentSizeRange', + 'name': 'Content Size (range)', + 'enabled': true, + 'component': { + 'selector': 'number-range', + 'settings': { + 'field': 'cm:content.size', + 'format': '[{FROM} TO {TO}]' + } + } + }, + { + 'id': 'createdDateRange', + 'name': 'Created Date (range)', + 'enabled': true, + 'component': { + 'selector': 'date-range', + 'settings': { + 'field': 'cm:created', + 'dateFormat': 'DD-MMM-YY' + } + } + }, + { + 'id': 'queryType', + 'name': 'Type', + 'enabled': true, + 'component': { + 'selector': 'radio', + 'settings': { + 'field': null, + 'pageSize': 5, + 'options': [] + } + } + } + ] +}; + +export const mockSearchResult = { + 'list': { + 'pagination': { 'count': 20, 'hasMoreItems': true, 'totalItems': 20284, 'skipCount': 0, 'maxItems': 20 }, + 'context': { + 'consistency': { 'lastTxId': 122854 }, + 'facets': [ + { + 'type': 'query', + 'label': 'Type facet queries', + 'buckets': [ + { + 'label': 'SEARCH.FACET_QUERIES.MIMETYPE', + 'filterQuery': 'content.mimetype:text/html', + 'metrics': [{ 'type': 'count', 'value': { 'count': 13 } }] + }] + }, { + 'type': 'query', + 'label': 'Size facet queries', + 'buckets': [ + { + 'label': 'my1', + 'filterQuery': 'content.size:[111111 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 806 } }] + }, { + 'label': 'my3', + 'filterQuery': 'content.size:[333333 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 669 } }] + }, { + 'label': 'my2', + 'filterQuery': 'content.size:[222222 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 691 } }] + }, { + 'label': 'my5', + 'filterQuery': 'content.size:[5555 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 1866 } }] + }, { + 'label': 'my4', + 'filterQuery': 'content.size:[444444 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 665 } }] + }, { + 'label': 'my7', + 'filterQuery': 'content.size:[777777 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 641 } }] + }, { + 'label': 'SEARCH.FACET_QUERIES.SMALL', + 'filterQuery': 'content.size:[10240 TO 102400]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 526 } }] + }, { + 'label': 'my6', + 'filterQuery': 'content.size:[666666 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 652 } }] + }, { + 'label': 'SEARCH.FACET_QUERIES.XTRALARGE', + 'filterQuery': 'content.size:[16777216 TO 134217728]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 617 } }] + }, { + 'label': 'my8', + 'filterQuery': 'content.size:[888888 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 641 } }] + }, { + 'label': 'SEARCH.FACET_QUERIES.XXTRALARGE', + 'filterQuery': 'content.size:[134217728 TO MAX]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 0 } }] + }, { + 'label': 'SEARCH.FACET_QUERIES.MEDIUM', + 'filterQuery': 'content.size:[102400 TO 1048576]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 630 } }] + }, { + 'label': 'SEARCH.FACET_QUERIES.LARGE', + 'filterQuery': 'content.size:[1048576 TO 16777216]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 23 } }] + }, { + 'label': 'Extra Small', + 'filterQuery': 'content.size:[0 TO 10240]', + 'metrics': [{ 'type': 'count', 'value': { 'count': 10239 } }] + }] + }, { + 'type': 'query', + 'label': 'SEARCH.FACET_QUERIES.MY_FACET_QUERIES', + 'buckets': [ + { + 'label': 'SEARCH.FACET_QUERIES.CREATED_THIS_YEAR', + 'filterQuery': 'created:2019', + 'metrics': [{ 'type': 'count', 'value': { 'count': 0 } }] + }] + }, + { + 'type': 'field', + 'label': 'SEARCH.FACET_FIELDS.SIZE', + 'buckets': [] + }, { + 'type': 'field', + 'label': 'SEARCH.FACET_FIELDS.CREATED', + 'buckets': [] + }, { + 'type': 'field', + 'label': 'SEARCH.FACET_FIELDS.TYPE', + 'buckets': [] + }, { + 'type': 'field', + 'label': 'SEARCH.FACET_FIELDS.MODIFIER', + 'buckets': [] + }, { + 'type': 'field', + 'label': 'SEARCH.FACET_FIELDS.CREATOR', + 'buckets': [] + }, { + 'type': 'interval', + 'label': 'TheModified', + 'buckets': [] + }, { + 'type': 'interval', + 'label': 'The Created', + 'buckets': [] + }] + } + } +}; + +export const stepOne = [ + 'Extra Small (10239)', + 'SEARCH.FACET_QUERIES.SMALL (526)', + 'SEARCH.FACET_QUERIES.MEDIUM (630)', + 'SEARCH.FACET_QUERIES.LARGE (23)', + 'SEARCH.FACET_QUERIES.XTRALARGE (617)' +]; + +export const stepTwo = [ + 'Extra Small (10239)', + 'SEARCH.FACET_QUERIES.SMALL (526)', + 'SEARCH.FACET_QUERIES.MEDIUM (630)', + 'SEARCH.FACET_QUERIES.LARGE (23)', + 'SEARCH.FACET_QUERIES.XTRALARGE (617)', + 'my1 (806)', + 'my2 (691)', + 'my3 (669)', + 'my4 (665)', + 'my5 (1866)' +]; + +export const stepThree = [ + 'Extra Small (10239)', + 'SEARCH.FACET_QUERIES.SMALL (526)', + 'SEARCH.FACET_QUERIES.MEDIUM (630)', + 'SEARCH.FACET_QUERIES.LARGE (23)', + 'SEARCH.FACET_QUERIES.XTRALARGE (617)', + 'my1 (806)', + 'my2 (691)', + 'my3 (669)', + 'my4 (665)', + 'my5 (1866)', + 'my6 (652)', + 'my7 (641)', + 'my8 (641)' +]; + +export const sizeOptions = [ + { + 'name': 'Extra Small (10239)', + 'value': 'Extra Small (10239)' + }, + { + 'name': 'SEARCH.FACET_QUERIES.SMALL (526)', + 'value': 'SEARCH.FACET_QUERIES.SMALL (526)' + }, + { + 'name': 'SEARCH.FACET_QUERIES.MEDIUM (630)', + 'value': 'SEARCH.FACET_QUERIES.MEDIUM (630)' + }, + { + 'name': 'SEARCH.FACET_QUERIES.LARGE (23)', + 'value': 'SEARCH.FACET_QUERIES.LARGE (23)' + }, + { + 'name': 'SEARCH.FACET_QUERIES.XTRALARGE (617)', + 'value': 'SEARCH.FACET_QUERIES.XTRALARGE (617)' + }, + { + 'name': 'my1 (806)', + 'group': 'my1 (806)' + }, + { + 'name': 'my2 (691)', + 'value': 'my2 (691)' + }, + { + 'name': 'my3 (669)', + 'value': 'my3 (669)' + }, + { + 'name': 'my4 (665)', + 'value': 'my4 (665)' + }, + { + 'name': 'my5 (1866)', + 'group': 'my5 (1866)' + }, + { + 'name': 'my6 (652)', + 'group': 'my6 (652)' + }, + { + 'name': 'my7 (641)', + 'value': 'my7 (641)' + }, + { + 'name': 'my8 (641)', + 'value': 'my8 (641)' + } +]; + +export const filteredResult = [ + 'my1 (806)', + 'my2 (691)', + 'my3 (669)', + 'my4 (665)', + 'my5 (1866)' +]; diff --git a/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts b/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts index b84c658c9c..3de9c77e6e 100644 --- a/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-check-list/search-check-list.component.spec.ts @@ -17,13 +17,23 @@ import { SearchCheckListComponent, SearchListOption } from './search-check-list.component'; import { SearchFilterList } from '../search-filter/models/search-filter-list.model'; +import { setupTestBed } from '@alfresco/adf-core'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { sizeOptions, stepOne, stepThree } from '../../../mock'; +import { By } from '@angular/platform-browser'; describe('SearchCheckListComponent', () => { - + let fixture: ComponentFixture; let component: SearchCheckListComponent; + setupTestBed({ + imports: [ ContentTestingModule ] + }); + beforeEach(() => { - component = new SearchCheckListComponent(); + fixture = TestBed.createComponent(SearchCheckListComponent); + component = fixture.componentInstance; }); it('should setup options from settings', () => { @@ -115,4 +125,69 @@ describe('SearchCheckListComponent', () => { expect(component.context.update).toHaveBeenCalled(); expect(component.context.queryFragments[component.id]).toBe(''); }); + + describe('Pagination', () => { + it('should show 5 items when pageSize not defined', () => { + component.id = 'checklist'; + component.context = { + queryFragments: { + 'checklist': 'query' + }, + update() {} + }; + component.settings = { options: sizeOptions }; + + component.ngOnInit(); + fixture.detectChanges(); + + const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox')); + expect(optionElements.length).toEqual(5); + const labels = Array.from(optionElements).map(element => element.nativeElement.innerText); + expect(labels).toEqual(stepOne); + }); + + it('should show all items when pageSize is high', () => { + component.id = 'checklist'; + component.context = { + queryFragments: { + 'checklist': 'query' + }, + update() {} + }; + component.settings = { pageSize: 15, options: sizeOptions }; + component.ngOnInit(); + fixture.detectChanges(); + + const optionElements = fixture.debugElement.queryAll(By.css('mat-checkbox')); + expect(optionElements.length).toEqual(13); + const labels = Array.from(optionElements).map(element => element.nativeElement.innerText); + expect(labels).toEqual(stepThree); + }); + }); + + it('should able to check/reset the checkbox', () => { + component.id = 'checklist'; + component.context = { + queryFragments: { + 'checklist': 'query' + }, + update: () => {} + }; + component.settings = { options: sizeOptions }; + spyOn(component, 'flush').and.stub(); + component.ngOnInit(); + fixture.detectChanges(); + + const optionElements = fixture.debugElement.query(By.css('mat-checkbox')); + optionElements.triggerEventHandler('change', { checked: true }); + + expect(component.flush).toHaveBeenCalled(); + + const clearAllElement = fixture.debugElement.query(By.css('button[title="SEARCH.FILTER.ACTIONS.CLEAR-ALL"]')); + clearAllElement.triggerEventHandler('click', {} ); + fixture.detectChanges(); + + const selectedElements = fixture.debugElement.queryAll(By.css('.mat-checkbox-checked')); + expect(selectedElements.length).toBe(0); + }); }); diff --git a/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts b/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts index 90b20f3357..c5b21d55a4 100644 --- a/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-filter/search-filter.component.spec.ts @@ -17,721 +17,961 @@ import { SearchFilterComponent } from './search-filter.component'; import { SearchQueryBuilderService } from '../../search-query-builder.service'; -import { AppConfigService, TranslationMock, CoreModule, TranslationService, SearchService } from '@alfresco/adf-core'; +import { AppConfigService, SearchService, setupTestBed, TranslationService } from '@alfresco/adf-core'; import { Subject } from 'rxjs'; import { FacetFieldBucket } from '../../facet-field-bucket.interface'; import { FacetField } from '../../facet-field.interface'; import { SearchFilterList } from './models/search-filter-list.model'; -import { TestBed, async } from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { HttpClientModule } from '@angular/common/http'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { + disabledCategories, + expandableCategories, + expandedCategories, + filteredResult, + mockSearchResult, + searchFilter, + simpleCategories, + stepOne, + stepThree, + stepTwo +} from '../../../mock'; describe('SearchFilterComponent', () => { - + let fixture: ComponentFixture; let component: SearchFilterComponent; let queryBuilder: SearchQueryBuilderService; - let appConfig: AppConfigService; - const translationMock = new TranslationMock(); + let appConfigService: AppConfigService; + const searchMock: any = { + dataLoaded: new Subject() + }; + + setupTestBed({ + imports: [ + ContentTestingModule + ], + providers: [ + { provide: SearchService, useValue: searchMock } + ] + }); beforeEach(() => { - const searchMock: any = { - dataLoaded: new Subject() - }; - translationMock.instant = (key) => `${key}_translated`; - - TestBed.configureTestingModule({ - imports: [ - CoreModule.forRoot(), - HttpClientModule, - NoopAnimationsModule - ], - declarations: [SearchFilterComponent], - providers: [ - { provide: SearchService, useValue: searchMock }, - { provide: TranslationService, useValue: translationMock } - ], - schemas: [ NO_ERRORS_SCHEMA ] - }); - - appConfig = TestBed.get(AppConfigService); - appConfig.config.search = {}; - queryBuilder = TestBed.get(SearchQueryBuilderService); - - component = new SearchFilterComponent(queryBuilder, searchMock, translationMock); - component.ngOnInit(); + fixture = TestBed.createComponent(SearchFilterComponent); + appConfigService = TestBed.get(AppConfigService); + const translationService = fixture.debugElement.injector.get(TranslationService); + spyOn(translationService, 'instant').and.callFake((key) => key ? `${key}_translated` : null); + component = fixture.componentInstance; }); - it('should have expandable categories', async(() => { - queryBuilder.categories = [ - { - id: 'cat-1', - name: 'category-1', - expanded: false, - enabled: false, - component: { - selector: 'cat-1-component', - settings: null - } - } - ]; + afterEach(() => fixture.destroy()); - const fixture = TestBed.createComponent(SearchFilterComponent); - fixture.detectChanges(); - fixture.whenStable().then(() => { - const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); - expect(panels.length).toBe(1); + describe('component', () => { + beforeEach(() => fixture.detectChanges()); - const element: HTMLElement = panels[0].nativeElement; + it('should subscribe to query builder executed event', () => { + spyOn(component, 'onDataLoaded').and.stub(); + const data = { list: {} }; + queryBuilder.executed.next(data); - (element.childNodes[0] as HTMLElement).click(); - fixture.detectChanges(); - expect(element.classList.contains('mat-expanded')).toBeTruthy(); - - (element.childNodes[0] as HTMLElement).click(); - fixture.detectChanges(); - expect(element.classList.contains('mat-expanded')).toBeFalsy(); + expect(component.onDataLoaded).toHaveBeenCalledWith(data); }); - })); - it('should subscribe to query builder executed event', () => { - spyOn(component, 'onDataLoaded').and.stub(); - const data = {}; - queryBuilder.executed.next(data); + it('should update bucket model and query builder on facet toggle', () => { + spyOn(queryBuilder, 'update').and.stub(); + spyOn(queryBuilder, 'addUserFacetBucket').and.callThrough(); - expect(component.onDataLoaded).toHaveBeenCalledWith(data); - }); + const event: any = { checked: true }; + const field: FacetField = { field: 'f1', label: 'f1' }; + const bucket: FacetFieldBucket = { checked: false, filterQuery: 'q1', label: 'q1', count: 1 }; - it('should update bucket model and query builder on facet toggle', () => { - spyOn(queryBuilder, 'update').and.stub(); - spyOn(queryBuilder, 'addUserFacetBucket').and.callThrough(); + component.onToggleBucket(event, field, bucket); - const event: any = { checked: true }; - const field: FacetField = { field: 'f1', label: 'f1' }; - const bucket: FacetFieldBucket = { checked: false, filterQuery: 'q1', label: 'q1', count: 1 }; + expect(bucket.checked).toBeTruthy(); + expect(queryBuilder.addUserFacetBucket).toHaveBeenCalledWith(field, bucket); + expect(queryBuilder.update).toHaveBeenCalled(); + }); - component.onToggleBucket(event, field, bucket); + it('should update bucket model and query builder on facet un-toggle', () => { + spyOn(queryBuilder, 'update').and.stub(); + spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough(); - expect(bucket.checked).toBeTruthy(); - expect(queryBuilder.addUserFacetBucket).toHaveBeenCalledWith(field, bucket); - expect(queryBuilder.update).toHaveBeenCalled(); - }); + const event: any = { checked: false }; + const field: FacetField = { field: 'f1', label: 'f1' }; + const bucket: FacetFieldBucket = { checked: true, filterQuery: 'q1', label: 'q1', count: 1 }; - it('should update bucket model and query builder on facet un-toggle', () => { - spyOn(queryBuilder, 'update').and.stub(); - spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough(); + component.onToggleBucket(event, field, bucket); - const event: any = { checked: false }; - const field: FacetField = { field: 'f1', label: 'f1' }; - const bucket: FacetFieldBucket = { checked: true, filterQuery: 'q1', label: 'q1', count: 1 }; + expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith(field, bucket); + expect(queryBuilder.update).toHaveBeenCalled(); + }); - component.onToggleBucket(event, field, bucket); + it('should unselect facet query and update builder', () => { + spyOn(queryBuilder, 'update').and.stub(); + spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough(); - expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith(field, bucket); - expect(queryBuilder.update).toHaveBeenCalled(); - }); + const event: any = { checked: false }; + const query = { checked: true, label: 'q1', filterQuery: 'query1' }; + const field = { type: 'query', label: 'label1', buckets: [ query ] }; - it('should unselect facet query and update builder', () => { - spyOn(queryBuilder, 'update').and.stub(); - spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough(); + component.onToggleBucket(event, field, query); - const event: any = { checked: false }; - const query = { checked: true, label: 'q1', filterQuery: 'query1' }; - const field = { type: 'query', label: 'label1', buckets: [ query ] }; + expect(query.checked).toEqual(false); + expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith(field, query); + expect(queryBuilder.update).toHaveBeenCalled(); + }); - component.onToggleBucket(event, field, query); + it('should fetch facet queries from response payload', () => { + component.responseFacets = null; - expect(query.checked).toBeFalsy(); - expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith(field, query); - expect(queryBuilder.update).toHaveBeenCalled(); - }); - - it('should fetch facet queries from response payload', () => { - component.responseFacets = null; - - queryBuilder.config = { - categories: [], - facetQueries: { - label: 'label1', - queries: [ - { label: 'q1', query: 'query1' }, - { label: 'q2', query: 'query2' } - ] - } - }; - - const queries = [ - { label: 'q1', filterQuery: 'query1', metrics: [{value: {count: 1}}] }, - { label: 'q2', filterQuery: 'query2', metrics: [{value: {count: 1}}] } - ]; - const data = { - list: { - context: { - facets: [{ - type: 'query', - label: 'label1', - buckets: queries - }] + queryBuilder.config = { + categories: [], + facetQueries: { + label: 'label1', + queries: [ + { label: 'q1', query: 'query1' }, + { label: 'q2', query: 'query2' } + ] } - } - }; + }; - component.onDataLoaded(data); - - expect(component.responseFacets.length).toBe(1); - expect(component.responseFacets[0].buckets.length).toEqual(2); - }); - - it('should preserve order after response processing', () => { - component.responseFacets = null; - - queryBuilder.config = { - categories: [], - facetQueries: { - label: 'label1', - queries: [ - { label: 'q1', query: 'query1' }, - { label: 'q2', query: 'query2' }, - { label: 'q3', query: 'query3' } - ] - } - }; - - const queries = [ - { label: 'q2', filterQuery: 'query2', metrics: [{value: {count: 1}}] }, - { label: 'q1', filterQuery: 'query1', metrics: [{value: {count: 1}}] }, - { label: 'q3', filterQuery: 'query3', metrics: [{value: {count: 1}}] } - - ]; - const data = { - list: { - context: { - facets: [{ - type: 'query', - label: 'label1', - buckets: queries - }] + const queries = [ + { label: 'q1', filterQuery: 'query1', metrics: [{value: {count: 1}}] }, + { label: 'q2', filterQuery: 'query2', metrics: [{value: {count: 1}}] } + ]; + const data = { + list: { + context: { + facets: [{ + type: 'query', + label: 'label1', + buckets: queries + }] + } } - } - }; + }; - component.onDataLoaded(data); + component.onDataLoaded(data); - expect(component.responseFacets.length).toBe(1); - expect(component.responseFacets[0].buckets.length).toBe(3); - expect(component.responseFacets[0].buckets.items[0].label).toBe('q1'); - expect(component.responseFacets[0].buckets.items[1].label).toBe('q2'); - expect(component.responseFacets[0].buckets.items[2].label).toBe('q3'); - }); + expect(component.responseFacets.length).toBe(1); + expect(component.responseFacets[0].buckets.length).toEqual(2); + }); - it('should not fetch facet queries from response payload', () => { - component.responseFacets = null; + it('should preserve order after response processing', () => { + component.responseFacets = null; - queryBuilder.config = { - categories: [], - facetQueries: { - queries: [] - } - }; - - const data = { - list: { - context: { - facets: null + queryBuilder.config = { + categories: [], + facetQueries: { + label: 'label1', + queries: [ + { label: 'q1', query: 'query1' }, + { label: 'q2', query: 'query2' }, + { label: 'q3', query: 'query3' } + ] } - } - }; + }; - component.onDataLoaded(data); + const queries = [ + { label: 'q2', filterQuery: 'query2', metrics: [{value: {count: 1}}] }, + { label: 'q1', filterQuery: 'query1', metrics: [{value: {count: 1}}] }, + { label: 'q3', filterQuery: 'query3', metrics: [{value: {count: 1}}] } - expect(component.responseFacets).toBeNull(); - }); - - it('should fetch facet fields from response payload', () => { - component.responseFacets = null; - - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1', mincount: 0 }, - { label: 'f2', field: 'f2', mincount: 0 } - ]}, - facetQueries: { - queries: [] - } - }; - - const fields: any = [ - { type: 'field', label: 'f1', buckets: [{ label: 'a1' }, { label: 'a2' }] }, - { type: 'field', label: 'f2', buckets: [{ label: 'b1' }, { label: 'b2' }] } - ]; - const data = { - list: { - context: { - facets: fields + ]; + const data = { + list: { + context: { + facets: [{ + type: 'query', + label: 'label1', + buckets: queries + }] + } } - } - }; + }; - component.onDataLoaded(data); + component.onDataLoaded(data); - expect(component.responseFacets.length).toEqual(2); - expect(component.responseFacets[0].buckets.length).toEqual(2); - expect(component.responseFacets[1].buckets.length).toEqual(2); - }); + expect(component.responseFacets.length).toBe(1); + expect(component.responseFacets[0].buckets.length).toBe(3); + expect(component.responseFacets[0].buckets.items[0].label).toBe('q1'); + expect(component.responseFacets[0].buckets.items[1].label).toBe('q2'); + expect(component.responseFacets[0].buckets.items[2].label).toBe('q3'); + }); - it('should filter response facet fields based on search filter config method', () => { - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1' } - ]}, - facetQueries: { - queries: [] - }, - filterWithContains: false - }; + it('should not fetch facet queries from response payload', () => { + component.responseFacets = null; - const initialFields: any = [ - { type: 'field', label: 'f1', buckets: [ - { label: 'firstLabel', display: 'firstLabel', metrics: [{value: {count: 5}}] }, - { label: 'secondLabel', display: 'secondLabel', metrics: [{value: {count: 5}}] }, - { label: 'thirdLabel', display: 'thirdLabel', metrics: [{value: {count: 5}}] } - ] - } - ]; - - const data = { - list: { - context: { - facets: initialFields + queryBuilder.config = { + categories: [], + facetQueries: { + queries: [] } - } - }; + }; - component.onDataLoaded(data); - expect(component.responseFacets.length).toBe(1); - expect(component.responseFacets[0].buckets.visibleItems.length).toBe(3); + const data = { + list: { + context: { + facets: null + } + } + }; - component.responseFacets[0].buckets.filterText = 'f'; - expect(component.responseFacets[0].buckets.visibleItems.length).toBe(1); - expect(component.responseFacets[0].buckets.visibleItems[0].label).toEqual('firstLabel'); + component.onDataLoaded(data); - component.responseFacets[0].buckets.filterText = 'label'; - expect(component.responseFacets[0].buckets.visibleItems.length).toBe(0); + expect(component.responseFacets).toBeNull(); + }); - // Set filter method to use contains and test again - queryBuilder.config.filterWithContains = true; - component.responseFacets[0].buckets.filterText = 'f'; - expect(component.responseFacets[0].buckets.visibleItems.length).toBe(1); - component.responseFacets[0].buckets.filterText = 'label'; - expect(component.responseFacets[0].buckets.visibleItems.length).toBe(3); - }); + it('should fetch facet fields from response payload', () => { + component.responseFacets = null; - it('should fetch facet fields from response payload and show the bucket values', () => { - component.responseFacets = null; + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1', mincount: 0 }, + { label: 'f2', field: 'f2', mincount: 0 } + ]}, + facetQueries: { + queries: [] + } + }; - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1' }, - { label: 'f2', field: 'f2' } - ]}, - facetQueries: { - queries: [] - } - }; + const fields: any = [ + { type: 'field', label: 'f1', buckets: [{ label: 'a1' }, { label: 'a2' }] }, + { type: 'field', label: 'f2', buckets: [{ label: 'b1' }, { label: 'b2' }] } + ]; + const data = { + list: { + context: { + facets: fields + } + } + }; - const serverResponseFields: any = [ - { + component.onDataLoaded(data); + + expect(component.responseFacets.length).toEqual(2); + expect(component.responseFacets[0].buckets.length).toEqual(2); + expect(component.responseFacets[1].buckets.length).toEqual(2); + }); + + it('should filter response facet fields based on search filter config method', () => { + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1' } + ]}, + facetQueries: { + queries: [] + }, + filterWithContains: false + }; + + const initialFields: any = [ + { type: 'field', label: 'f1', buckets: [ + { label: 'firstLabel', display: 'firstLabel', metrics: [{value: {count: 5}}] }, + { label: 'secondLabel', display: 'secondLabel', metrics: [{value: {count: 5}}] }, + { label: 'thirdLabel', display: 'thirdLabel', metrics: [{value: {count: 5}}] } + ] + } + ]; + + const data = { + list: { + context: { + facets: initialFields + } + } + }; + + component.onDataLoaded(data); + expect(component.responseFacets.length).toBe(1); + expect(component.responseFacets[0].buckets.visibleItems.length).toBe(3); + + component.responseFacets[0].buckets.filterText = 'f'; + expect(component.responseFacets[0].buckets.visibleItems.length).toBe(1); + expect(component.responseFacets[0].buckets.visibleItems[0].label).toEqual('firstLabel'); + + component.responseFacets[0].buckets.filterText = 'label'; + expect(component.responseFacets[0].buckets.visibleItems.length).toBe(0); + + // Set filter method to use contains and test again + queryBuilder.config.filterWithContains = true; + component.responseFacets[0].buckets.filterText = 'f'; + expect(component.responseFacets[0].buckets.visibleItems.length).toBe(1); + component.responseFacets[0].buckets.filterText = 'label'; + expect(component.responseFacets[0].buckets.visibleItems.length).toBe(3); + }); + + it('should fetch facet fields from response payload and show the bucket values', () => { + component.responseFacets = null; + + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1' }, + { label: 'f2', field: 'f2' } + ]}, + facetQueries: { + queries: [] + } + }; + + const serverResponseFields: any = [ + { + type: 'field', + label: 'f1', + buckets: [ + { label: 'b1', metrics: [{value: {count: 10}}] }, + { label: 'b2', metrics: [{value: {count: 1}}] } + ] + }, + { type: 'field', label: 'f2', buckets: [] } + ]; + const data = { + list: { + context: { + facets: serverResponseFields + } + } + }; + + component.onDataLoaded(data); + expect(component.responseFacets.length).toEqual(2); + expect(component.responseFacets[0].buckets.items[0].count).toEqual(10); + expect(component.responseFacets[0].buckets.items[1].count).toEqual(1); + }); + + it('should fetch facet fields from response payload and update the existing bucket values', () => { + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1' }, + { label: 'f2', field: 'f2' } + ]}, + facetQueries: { + queries: [] + } + }; + + const initialFields: any = [ + { type: 'field', label: 'f1', buckets: { items: [{ label: 'b1', count: 10, filterQuery: 'filter' }, { label: 'b2', count: 1 }]} }, + { type: 'field', label: 'f2', buckets: [] } + ]; + component.responseFacets = initialFields; + expect(component.responseFacets[0].buckets.items[0].count).toEqual(10); + expect(component.responseFacets[0].buckets.items[1].count).toEqual(1); + + const serverResponseFields: any = [ + { type: 'field', label: 'f1', buckets: + [{ label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' }, + { label: 'b2', metrics: [{value: {count: 0}}] }] }, + { type: 'field', label: 'f2', buckets: [] } + ]; + const data = { + list: { + context: { + facets: serverResponseFields + } + } + }; + + component.onDataLoaded(data); + expect(component.responseFacets[0].buckets.items[0].count).toEqual(6); + expect(component.responseFacets[0].buckets.items[1].count).toEqual(0); + }); + + it('should update correctly the existing facetFields bucket values', () => { + component.responseFacets = null; + + queryBuilder.config = { + categories: [], + facetFields: { fields: [{ label: 'f1', field: 'f1' }] }, + facetQueries: { queries: [] } + }; + + const firstCallFields: any = [{ type: 'field', label: 'f1', - buckets: [ - { label: 'b1', metrics: [{value: {count: 10}}] }, - { label: 'b2', metrics: [{value: {count: 1}}] } - ] - }, - { type: 'field', label: 'f2', buckets: [] } - ]; - const data = { - list: { - context: { - facets: serverResponseFields - } - } - }; + buckets: [{ label: 'b1', metrics: [{value: {count: 10}}] }] + }]; + const firstCallData = { list: { context: { facets: firstCallFields }}}; + component.onDataLoaded(firstCallData); + expect(component.responseFacets[0].buckets.items[0].count).toEqual(10); - component.onDataLoaded(data); - expect(component.responseFacets.length).toEqual(2); - expect(component.responseFacets[0].buckets.items[0].count).toEqual(10); - expect(component.responseFacets[0].buckets.items[1].count).toEqual(1); - }); + const secondCallFields: any = [{ + type: 'field', + label: 'f1', + buckets: [{ label: 'b1', metrics: [{value: {count: 6}}] }] + }]; + const secondCallData = { list: { context: { facets: secondCallFields}}}; + component.onDataLoaded(secondCallData); + expect(component.responseFacets[0].buckets.items[0].count).toEqual(6); + }); - it('should fetch facet fields from response payload and update the existing bucket values', () => { - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1' }, - { label: 'f2', field: 'f2' } - ]}, - facetQueries: { - queries: [] - } - }; - - const initialFields: any = [ - { type: 'field', label: 'f1', buckets: { items: [{ label: 'b1', count: 10, filterQuery: 'filter' }, { label: 'b2', count: 1 }]} }, - { type: 'field', label: 'f2', buckets: [] } - ]; - component.responseFacets = initialFields; - expect(component.responseFacets[0].buckets.items[0].count).toEqual(10); - expect(component.responseFacets[0].buckets.items[1].count).toEqual(1); - - const serverResponseFields: any = [ - { type: 'field', label: 'f1', buckets: - [{ label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' }, - { label: 'b2', metrics: [{value: {count: 0}}] }] }, - { type: 'field', label: 'f2', buckets: [] } - ]; - const data = { - list: { - context: { - facets: serverResponseFields - } - } - }; - - component.onDataLoaded(data); - expect(component.responseFacets[0].buckets.items[0].count).toEqual(6); - expect(component.responseFacets[0].buckets.items[1].count).toEqual(0); - }); - - it('should update correctly the existing facetFields bucket values', () => { - component.responseFacets = null; - - queryBuilder.config = { - categories: [], - facetFields: { fields: [{ label: 'f1', field: 'f1' }] }, - facetQueries: { queries: [] } - }; - - const firstCallFields: any = [{ - type: 'field', - label: 'f1', - buckets: [{ label: 'b1', metrics: [{value: {count: 10}}] }] - }]; - const firstCallData = { list: { context: { facets: firstCallFields }}}; - component.onDataLoaded(firstCallData); - expect(component.responseFacets[0].buckets.items[0].count).toEqual(10); - - const secondCallFields: any = [{ - type: 'field', - label: 'f1', - buckets: [{ label: 'b1', metrics: [{value: {count: 6}}] }] - }]; - const secondCallData = { list: { context: { facets: secondCallFields}}}; - component.onDataLoaded(secondCallData); - expect(component.responseFacets[0].buckets.items[0].count).toEqual(6); - }); - - it('should fetch facet fields from response payload and show the already checked items', () => { - spyOn(queryBuilder, 'execute').and.stub(); - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1' }, - { label: 'f2', field: 'f2' } - ]}, - facetQueries: { - queries: [] - } - }; - - component.responseFacets = [ - { type: 'field', label: 'f1', field: 'f1', buckets: {items: [ - { label: 'b1', count: 10, filterQuery: 'filter', checked: true }, - { label: 'b2', count: 1, filterQuery: 'filter2' }] }}, - { type: 'field', label: 'f2', field: 'f2', buckets: {items: [] }} - ]; - component.queryBuilder.addUserFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[0]); - - const serverResponseFields: any = [ - { type: 'field', label: 'f1', field: 'f1', buckets: [ - { label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' }, - { label: 'b2', metrics: [{value: {count: 1}}], filterQuery: 'filter2' }] }, - { type: 'field', label: 'f2', field: 'f2', buckets: [] } - ]; - const data = { - list: { - context: { - facets: serverResponseFields - } - } - }; - component.selectFacetBucket({ field: 'f1', label: 'f1' }, component.responseFacets[0].buckets.items[1]); - component.onDataLoaded(data); - expect(component.responseFacets.length).toEqual(2); - expect(component.responseFacets[0].buckets.items[0].checked).toEqual(true, 'should show the already checked item'); - }); - - it('should fetch facet fields from response payload and show the newly checked items', () => { - spyOn(queryBuilder, 'execute').and.stub(); - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1' }, - { label: 'f2', field: 'f2' } - ]}, - facetQueries: { - queries: [] - } - }; - - component.responseFacets = [ - { type: 'field', label: 'f1', field: 'f1', buckets: {items: [ - { label: 'b1', count: 10, filterQuery: 'filter', checked: true }, - { label: 'b2', count: 1, filterQuery: 'filter2' }] }}, - { type: 'field', label: 'f2', field: 'f2', buckets: {items: [] }} - ]; - component.queryBuilder.addUserFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[0]); - - const serverResponseFields: any = [ - { type: 'field', label: 'f1', field: 'f1', buckets: [ - { label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' }, - { label: 'b2', metrics: [{value: {count: 1}}], filterQuery: 'filter2' }] }, - { type: 'field', label: 'f2', field: 'f2', buckets: [] } - ]; - const data = { - list: { - context: { - facets: serverResponseFields - } - } - }; - component.selectFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[1]); - component.onDataLoaded(data); - expect(component.responseFacets.length).toEqual(2); - expect(component.responseFacets[0].buckets.items[1].checked).toEqual(true, 'should show the newly checked item'); - }); - - it('should show buckets with 0 values when there are no facet fields on the response payload', () => { - spyOn(queryBuilder, 'execute').and.stub(); - queryBuilder.config = { - categories: [], - facetFields: { fields: [ - { label: 'f1', field: 'f1' }, - { label: 'f2', field: 'f2' } - ]}, - facetQueries: { - queries: [] - } - }; - - component.responseFacets = [ - { type: 'field', label: 'f1', field: 'f1', buckets: {items: [ - { label: 'b1', count: 10, filterQuery: 'filter', checked: true }, - { label: 'b2', count: 1, filterQuery: 'filter2' }] }}, - { type: 'field', label: 'f2', field: 'f2', buckets: {items: [] }} - ]; - component.queryBuilder.addUserFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[0]); - const data = { - list: { - context: {} - } - }; - component.selectFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[1]); - component.onDataLoaded(data); - - expect(component.responseFacets[0].buckets.items[0].count).toEqual(0); - expect(component.responseFacets[0].buckets.items[1].count).toEqual(0); - }); - - it('should update query builder only when has bucket to unselect', () => { - spyOn(queryBuilder, 'update').and.stub(); - - const field: FacetField = { field: 'f1', label: 'f1' }; - component.onToggleBucket( { checked: true }, field, null); - - expect(queryBuilder.update).not.toHaveBeenCalled(); - }); - - it('should allow to to reset selected buckets', () => { - const buckets: FacetFieldBucket[] = [ - { label: 'bucket1', checked: true, count: 1, filterQuery: 'q1' }, - { label: 'bucket2', checked: false, count: 1, filterQuery: 'q2' } - ]; - - const field: FacetField = { - field: 'f1', - label: 'field1', - buckets: new SearchFilterList(buckets) - }; - - expect(component.canResetSelectedBuckets(field)).toBeTruthy(); - }); - - it('should not allow to reset selected buckets', () => { - const buckets: FacetFieldBucket[] = [ - { label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' }, - { label: 'bucket2', checked: false, count: 1, filterQuery: 'q2' } - ]; - - const field: FacetField = { - field: 'f1', - label: 'field1', - buckets: new SearchFilterList(buckets) - }; - - expect(component.canResetSelectedBuckets(field)).toBeFalsy(); - }); - - it('should reset selected buckets', () => { - spyOn(queryBuilder, 'execute').and.stub(); - const buckets: FacetFieldBucket[] = [ - { label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' }, - { label: 'bucket2', checked: true, count: 1, filterQuery: 'q2' } - ]; - - const field: FacetField = { - field: 'f1', - label: 'field1', - buckets: new SearchFilterList(buckets) - }; - - component.resetSelectedBuckets(field); - - expect(buckets[0].checked).toBeFalsy(); - expect(buckets[1].checked).toBeFalsy(); - }); - - it('should update query builder upon resetting buckets', () => { - spyOn(queryBuilder, 'update').and.stub(); - - const buckets: FacetFieldBucket[] = [ - { label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' }, - { label: 'bucket2', checked: true, count: 1, filterQuery: 'q2' } - ]; - - const field: FacetField = { - field: 'f1', - label: 'field1', - buckets: new SearchFilterList(buckets) - }; - - component.resetSelectedBuckets(field); - expect(queryBuilder.update).toHaveBeenCalled(); - }); - - it('should update query builder upon resetting selected queries', () => { - spyOn(queryBuilder, 'update').and.stub(); - spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough(); - - const queryResponse = { - label: 'query response', - buckets: { - items: [ - { label: 'q1', query: 'q1', checked: true, metrics: [{value: {count: 1}}] }, - { label: 'q2', query: 'q2', checked: false, metrics: [{value: {count: 1}}] }, - { label: 'q3', query: 'q3', checked: true, metrics: [{value: {count: 1}}] }] - }}; - component.responseFacets = [queryResponse]; - component.resetSelectedBuckets(queryResponse); - - expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledTimes(3); - expect(queryBuilder.update).toHaveBeenCalled(); - - for (const entry of component.responseFacets[0].buckets.items) { - expect(entry.checked).toBeFalsy(); - } - }); - - it('should fetch facet intervals from response payload', () => { - component.responseFacets = null; - queryBuilder.config = { - categories: [], - facetIntervals: { - intervals: [ - { label: 'test_intervals1', field: 'f1', sets: [ - { label: 'interval1', start: 's1', end: 'e1'}, - { label: 'interval2', start: 's2', end: 'e2'} + it('should fetch facet fields from response payload and show the already checked items', () => { + spyOn(queryBuilder, 'execute').and.stub(); + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1' }, + { label: 'f2', field: 'f2' } ]}, - { label: 'test_intervals2', field: 'f2', sets: [ - { label: 'interval3', start: 's3', end: 'e3'}, - { label: 'interval4', start: 's4', end: 'e4'} - ]} - ] - } - }; + facetQueries: { + queries: [] + } + }; - const response1 = [ - { label: 'interval1', filterQuery: 'query1', metrics: [{ value: { count: 1 }}]}, - { label: 'interval2', filterQuery: 'query2', metrics: [{ value: { count: 2 }}]} - ]; - const response2 = [ - { label: 'interval3', filterQuery: 'query3', metrics: [{ value: { count: 3 }}]}, - { label: 'interval4', filterQuery: 'query4', metrics: [{ value: { count: 4 }}]} - ]; - const data = { - list: { - context: { - facets: [ - { type: 'interval', label: 'test_intervals1', buckets: response1 }, - { type: 'interval', label: 'test_intervals2', buckets: response2 } + component.responseFacets = [ + { type: 'field', label: 'f1', field: 'f1', buckets: {items: [ + { label: 'b1', count: 10, filterQuery: 'filter', checked: true }, + { label: 'b2', count: 1, filterQuery: 'filter2' }] }}, + { type: 'field', label: 'f2', field: 'f2', buckets: {items: [] }} + ]; + component.queryBuilder.addUserFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[0]); + + const serverResponseFields: any = [ + { type: 'field', label: 'f1', field: 'f1', buckets: [ + { label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' }, + { label: 'b2', metrics: [{value: {count: 1}}], filterQuery: 'filter2' }] }, + { type: 'field', label: 'f2', field: 'f2', buckets: [] } + ]; + const data = { + list: { + context: { + facets: serverResponseFields + } + } + }; + component.selectFacetBucket({ field: 'f1', label: 'f1' }, component.responseFacets[0].buckets.items[1]); + component.onDataLoaded(data); + expect(component.responseFacets.length).toEqual(2); + expect(component.responseFacets[0].buckets.items[0].checked).toEqual(true, 'should show the already checked item'); + }); + + it('should fetch facet fields from response payload and show the newly checked items', () => { + spyOn(queryBuilder, 'execute').and.stub(); + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1' }, + { label: 'f2', field: 'f2' } + ]}, + facetQueries: { + queries: [] + } + }; + + component.responseFacets = [ + { type: 'field', label: 'f1', field: 'f1', buckets: {items: [ + { label: 'b1', count: 10, filterQuery: 'filter', checked: true }, + { label: 'b2', count: 1, filterQuery: 'filter2' }] }}, + { type: 'field', label: 'f2', field: 'f2', buckets: {items: [] }} + ]; + component.queryBuilder.addUserFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[0]); + + const serverResponseFields: any = [ + { type: 'field', label: 'f1', field: 'f1', buckets: [ + { label: 'b1', metrics: [{value: {count: 6}}], filterQuery: 'filter' }, + { label: 'b2', metrics: [{value: {count: 1}}], filterQuery: 'filter2' }] }, + { type: 'field', label: 'f2', field: 'f2', buckets: [] } + ]; + const data = { + list: { + context: { + facets: serverResponseFields + } + } + }; + component.selectFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[1]); + component.onDataLoaded(data); + expect(component.responseFacets.length).toEqual(2); + expect(component.responseFacets[0].buckets.items[1].checked).toEqual(true, 'should show the newly checked item'); + }); + + it('should show buckets with 0 values when there are no facet fields on the response payload', () => { + spyOn(queryBuilder, 'execute').and.stub(); + queryBuilder.config = { + categories: [], + facetFields: { fields: [ + { label: 'f1', field: 'f1' }, + { label: 'f2', field: 'f2' } + ]}, + facetQueries: { + queries: [] + } + }; + + component.responseFacets = [ + { type: 'field', label: 'f1', field: 'f1', buckets: {items: [ + { label: 'b1', count: 10, filterQuery: 'filter', checked: true }, + { label: 'b2', count: 1, filterQuery: 'filter2' }] }}, + { type: 'field', label: 'f2', field: 'f2', buckets: {items: [] }} + ]; + component.queryBuilder.addUserFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[0]); + const data = { + list: { + context: {} + } + }; + component.selectFacetBucket({ label: 'f1', field: 'f1' }, component.responseFacets[0].buckets.items[1]); + component.onDataLoaded(data); + + expect(component.responseFacets[0].buckets.items[0].count).toEqual(0); + expect(component.responseFacets[0].buckets.items[1].count).toEqual(0); + }); + + it('should update query builder only when has bucket to unselect', () => { + spyOn(queryBuilder, 'update').and.stub(); + + const field: FacetField = { field: 'f1', label: 'f1' }; + component.onToggleBucket( { checked: true }, field, null); + + expect(queryBuilder.update).not.toHaveBeenCalled(); + }); + + it('should allow to to reset selected buckets', () => { + const buckets: FacetFieldBucket[] = [ + { label: 'bucket1', checked: true, count: 1, filterQuery: 'q1' }, + { label: 'bucket2', checked: false, count: 1, filterQuery: 'q2' } + ]; + + const field: FacetField = { + field: 'f1', + label: 'field1', + buckets: new SearchFilterList(buckets) + }; + + expect(component.canResetSelectedBuckets(field)).toBeTruthy(); + }); + + it('should not allow to reset selected buckets', () => { + const buckets: FacetFieldBucket[] = [ + { label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' }, + { label: 'bucket2', checked: false, count: 1, filterQuery: 'q2' } + ]; + + const field: FacetField = { + field: 'f1', + label: 'field1', + buckets: new SearchFilterList(buckets) + }; + + expect(component.canResetSelectedBuckets(field)).toEqual(false); + }); + + it('should reset selected buckets', () => { + spyOn(queryBuilder, 'execute').and.stub(); + const buckets: FacetFieldBucket[] = [ + { label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' }, + { label: 'bucket2', checked: true, count: 1, filterQuery: 'q2' } + ]; + + const field: FacetField = { + field: 'f1', + label: 'field1', + buckets: new SearchFilterList(buckets) + }; + + component.resetSelectedBuckets(field); + + expect(buckets[0].checked).toEqual(false); + expect(buckets[1].checked).toEqual(false); + }); + + it('should update query builder upon resetting buckets', () => { + spyOn(queryBuilder, 'update').and.stub(); + + const buckets: FacetFieldBucket[] = [ + { label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' }, + { label: 'bucket2', checked: true, count: 1, filterQuery: 'q2' } + ]; + + const field: FacetField = { + field: 'f1', + label: 'field1', + buckets: new SearchFilterList(buckets) + }; + + component.resetSelectedBuckets(field); + expect(queryBuilder.update).toHaveBeenCalled(); + }); + + it('should update query builder upon resetting selected queries', () => { + spyOn(queryBuilder, 'update').and.stub(); + spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough(); + + const queryResponse = { + label: 'query response', + buckets: { + items: [ + { label: 'q1', query: 'q1', checked: true, metrics: [{value: {count: 1}}] }, + { label: 'q2', query: 'q2', checked: false, metrics: [{value: {count: 1}}] }, + { label: 'q3', query: 'q3', checked: true, metrics: [{value: {count: 1}}] }] + }}; + component.responseFacets = [queryResponse]; + component.resetSelectedBuckets(queryResponse); + + expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledTimes(3); + expect(queryBuilder.update).toHaveBeenCalled(); + + for (const entry of component.responseFacets[0].buckets.items) { + expect(entry.checked).toEqual(false); + } + }); + + it('should fetch facet intervals from response payload', () => { + component.responseFacets = null; + queryBuilder.config = { + categories: [], + facetIntervals: { + intervals: [ + { label: 'test_intervals1', field: 'f1', sets: [ + { label: 'interval1', start: 's1', end: 'e1'}, + { label: 'interval2', start: 's2', end: 'e2'} + ]}, + { label: 'test_intervals2', field: 'f2', sets: [ + { label: 'interval3', start: 's3', end: 'e3'}, + { label: 'interval4', start: 's4', end: 'e4'} + ]} ] } - } - }; + }; - component.onDataLoaded(data); + const response1 = [ + { label: 'interval1', filterQuery: 'query1', metrics: [{ value: { count: 1 }}]}, + { label: 'interval2', filterQuery: 'query2', metrics: [{ value: { count: 2 }}]} + ]; + const response2 = [ + { label: 'interval3', filterQuery: 'query3', metrics: [{ value: { count: 3 }}]}, + { label: 'interval4', filterQuery: 'query4', metrics: [{ value: { count: 4 }}]} + ]; + const data = { + list: { + context: { + facets: [ + { type: 'interval', label: 'test_intervals1', buckets: response1 }, + { type: 'interval', label: 'test_intervals2', buckets: response2 } + ] + } + } + }; - expect(component.responseFacets.length).toBe(2); - expect(component.responseFacets[0].buckets.length).toEqual(2); - expect(component.responseFacets[1].buckets.length).toEqual(2); - }); + component.onDataLoaded(data); - it('should filter out the fetched facet intervals that have bucket values less than their set mincount', () => { - component.responseFacets = null; - queryBuilder.config = { - categories: [], - facetIntervals: { - intervals: [ - { label: 'test_intervals1', field: 'f1', mincount: 2, sets: [ - { label: 'interval1', start: 's1', end: 'e1'}, - { label: 'interval2', start: 's2', end: 'e2'} - ]}, - { label: 'test_intervals2', field: 'f2', mincount: 5, sets: [ - { label: 'interval3', start: 's3', end: 'e3'}, - { label: 'interval4', start: 's4', end: 'e4'} - ]} - ] - } - }; + expect(component.responseFacets.length).toBe(2); + expect(component.responseFacets[0].buckets.length).toEqual(2); + expect(component.responseFacets[1].buckets.length).toEqual(2); + }); - const response1 = [ - { label: 'interval1', filterQuery: 'query1', metrics: [{ value: { count: 1 }}]}, - { label: 'interval2', filterQuery: 'query2', metrics: [{ value: { count: 2 }}]} - ]; - const response2 = [ - { label: 'interval3', filterQuery: 'query3', metrics: [{ value: { count: 3 }}]}, - { label: 'interval4', filterQuery: 'query4', metrics: [{ value: { count: 4 }}]} - ]; - const data = { - list: { - context: { - facets: [ - { type: 'interval', label: 'test_intervals1', buckets: response1 }, - { type: 'interval', label: 'test_intervals2', buckets: response2 } + it('should filter out the fetched facet intervals that have bucket values less than their set mincount', () => { + component.responseFacets = null; + queryBuilder.config = { + categories: [], + facetIntervals: { + intervals: [ + { label: 'test_intervals1', field: 'f1', mincount: 2, sets: [ + { label: 'interval1', start: 's1', end: 'e1'}, + { label: 'interval2', start: 's2', end: 'e2'} + ]}, + { label: 'test_intervals2', field: 'f2', mincount: 5, sets: [ + { label: 'interval3', start: 's3', end: 'e3'}, + { label: 'interval4', start: 's4', end: 'e4'} + ]} ] } - } - }; + }; - component.onDataLoaded(data); + const response1 = [ + { label: 'interval1', filterQuery: 'query1', metrics: [{ value: { count: 1 }}]}, + { label: 'interval2', filterQuery: 'query2', metrics: [{ value: { count: 2 }}]} + ]; + const response2 = [ + { label: 'interval3', filterQuery: 'query3', metrics: [{ value: { count: 3 }}]}, + { label: 'interval4', filterQuery: 'query4', metrics: [{ value: { count: 4 }}]} + ]; + const data = { + list: { + context: { + facets: [ + { type: 'interval', label: 'test_intervals1', buckets: response1 }, + { type: 'interval', label: 'test_intervals2', buckets: response2 } + ] + } + } + }; + + component.onDataLoaded(data); + + expect(component.responseFacets.length).toBe(2); + expect(component.responseFacets[0].buckets.length).toEqual(1); + expect(component.responseFacets[1].buckets.length).toEqual(0); + }); + }); + + describe('widgets', () => { + + it('should have expandable categories', async(() => { + fixture.detectChanges(); + queryBuilder.categories = expandableCategories; + + fixture.detectChanges(); + fixture.whenStable().then(() => { + const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); + expect(panels.length).toBe(1); + + const element: HTMLElement = panels[0].nativeElement; + + (element.childNodes[0] as HTMLElement).click(); + fixture.detectChanges(); + expect(element.classList.contains('mat-expanded')).toBeTruthy(); + + (element.childNodes[0] as HTMLElement).click(); + fixture.detectChanges(); + expect(element.classList.contains('mat-expanded')).toEqual(false); + }); + })); + + it('should not show the disabled widget', async(() => { + appConfigService.config.search = { categories: disabledCategories }; + queryBuilder.resetToDefaults(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); + expect(panels.length).toBe(0); + }); + })); + + it('should show the widget in expanded mode', async(() => { + appConfigService.config.search = { categories: expandedCategories }; + queryBuilder.resetToDefaults(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); + expect(panels.length).toBe(1); + + const title = fixture.debugElement.query(By.css('.mat-expansion-panel-header-title')); + expect(title.nativeElement.innerText.trim()).toBe('Type'); + + const element: HTMLElement = panels[0].nativeElement; + expect(element.classList.contains('mat-expanded')).toBeTruthy(); + + (element.childNodes[0] as HTMLElement).click(); + fixture.detectChanges(); + expect(element.classList.contains('mat-expanded')).toEqual(false); + }); + })); + + it('should show the widgets only if configured', async(() => { + appConfigService.config.search = { categories: simpleCategories }; + queryBuilder.resetToDefaults(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + const panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); + expect(panels.length).toBe(2); + + const titleElements = fixture.debugElement.queryAll(By.css('.mat-expansion-panel-header-title')); + expect(titleElements.map(title => title.nativeElement.innerText.trim())).toEqual(['Name', 'Type']); + }); + })); + + it('should be update the search query when name changed', async( async () => { + spyOn(queryBuilder, 'update').and.stub(); + appConfigService.config.search = searchFilter; + queryBuilder.resetToDefaults(); + + fixture.detectChanges(); + await fixture.whenStable(); + let panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); + expect(panels.length).toBe(6); + + const inputElement = fixture.debugElement.query(By.css('[data-automation-id="expansion-panel-Name"] input')); + inputElement.triggerEventHandler('change', { target: { value: '*' } }); + expect(queryBuilder.update).toHaveBeenCalled(); + + queryBuilder.executed.next( mockSearchResult); + fixture.detectChanges(); + + panels = fixture.debugElement.queryAll(By.css('.mat-expansion-panel')); + expect(panels.length).toBe(16); + })); + + it('should show the long facet options list with pagination', () => { + const panel = '[data-automation-id="expansion-panel-Size facet queries"]'; + appConfigService.config.search = searchFilter; + queryBuilder.resetToDefaults(); + + fixture.detectChanges(); + queryBuilder.executed.next( mockSearchResult); + fixture.detectChanges(); + + let sizes = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(sizes).toEqual(stepOne); + + let moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`)); + let lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`)); + + expect(lessButton).toEqual(null); + expect(moreButton).toBeDefined(); + + moreButton.triggerEventHandler('click', {}); + fixture.detectChanges(); + + sizes = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(sizes).toEqual(stepTwo); + + moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`)); + lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`)); + expect(lessButton).toBeDefined(); + expect(moreButton).toBeDefined(); + + moreButton.triggerEventHandler('click', {}); + fixture.detectChanges(); + sizes = getAllMenus(`${panel} mat-checkbox`, fixture); + + expect(sizes).toEqual(stepThree); + + moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`)); + lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`)); + expect(lessButton).toBeDefined(); + expect(moreButton).toEqual(null); + + lessButton.triggerEventHandler('click', {}); + fixture.detectChanges(); + + sizes = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(sizes).toEqual(stepTwo); + + moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`)); + lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`)); + expect(lessButton).toBeDefined(); + expect(moreButton).toBeDefined(); + + lessButton.triggerEventHandler('click', {}); + fixture.detectChanges(); + + sizes = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(sizes).toEqual(stepOne); + + moreButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-MORE"]`)); + lessButton = fixture.debugElement.query(By.css(`${panel} button[title="SEARCH.FILTER.ACTIONS.SHOW-LESS"]`)); + expect(lessButton).toEqual(null); + expect(moreButton).toBeDefined(); + }); + + it('should not show facets if filter is not available', () => { + const panel = '[data-automation-id="expansion-panel-Size facet queries"]'; + const filter = { ...searchFilter }; + delete filter.facetQueries; + + appConfigService.config.search = filter; + queryBuilder.resetToDefaults(); + + fixture.detectChanges(); + queryBuilder.executed.next( mockSearchResult); + fixture.detectChanges(); + + const facetElement = fixture.debugElement.query(By.css(panel)); + expect(facetElement).toEqual(null); + }); + + it('should search the facets options and select it', () => { + const panel = '[data-automation-id="expansion-panel-Size facet queries"]'; + appConfigService.config.search = searchFilter; + queryBuilder.resetToDefaults(); + fixture.detectChanges(); + queryBuilder.executed.next( mockSearchResult); + fixture.detectChanges(); + + spyOn(queryBuilder, 'update').and.stub(); + spyOn(component, 'selectFacetBucket').and.callThrough(); + spyOn(component, 'onToggleBucket').and.callThrough(); + + const inputElement = fixture.debugElement.query(By.css(`${panel} input`)); + inputElement.nativeElement.value = 'Extra'; + inputElement.nativeElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + + let filteredMenu = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(filteredMenu).toEqual(['Extra Small (10239)']); + + inputElement.nativeElement.value = 'my'; + inputElement.nativeElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + + filteredMenu = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(filteredMenu).toEqual(filteredResult); + + const clearButton = fixture.debugElement.query(By.css(`${panel} button`)); + clearButton.triggerEventHandler('click', {}); + fixture.detectChanges(); + + filteredMenu = getAllMenus(`${panel} mat-checkbox`, fixture); + expect(filteredMenu).toEqual(stepOne); + + const firstOption = fixture.debugElement.query(By.css(`${panel} mat-checkbox`)); + firstOption.triggerEventHandler('change', { checked: true }); + fixture.detectChanges(); + + const checkedOption = fixture.debugElement.query(By.css(`${panel} mat-checkbox.mat-checkbox-checked`)); + expect(checkedOption.nativeElement.innerText).toEqual('Extra Small (10239)'); + + expect(component.onToggleBucket).toHaveBeenCalledTimes(1); + expect(component.selectFacetBucket).toHaveBeenCalledTimes(1); + }); + + it('should preserve the filter state if other fields edited', () => { + const panel1 = '[data-automation-id="expansion-panel-Size facet queries"]'; + const panel2 = '[data-automation-id="expansion-panel-Type facet queries"]'; + appConfigService.config.search = searchFilter; + queryBuilder.resetToDefaults(); + fixture.detectChanges(); + queryBuilder.executed.next( mockSearchResult); + fixture.detectChanges(); + spyOn(queryBuilder, 'update').and.stub(); + spyOn(component, 'selectFacetBucket').and.callThrough(); + spyOn(component, 'onToggleBucket').and.callThrough(); + + const inputElement = fixture.debugElement.query(By.css(`${panel1} input`)); + inputElement.nativeElement.value = 'my'; + inputElement.nativeElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + + let filteredMenu = getAllMenus(`${panel1} mat-checkbox`, fixture); + expect(filteredMenu).toEqual(filteredResult); + + const firstOption = fixture.debugElement.query(By.css(`${panel1} mat-checkbox`)); + firstOption.triggerEventHandler('change', { checked: true }); + fixture.detectChanges(); + + let panel1CheckedOption = fixture.debugElement.query(By.css(`${panel1} mat-checkbox.mat-checkbox-checked`)); + expect(panel1CheckedOption.nativeElement.innerText).toEqual('my1 (806)'); + + const panel2Options = fixture.debugElement.query(By.css(`${panel2} mat-checkbox`)); + panel2Options.triggerEventHandler('change', { checked: true }); + fixture.detectChanges(); + + const panel2CheckedOption = fixture.debugElement.query(By.css(`${panel2} mat-checkbox.mat-checkbox-checked`)); + expect(panel2CheckedOption.nativeElement.innerText).toEqual('SEARCH.FACET_QUERIES.MIMETYPE (13)'); + + filteredMenu = getAllMenus(`${panel1} mat-checkbox`, fixture); + expect(filteredMenu).toEqual(filteredResult); + + panel1CheckedOption = fixture.debugElement.query(By.css(`${panel1} mat-checkbox.mat-checkbox-checked`)); + expect(panel1CheckedOption.nativeElement.innerText).toEqual('my1 (806)'); + + expect(component.onToggleBucket).toHaveBeenCalledTimes(2); + expect(component.selectFacetBucket).toHaveBeenCalledTimes(2); + }); - expect(component.responseFacets.length).toBe(2); - expect(component.responseFacets[0].buckets.length).toEqual(1); - expect(component.responseFacets[1].buckets.length).toEqual(0); }); }); + +export function getAllMenus(regex, fixture: ComponentFixture): string[] { + const elements = fixture.debugElement.queryAll(By.css(regex)); + return Array.from(elements).map(element => element.nativeElement.innerText); +} diff --git a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts new file mode 100644 index 0000000000..e66582c459 --- /dev/null +++ b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.spec.ts @@ -0,0 +1,96 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { sizeOptions, stepOne, stepThree } from '../../../mock'; +import { By } from '@angular/platform-browser'; +import { SearchRadioComponent } from './search-radio.component'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { setupTestBed } from '@alfresco/adf-core'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; + +describe('SearchRadioComponent', () => { + let fixture: ComponentFixture; + let component: SearchRadioComponent; + + setupTestBed({ + imports: [ ContentTestingModule ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchRadioComponent); + component = fixture.componentInstance; + }); + + describe('Pagination', () => { + it('should show 5 items when pageSize not defined', () => { + component.id = 'checklist'; + component.context = { + queryFragments: { + 'checklist': 'query' + }, + update() {} + }; + component.settings = { options: sizeOptions }; + + component.ngOnInit(); + fixture.detectChanges(); + + const optionElements = fixture.debugElement.queryAll(By.css('mat-radio-button')); + expect(optionElements.length).toEqual(5); + const labels = Array.from(optionElements).map(element => element.nativeElement.innerText); + expect(labels).toEqual(stepOne); + }); + + it('should show all items when pageSize is high', () => { + component.id = 'checklist'; + component.context = { + queryFragments: { + 'checklist': 'query' + }, + update() {} + }; + component.settings = { pageSize: 15, options: sizeOptions }; + component.ngOnInit(); + fixture.detectChanges(); + + const optionElements = fixture.debugElement.queryAll(By.css('mat-radio-button')); + expect(optionElements.length).toEqual(13); + const labels = Array.from(optionElements).map(element => element.nativeElement.innerText); + expect(labels).toEqual(stepThree); + }); + }); + + it('should able to check the radio button', () => { + component.id = 'checklist'; + component.context = { + queryFragments: { + 'checklist': 'query' + }, + update: () => {} + }; + component.settings = { options: sizeOptions }; + spyOn(component.context, 'update').and.stub(); + component.ngOnInit(); + fixture.detectChanges(); + + const optionElements = fixture.debugElement.query(By.css('mat-radio-button')); + optionElements.triggerEventHandler('change', { checked: true }); + + expect(component.context.update).toHaveBeenCalled(); + expect(component.context.queryFragments[component.id]).toBe(sizeOptions[0].value); + }); +}); diff --git a/lib/content-services/src/lib/search/components/search-text/search-text.component.spec.ts b/lib/content-services/src/lib/search/components/search-text/search-text.component.spec.ts index acb055a6b7..aa53a95463 100644 --- a/lib/content-services/src/lib/search/components/search-text/search-text.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-text/search-text.component.spec.ts @@ -16,13 +16,21 @@ */ import { SearchTextComponent } from './search-text.component'; +import { setupTestBed } from '@alfresco/adf-core'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; describe('SearchTextComponent', () => { - + let fixture: ComponentFixture; let component: SearchTextComponent; + setupTestBed({ + imports: [ ContentTestingModule ] + }); + beforeEach(() => { - component = new SearchTextComponent(); + fixture = TestBed.createComponent(SearchTextComponent); + component = fixture.componentInstance; component.id = 'text'; component.settings = { 'pattern': "cm:name:'(.*?)'", @@ -38,7 +46,7 @@ describe('SearchTextComponent', () => { it('should parse value from the context at startup', () => { component.context.queryFragments[component.id] = "cm:name:'secret.pdf'"; - component.ngOnInit(); + fixture.detectChanges(); expect(component.value).toEqual('secret.pdf'); }); @@ -46,7 +54,7 @@ describe('SearchTextComponent', () => { it('should not parse value when pattern not defined', () => { component.settings.pattern = null; component.context.queryFragments[component.id] = "cm:name:'secret.pdf'"; - component.ngOnInit(); + fixture.detectChanges(); expect(component.value).toEqual(''); }); @@ -84,4 +92,25 @@ describe('SearchTextComponent', () => { expect(component.value).toBe(''); expect(component.context.queryFragments[component.id]).toBe(''); }); + + it('should show the custom/default name', async(() => { + component.context.queryFragments[component.id] = "cm:name:'secret.pdf'"; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(component.value).toEqual('secret.pdf'); + const input = fixture.debugElement.nativeElement.querySelector('.mat-form-field-infix input'); + expect(input.value).toEqual('secret.pdf'); + }); + })); + + it('should be able to reset by clicking clear button', async(() => { + component.context.queryFragments[component.id] = "cm:name:'secret.pdf'"; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const clearElement = fixture.debugElement.nativeElement.querySelector('button'); + clearElement.click(); + expect(component.value).toBe(''); + expect(component.context.queryFragments[component.id]).toBe(''); + }); + })); });