mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[MNT-25410] ADW - Saved Searches can load the wrong search set, and t… (#11599)
This commit is contained in:
+5
-2
@@ -53,6 +53,7 @@ describe('SearchFilterChipsComponent', () => {
|
||||
it('should fetch facet fields from response payload and show the already checked items', async () => {
|
||||
spyOn(queryBuilder, 'execute').and.stub();
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -115,6 +116,7 @@ describe('SearchFilterChipsComponent', () => {
|
||||
it('should fetch facet fields from response payload and show the newly checked items', async () => {
|
||||
spyOn(queryBuilder, 'execute').and.stub();
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -176,6 +178,7 @@ describe('SearchFilterChipsComponent', () => {
|
||||
it('should show buckets with 0 values when there are no facet fields on the response payload', async () => {
|
||||
spyOn(queryBuilder, 'execute').and.stub();
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -253,7 +256,7 @@ describe('SearchFilterChipsComponent', () => {
|
||||
|
||||
describe('widgets', () => {
|
||||
it('should not show the disabled widget', async () => {
|
||||
appConfigService.config.search = { categories: disabledCategories };
|
||||
appConfigService.config.search = { id: 'test-config', categories: disabledCategories };
|
||||
queryBuilder.resetToDefaults();
|
||||
|
||||
const chips = await loader.getAllHarnesses(MatChipHarness);
|
||||
@@ -262,7 +265,7 @@ describe('SearchFilterChipsComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the widgets only if configured', async () => {
|
||||
appConfigService.config.search = { categories: simpleCategories };
|
||||
appConfigService.config.search = { id: 'test-config', categories: simpleCategories };
|
||||
queryBuilder.resetToDefaults();
|
||||
|
||||
const chips = await loader.getAllHarnesses(MatChipHarness);
|
||||
|
||||
+6
-3
@@ -80,6 +80,7 @@ describe('SearchFilterComponent', () => {
|
||||
it('should fetch facet fields from response payload and show the already checked items', () => {
|
||||
spyOn(queryBuilder, 'execute').and.stub();
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -138,6 +139,7 @@ describe('SearchFilterComponent', () => {
|
||||
it('should fetch facet fields from response payload and show the newly checked items', () => {
|
||||
spyOn(queryBuilder, 'execute').and.stub();
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -196,6 +198,7 @@ describe('SearchFilterComponent', () => {
|
||||
it('should show buckets with 0 values when there are no facet fields on the response payload', () => {
|
||||
spyOn(queryBuilder, 'execute').and.stub();
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -278,7 +281,7 @@ describe('SearchFilterComponent', () => {
|
||||
});
|
||||
|
||||
it('should not show the disabled widget', async () => {
|
||||
appConfigService.config.search = { categories: disabledCategories };
|
||||
appConfigService.config.search = { id: 'test-config', categories: disabledCategories };
|
||||
queryBuilder.resetToDefaults();
|
||||
|
||||
fixture.detectChanges();
|
||||
@@ -289,7 +292,7 @@ describe('SearchFilterComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the widget in expanded mode', async () => {
|
||||
appConfigService.config.search = { categories: expandedCategories };
|
||||
appConfigService.config.search = { id: 'test-config', categories: expandedCategories };
|
||||
queryBuilder.resetToDefaults();
|
||||
|
||||
fixture.detectChanges();
|
||||
@@ -303,7 +306,7 @@ describe('SearchFilterComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the widgets only if configured', async () => {
|
||||
appConfigService.config.search = { categories: simpleCategories };
|
||||
appConfigService.config.search = { id: 'test-config', categories: simpleCategories };
|
||||
queryBuilder.resetToDefaults();
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
+4
-4
@@ -32,9 +32,9 @@ describe('SearchFormComponent', () => {
|
||||
let component: SearchFormComponent;
|
||||
let queryBuilder: SearchQueryBuilderService;
|
||||
const mockSearchForms: SearchForm[] = [
|
||||
{ default: false, index: 0, name: 'All', selected: false },
|
||||
{ default: true, index: 1, name: 'First', selected: true },
|
||||
{ default: false, index: 2, name: 'Second', selected: false }
|
||||
{ id: 'form-all', default: false, index: 0, name: 'All', selected: false },
|
||||
{ id: 'form-first', default: true, index: 1, name: 'First', selected: true },
|
||||
{ id: 'form-second', default: false, index: 2, name: 'Second', selected: false }
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -75,7 +75,7 @@ describe('SearchFormComponent', () => {
|
||||
});
|
||||
|
||||
it('should not show menu if only one config found', async () => {
|
||||
queryBuilder.searchForms.next([{ name: 'one', selected: true, default: true, index: 0 }]);
|
||||
queryBuilder.searchForms.next([{ id: 'form-one', name: 'one', selected: true, default: true, index: 0 }]);
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = await loader.getHarness(MatButtonHarness.with({ selector: '.adf-search-form' }));
|
||||
|
||||
@@ -41,7 +41,7 @@ export class SearchFormComponent {
|
||||
formChange: EventEmitter<SearchForm> = new EventEmitter<SearchForm>();
|
||||
|
||||
onSelectionChange(form: SearchForm) {
|
||||
this.queryBuilder.updateSelectedConfiguration(form.index);
|
||||
this.queryBuilder.updateSelectedConfiguration(form.id);
|
||||
this.formChange.emit(form);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import { SearchSortingDefinition } from './search-sorting-definition.interface';
|
||||
import { RequestHighlight } from '@alfresco/js-api';
|
||||
|
||||
export interface SearchConfiguration {
|
||||
id: string;
|
||||
include?: string[];
|
||||
fields?: string[];
|
||||
categories?: SearchCategory[];
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
export interface SearchForm {
|
||||
id: string;
|
||||
index: number;
|
||||
name: string;
|
||||
default: boolean;
|
||||
|
||||
@@ -0,0 +1,583 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* 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 { TestBed } from '@angular/core/testing';
|
||||
import { provideRouter, Router } from '@angular/router';
|
||||
import { SearchQueryBuilderService } from './search-query-builder.service';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
import { SearchConfiguration } from '../models/search-configuration.interface';
|
||||
import { FacetFieldBucket } from '../models/facet-field-bucket.interface';
|
||||
import { ResultSetPaging } from '@alfresco/js-api';
|
||||
import { skip } from 'rxjs/operators';
|
||||
|
||||
describe('BaseQueryBuilderService', () => {
|
||||
let service: SearchQueryBuilderService;
|
||||
let appConfig: AppConfigService;
|
||||
let router: Router;
|
||||
|
||||
const mockSearchConfig: SearchConfiguration = {
|
||||
id: 'config-default',
|
||||
categories: [
|
||||
{
|
||||
id: 'cat1',
|
||||
name: 'Category 1',
|
||||
enabled: true,
|
||||
expanded: false,
|
||||
component: {
|
||||
selector: 'test',
|
||||
settings: undefined
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'cat2',
|
||||
name: 'Category 2',
|
||||
enabled: false,
|
||||
expanded: false,
|
||||
component: {
|
||||
selector: 'test',
|
||||
settings: undefined
|
||||
}
|
||||
}
|
||||
],
|
||||
filterQueries: [{ query: 'TYPE:"cm:content"' }],
|
||||
sorting: {
|
||||
options: [
|
||||
{ key: 'name', label: 'Name', type: 'FIELD', field: 'cm:name', ascending: true },
|
||||
{ key: 'date', label: 'Date', type: 'FIELD', field: 'cm:created', ascending: false }
|
||||
],
|
||||
defaults: [{ key: 'name', label: 'Name', type: 'FIELD', field: 'cm:name', ascending: true }]
|
||||
}
|
||||
};
|
||||
|
||||
const mockMultipleConfigs: SearchConfiguration[] = [
|
||||
{ ...mockSearchConfig, id: 'config-1', name: 'Config 1', default: true },
|
||||
{ ...mockSearchConfig, id: 'config-2', name: 'Config 2', default: false },
|
||||
{ ...mockSearchConfig, id: 'config-3', name: 'Config 3', default: false }
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideRouter([]),
|
||||
SearchQueryBuilderService,
|
||||
{
|
||||
provide: AppConfigService,
|
||||
useValue: {
|
||||
get: jasmine.createSpy('get').and.returnValue(mockSearchConfig)
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
service = TestBed.inject(SearchQueryBuilderService);
|
||||
appConfig = TestBed.inject(AppConfigService);
|
||||
router = TestBed.inject(Router);
|
||||
});
|
||||
|
||||
describe('userQuery', () => {
|
||||
it('should set userQuery with parentheses', () => {
|
||||
service.userQuery = 'test query';
|
||||
expect(service.userQuery).toBe('(test query)');
|
||||
});
|
||||
|
||||
it('should trim userQuery', () => {
|
||||
service.userQuery = ' test query ';
|
||||
expect(service.userQuery).toBe('(test query)');
|
||||
});
|
||||
|
||||
it('should return empty string for null input', () => {
|
||||
service.userQuery = null;
|
||||
expect(service.userQuery).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('queryFragments', () => {
|
||||
it('should emit queryFragmentsUpdate when queryFragments change after initial fragments emited', (done) => {
|
||||
service.queryFragmentsUpdate.pipe(skip(1)).subscribe((fragments) => {
|
||||
expect(fragments['testId']).toBe('test query');
|
||||
done();
|
||||
});
|
||||
|
||||
service.queryFragments['testId'] = 'test query';
|
||||
});
|
||||
|
||||
it('should emit queryFragmentsUpdate when setting new queryFragments object after initial fragments emited', (done) => {
|
||||
const newFragments = { id1: 'query1', id2: 'query2' };
|
||||
|
||||
service.queryFragmentsUpdate.pipe(skip(1)).subscribe((fragments) => {
|
||||
expect(fragments).toEqual(newFragments);
|
||||
done();
|
||||
});
|
||||
|
||||
service.queryFragments = newFragments;
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterQueries', () => {
|
||||
it('should add filter query', () => {
|
||||
service.filterQueries = [];
|
||||
service.addFilterQuery('TYPE:"cm:folder"');
|
||||
|
||||
expect(service.filterQueries.length).toBe(1);
|
||||
expect(service.filterQueries[0].query).toBe('TYPE:"cm:folder"');
|
||||
});
|
||||
|
||||
it('should not add duplicate filter query', () => {
|
||||
service.filterQueries = [];
|
||||
service.addFilterQuery('TYPE:"cm:folder"');
|
||||
service.addFilterQuery('TYPE:"cm:folder"');
|
||||
|
||||
expect(service.filterQueries.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should remove filter query', () => {
|
||||
service.filterQueries = [{ query: 'TYPE:"cm:folder"' }, { query: 'TYPE:"cm:content"' }];
|
||||
service.removeFilterQuery('TYPE:"cm:folder"');
|
||||
|
||||
expect(service.filterQueries.length).toBe(1);
|
||||
expect(service.filterQueries[0].query).toBe('TYPE:"cm:content"');
|
||||
});
|
||||
|
||||
it('should not add empty filter query', () => {
|
||||
service.filterQueries = [];
|
||||
service.addFilterQuery('');
|
||||
|
||||
expect(service.filterQueries.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('userFacetBuckets', () => {
|
||||
const mockBucket: FacetFieldBucket = {
|
||||
label: 'bucket1',
|
||||
count: 10,
|
||||
filterQuery: 'field:value1'
|
||||
};
|
||||
|
||||
const mockBucket2: FacetFieldBucket = {
|
||||
label: 'bucket2',
|
||||
count: 5,
|
||||
filterQuery: 'field:value2'
|
||||
};
|
||||
|
||||
it('should add user facet bucket', () => {
|
||||
service.addUserFacetBucket('field1', mockBucket);
|
||||
|
||||
const buckets = service.getUserFacetBuckets('field1');
|
||||
expect(buckets.length).toBe(1);
|
||||
expect(buckets[0].label).toBe('bucket1');
|
||||
});
|
||||
|
||||
it('should not add duplicate bucket', () => {
|
||||
service.addUserFacetBucket('field1', mockBucket);
|
||||
service.addUserFacetBucket('field1', mockBucket);
|
||||
|
||||
const buckets = service.getUserFacetBuckets('field1');
|
||||
expect(buckets.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should remove user facet bucket', () => {
|
||||
service.addUserFacetBucket('field1', mockBucket);
|
||||
service.addUserFacetBucket('field1', mockBucket2);
|
||||
service.removeUserFacetBucket('field1', mockBucket);
|
||||
|
||||
const buckets = service.getUserFacetBuckets('field1');
|
||||
expect(buckets.length).toBe(1);
|
||||
expect(buckets[0].label).toBe('bucket2');
|
||||
});
|
||||
|
||||
it('should reset user facet buckets', () => {
|
||||
service.addUserFacetBucket('field1', mockBucket);
|
||||
service.addUserFacetBucket('field2', mockBucket2);
|
||||
service.resetUserFacetBucket();
|
||||
|
||||
expect(service.getUserFacetBuckets('field1').length).toBe(0);
|
||||
expect(service.getUserFacetBuckets('field2').length).toBe(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('buildQuery', () => {
|
||||
it('should return null when no query is set', () => {
|
||||
service.userQuery = '';
|
||||
expect(service.buildQuery()).toBeNull();
|
||||
});
|
||||
|
||||
it('should build query with userQuery', () => {
|
||||
service.userQuery = 'test';
|
||||
const query = service.buildQuery();
|
||||
|
||||
expect(query).toBeTruthy();
|
||||
expect(query.query.query).toBe('(test)');
|
||||
});
|
||||
|
||||
it('should include scope in query when set', () => {
|
||||
service.userQuery = 'test';
|
||||
service.setScope({ locations: 'nodes' });
|
||||
const query = service.buildQuery();
|
||||
|
||||
expect(query.scope).toEqual({ locations: 'nodes' });
|
||||
});
|
||||
|
||||
it('should include default includes when none configured', () => {
|
||||
service.config = { id: 'test-config', categories: [] };
|
||||
service.userQuery = 'test';
|
||||
const query = service.buildQuery();
|
||||
|
||||
expect(query.include).toContain('path');
|
||||
expect(query.include).toContain('allowableOperations');
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should emit updated event with built query', (done) => {
|
||||
service.userQuery = 'test';
|
||||
|
||||
service.updated.subscribe((query) => {
|
||||
expect(query.query.query).toBe('(test)');
|
||||
done();
|
||||
});
|
||||
|
||||
service.update();
|
||||
});
|
||||
|
||||
it('should emit updated event with provided query body', (done) => {
|
||||
const customQuery = {
|
||||
query: { query: 'custom query', language: 'afts' }
|
||||
};
|
||||
|
||||
service.updated.subscribe((query) => {
|
||||
expect(query.query.query).toBe('custom query');
|
||||
done();
|
||||
});
|
||||
|
||||
service.update(customQuery);
|
||||
});
|
||||
});
|
||||
|
||||
describe('execute', () => {
|
||||
it('should update search query params by default', async () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
service.userQuery = 'test';
|
||||
|
||||
await service.execute();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not update search query params when disabled', async () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
service.userQuery = 'test';
|
||||
|
||||
await service.execute(false);
|
||||
|
||||
expect(router.navigate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit executed event on success', async () => {
|
||||
const mockResult: ResultSetPaging = {
|
||||
list: {
|
||||
entries: [
|
||||
{
|
||||
entry: {
|
||||
id: '1',
|
||||
name: '',
|
||||
nodeType: '',
|
||||
isFolder: false,
|
||||
isFile: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve(mockResult));
|
||||
service.userQuery = 'test';
|
||||
|
||||
const executedSpy = jasmine.createSpy('executedSpy');
|
||||
service.executed.subscribe(executedSpy);
|
||||
|
||||
await service.execute();
|
||||
|
||||
expect(executedSpy).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
|
||||
it('should emit error and empty result on failure', async () => {
|
||||
const mockError = new Error('Search failed');
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.reject(mockError));
|
||||
service.userQuery = 'test';
|
||||
|
||||
const errorSpy = jasmine.createSpy('errorSpy');
|
||||
const executedSpy = jasmine.createSpy('executedSpy');
|
||||
service.error.subscribe(errorSpy);
|
||||
service.executed.subscribe(executedSpy);
|
||||
|
||||
await service.execute();
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(mockError);
|
||||
expect(executedSpy).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
list: jasmine.objectContaining({
|
||||
pagination: { totalItems: 0 },
|
||||
entries: []
|
||||
})
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should update URL params even when query is null', async () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
service.userQuery = '';
|
||||
|
||||
await service.execute();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('sorting', () => {
|
||||
it('should return primary sorting', () => {
|
||||
service.sorting = [
|
||||
{ key: 'name', label: 'Name', type: 'FIELD', field: 'cm:name', ascending: true },
|
||||
{ key: 'date', label: 'Date', type: 'FIELD', field: 'cm:created', ascending: false }
|
||||
];
|
||||
|
||||
const primary = service.getPrimarySorting();
|
||||
expect(primary.key).toBe('name');
|
||||
});
|
||||
|
||||
it('should return null when no sorting defined', () => {
|
||||
service.sorting = [];
|
||||
expect(service.getPrimarySorting()).toBeNull();
|
||||
});
|
||||
|
||||
it('should return sorting options from config', () => {
|
||||
service.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
sorting: {
|
||||
options: [{ key: 'name', label: 'Name', type: 'FIELD', field: 'cm:name', ascending: true }],
|
||||
defaults: []
|
||||
}
|
||||
};
|
||||
|
||||
const options = service.getSortingOptions();
|
||||
expect(options.length).toBe(1);
|
||||
expect(options[0].key).toBe('name');
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple configurations', () => {
|
||||
beforeEach(() => {
|
||||
(appConfig.get as jasmine.Spy).and.returnValue(mockMultipleConfigs);
|
||||
service.resetToDefaults();
|
||||
});
|
||||
|
||||
it('should return default configuration', () => {
|
||||
const config = service.getDefaultConfiguration();
|
||||
expect(config.name).toBe('Config 1');
|
||||
});
|
||||
|
||||
it('should return search form details for multiple configurations', () => {
|
||||
const forms = service.getSearchFormDetails();
|
||||
|
||||
expect(forms.length).toBe(3);
|
||||
expect(forms[0].id).toBe('config-1');
|
||||
expect(forms[0].name).toBe('Config 1');
|
||||
expect(forms[0].default).toBe(true);
|
||||
expect(forms[0].selected).toBe(true);
|
||||
expect(forms[1].id).toBe('config-2');
|
||||
expect(forms[1].name).toBe('Config 2');
|
||||
expect(forms[1].selected).toBe(false);
|
||||
});
|
||||
|
||||
it('should update selected configuration', (done) => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
|
||||
service.configUpdated.subscribe((config) => {
|
||||
expect(config.name).toBe('Config 2');
|
||||
done();
|
||||
});
|
||||
|
||||
service.updateSelectedConfiguration('config-2');
|
||||
});
|
||||
|
||||
it('should update searchForms when configuration changes after initial forms emited', (done) => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
|
||||
let callCount = 0;
|
||||
service.searchForms.pipe(skip(1)).subscribe((forms) => {
|
||||
callCount++;
|
||||
expect(forms[1].selected).toBe(true);
|
||||
expect(forms[0].selected).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
service.updateSelectedConfiguration('config-2');
|
||||
});
|
||||
|
||||
it('should store selectedConfigurationId in filterRawParams', async () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
|
||||
service.updateSelectedConfiguration('config-2');
|
||||
|
||||
expect(service.filterRawParams['selectedConfigurationId']).toBe('config-2');
|
||||
});
|
||||
|
||||
it('should call execute when updating configuration', async () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
service.userQuery = 'test';
|
||||
|
||||
service.updateSelectedConfiguration('config-2');
|
||||
|
||||
expect(router.navigate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('populateFilters and selectedConfiguration restoration', () => {
|
||||
beforeEach(() => {
|
||||
(appConfig.get as jasmine.Spy<<T>(key: string, defaultValue?: T) => T>).and.returnValue(mockMultipleConfigs);
|
||||
service.resetToDefaults();
|
||||
});
|
||||
|
||||
it('should restore selectedConfiguration from populateFilters', (done) => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
|
||||
service.configUpdated.subscribe((config) => {
|
||||
expect(config.name).toBe('Config 3');
|
||||
done();
|
||||
});
|
||||
|
||||
service.populateFilters.next({ selectedConfigurationId: 'config-3', someOtherFilter: 'value' });
|
||||
});
|
||||
|
||||
it('should reset to default configuration when populateFilters has no selectedConfigurationId', (done) => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
|
||||
service.updateSelectedConfiguration('config-3');
|
||||
|
||||
setTimeout(() => {
|
||||
service.configUpdated.subscribe((config) => {
|
||||
expect(config.name).toBe('Config 1');
|
||||
done();
|
||||
});
|
||||
|
||||
service.populateFilters.next({ someOtherFilter: 'value' });
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should not change configuration when populateFilters is empty', () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
const configUpdatedSpy = jasmine.createSpy('configUpdatedSpy');
|
||||
|
||||
service.configUpdated.subscribe(configUpdatedSpy);
|
||||
configUpdatedSpy.calls.reset();
|
||||
|
||||
service.populateFilters.next({});
|
||||
|
||||
expect(configUpdatedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not change configuration when same configuration is already selected', (done) => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
spyOn(service.searchApi, 'search').and.returnValue(Promise.resolve({ list: { entries: [] } } as ResultSetPaging));
|
||||
|
||||
service.updateSelectedConfiguration('config-2');
|
||||
|
||||
setTimeout(() => {
|
||||
const configUpdatedSpy = jasmine.createSpy('configUpdatedSpy');
|
||||
service.configUpdated.subscribe(configUpdatedSpy);
|
||||
|
||||
service.populateFilters.next({ selectedConfigurationId: 'config-2' });
|
||||
|
||||
setTimeout(() => {
|
||||
expect(configUpdatedSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
}, 0);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should update filterRawParams when restoring configuration from populateFilters', (done) => {
|
||||
service.configUpdated.subscribe(() => {
|
||||
expect(service.filterRawParams['selectedConfigurationId']).toBe('config-2');
|
||||
done();
|
||||
});
|
||||
|
||||
service.populateFilters.next({ selectedConfigurationId: 'config-2' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetToDefaults', () => {
|
||||
it('should emit configUpdated', (done) => {
|
||||
service.configUpdated.subscribe((config) => {
|
||||
expect(config).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
|
||||
service.resetToDefaults();
|
||||
});
|
||||
|
||||
it('should emit searchForms', () => {
|
||||
let formsCalled = false;
|
||||
|
||||
service.searchForms.subscribe((forms) => {
|
||||
if (!formsCalled) {
|
||||
formsCalled = true;
|
||||
expect(forms).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
service.resetToDefaults();
|
||||
|
||||
expect(formsCalled).toBe(true);
|
||||
});
|
||||
|
||||
it('should navigate when withNavigate is true', () => {
|
||||
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
|
||||
service.resetToDefaults(true);
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith([], jasmine.objectContaining({ queryParams: { q: null } }));
|
||||
});
|
||||
|
||||
it('should reset categories', () => {
|
||||
service.categories = [
|
||||
{
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
enabled: true,
|
||||
expanded: false,
|
||||
component: {
|
||||
selector: 'test',
|
||||
settings: undefined
|
||||
}
|
||||
}
|
||||
];
|
||||
service.resetToDefaults();
|
||||
|
||||
expect(service.categories.length).toBe(1);
|
||||
expect(service.categories[0].id).toBe('cat1');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -88,10 +88,11 @@ export abstract class BaseQueryBuilderService {
|
||||
|
||||
private encodedQuery: string;
|
||||
private scope: RequestScope;
|
||||
private selectedConfiguration: number;
|
||||
private selectedConfigurationId: string;
|
||||
private _userQuery = '';
|
||||
private _queryFragments: { [id: string]: string } = {};
|
||||
|
||||
private readonly selectedConfigurationKey = 'selectedConfigurationId';
|
||||
private readonly queryFragmentsHandler: ProxyHandler<{ [key: string]: any }> = {
|
||||
set: (target: { [key: string]: any }, property: string, value: any) => {
|
||||
target[property as keyof typeof target] = value;
|
||||
@@ -121,7 +122,8 @@ export abstract class BaseQueryBuilderService {
|
||||
}
|
||||
|
||||
config: SearchConfiguration = {
|
||||
categories: []
|
||||
categories: [],
|
||||
id: 'SEARCH.UNKNOWN_CONFIGURATION'
|
||||
};
|
||||
|
||||
// TODO: to be supported in future iterations
|
||||
@@ -133,6 +135,8 @@ export abstract class BaseQueryBuilderService {
|
||||
) {
|
||||
this.resetToDefaults();
|
||||
this._queryFragments = this.createQueryFragmentsProxy({});
|
||||
|
||||
this.populateFilters.subscribe((filters) => this.handleSelectedConfigurationChange(filters));
|
||||
}
|
||||
|
||||
public abstract loadConfiguration(): SearchConfiguration | SearchConfiguration[];
|
||||
@@ -158,8 +162,8 @@ export abstract class BaseQueryBuilderService {
|
||||
const configurations = this.loadConfiguration();
|
||||
|
||||
if (Array.isArray(configurations)) {
|
||||
if (this.selectedConfiguration !== undefined) {
|
||||
return configurations[this.selectedConfiguration];
|
||||
if (this.selectedConfigurationId !== undefined) {
|
||||
return configurations.find((config) => config.id === this.selectedConfigurationId);
|
||||
}
|
||||
|
||||
return configurations.find((configuration) => configuration.default);
|
||||
@@ -167,15 +171,19 @@ export abstract class BaseQueryBuilderService {
|
||||
return configurations;
|
||||
}
|
||||
|
||||
public updateSelectedConfiguration(index: number): void {
|
||||
public updateSelectedConfiguration(id: string): void {
|
||||
const currentConfig = this.loadConfiguration();
|
||||
if (Array.isArray(currentConfig) && currentConfig[index] !== undefined) {
|
||||
this.selectedConfiguration = index;
|
||||
this.searchForms.next(this.getSearchFormDetails());
|
||||
this.resetSearchOptions();
|
||||
this.setUpSearchConfiguration(currentConfig[index]);
|
||||
this.configUpdated.next(currentConfig[index]);
|
||||
this.update();
|
||||
if (Array.isArray(currentConfig)) {
|
||||
const selectedConfig = currentConfig.find((config) => config.id === id);
|
||||
if (selectedConfig) {
|
||||
this.selectedConfigurationId = id;
|
||||
this.searchForms.next(this.getSearchFormDetails());
|
||||
this.resetSearchOptions();
|
||||
this.setUpSearchConfiguration(selectedConfig);
|
||||
this.filterRawParams[this.selectedConfigurationKey] = id;
|
||||
this.configUpdated.next(selectedConfig);
|
||||
this.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,14 +204,16 @@ export abstract class BaseQueryBuilderService {
|
||||
const configurations = this.loadConfiguration();
|
||||
if (Array.isArray(configurations)) {
|
||||
return configurations.map((configuration, index) => ({
|
||||
id: configuration.id,
|
||||
index,
|
||||
name: configuration.name || 'SEARCH.UNKNOWN_CONFIGURATION',
|
||||
default: configuration.default || false,
|
||||
selected: this.selectedConfiguration !== undefined ? index === this.selectedConfiguration : configuration.default
|
||||
selected: this.selectedConfigurationId !== undefined ? configuration.id === this.selectedConfigurationId : configuration.default
|
||||
}));
|
||||
} else if (configurations) {
|
||||
return [
|
||||
{
|
||||
id: 'SEARCH.UNKNOWN_CONFIGURATION',
|
||||
index: 0,
|
||||
name: configurations.name || 'SEARCH.UNKNOWN_CONFIGURATION',
|
||||
default: true,
|
||||
@@ -364,11 +374,11 @@ export abstract class BaseQueryBuilderService {
|
||||
*/
|
||||
async execute(updateQueryParams = true, queryBody?: SearchRequest) {
|
||||
try {
|
||||
if (updateQueryParams) {
|
||||
this.updateSearchQueryParams();
|
||||
}
|
||||
const query = queryBody ? queryBody : this.buildQuery();
|
||||
if (query) {
|
||||
if (updateQueryParams) {
|
||||
this.updateSearchQueryParams();
|
||||
}
|
||||
const resultSetPaging: ResultSetPaging = await this.searchApi.search(query);
|
||||
this.executed.next(resultSetPaging);
|
||||
}
|
||||
@@ -654,4 +664,40 @@ export abstract class BaseQueryBuilderService {
|
||||
private createQueryFragmentsProxy(target: { [key: string]: any }): { [key: string]: any } {
|
||||
return new Proxy(target, this.queryFragmentsHandler);
|
||||
}
|
||||
|
||||
private setSelectedConfiguration(id: string): void {
|
||||
const currentConfig = this.loadConfiguration();
|
||||
if (Array.isArray(currentConfig)) {
|
||||
const selectedConfig = currentConfig.find((config) => config.id === id);
|
||||
if (selectedConfig) {
|
||||
this.selectedConfigurationId = id;
|
||||
this.searchForms.next(this.getSearchFormDetails());
|
||||
this.setUpSearchConfiguration(selectedConfig);
|
||||
this.filterRawParams[this.selectedConfigurationKey] = id;
|
||||
this.configUpdated.next(selectedConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleSelectedConfigurationChange(filters: { [key: string]: string }): void {
|
||||
if (Object.keys(filters ?? {}).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newSelectedConfig = filters?.[this.selectedConfigurationKey];
|
||||
|
||||
if (newSelectedConfig) {
|
||||
if (newSelectedConfig !== this.selectedConfigurationId) {
|
||||
this.setSelectedConfiguration(newSelectedConfig);
|
||||
}
|
||||
} else {
|
||||
const configurations = this.loadConfiguration();
|
||||
if (Array.isArray(configurations)) {
|
||||
const defaultConfig = configurations.find(config => config.default);
|
||||
if (defaultConfig && this.selectedConfigurationId !== defaultConfig.id) {
|
||||
this.setSelectedConfiguration(defaultConfig.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
label: 'label1',
|
||||
@@ -97,6 +98,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
label: 'label1',
|
||||
@@ -140,6 +142,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: []
|
||||
@@ -163,6 +166,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -196,6 +200,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
|
||||
it('should filter response facet fields based on search filter config method', () => {
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: { fields: [{ label: 'f1', field: 'f1' }] },
|
||||
facetQueries: {
|
||||
@@ -247,6 +252,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -286,6 +292,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
|
||||
it('should fetch facet fields from response payload and update the existing bucket values', () => {
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -343,6 +350,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: { fields: [{ label: 'f1', field: 'f1' }] },
|
||||
facetQueries: { queries: [] }
|
||||
@@ -374,6 +382,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
it('should fetch facet intervals from response payload', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetIntervals: {
|
||||
intervals: [
|
||||
@@ -426,6 +435,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
it('should filter out the fetched facet intervals that have bucket values less than their set mincount', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetIntervals: {
|
||||
intervals: [
|
||||
@@ -479,6 +489,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
it('should sort the facets based on the order set in the settings', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
label: 'Query 1',
|
||||
@@ -525,6 +536,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
spyOn(categoryService, 'getCategory').and.returnValue(of({ entry }));
|
||||
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -569,6 +581,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
it('should extract creator and modifier facets and create tabbed facet for them', () => {
|
||||
searchFacetFiltersService.responseFacets = null;
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -671,6 +684,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
|
||||
it('should sort the buckets by label', () => {
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: { queries: [] },
|
||||
facetFields: {
|
||||
@@ -690,6 +704,7 @@ describe('SearchFacetFiltersService', () => {
|
||||
|
||||
it('should sort the buckets by count', () => {
|
||||
queryBuilder.config = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: { queries: [] },
|
||||
facetFields: {
|
||||
|
||||
+11
-5
@@ -45,7 +45,8 @@ describe('SearchHeaderQueryBuilderService', () => {
|
||||
|
||||
it('should load the configuration from app config', () => {
|
||||
TestBed.runInInjectionContext(() => {
|
||||
const config = {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true },
|
||||
{ id: 'cat2', enabled: true }
|
||||
@@ -71,7 +72,8 @@ describe('SearchHeaderQueryBuilderService', () => {
|
||||
|
||||
it('should return the category assigned to a column key', () => {
|
||||
TestBed.runInInjectionContext(() => {
|
||||
const config = {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [
|
||||
{ id: 'cat1', columnKey: 'fake-key-1', enabled: true },
|
||||
{ id: 'cat2', columnKey: 'fake-key-2', enabled: true }
|
||||
@@ -92,6 +94,7 @@ describe('SearchHeaderQueryBuilderService', () => {
|
||||
it('should return operator for a category by id', () => {
|
||||
TestBed.runInInjectionContext(() => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [
|
||||
{ id: 'cat1', columnKey: 'fake-key-1', enabled: true, component: { settings: { operator: 'operator' } } },
|
||||
{ id: 'cat2', columnKey: 'fake-key-2', enabled: true }
|
||||
@@ -118,7 +121,8 @@ describe('SearchHeaderQueryBuilderService', () => {
|
||||
|
||||
it('should add the extra filter for the parent node', () => {
|
||||
TestBed.runInInjectionContext(() => {
|
||||
const config = {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true },
|
||||
{ id: 'cat2', enabled: true }
|
||||
@@ -141,7 +145,8 @@ describe('SearchHeaderQueryBuilderService', () => {
|
||||
TestBed.runInInjectionContext(() => {
|
||||
const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }];
|
||||
|
||||
const config = {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [
|
||||
{ id: 'cat1', enabled: true },
|
||||
{ id: 'cat2', enabled: true }
|
||||
@@ -162,7 +167,8 @@ describe('SearchHeaderQueryBuilderService', () => {
|
||||
TestBed.runInInjectionContext(() => {
|
||||
const activeFilter = 'FakeColumn';
|
||||
|
||||
const config = {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true }],
|
||||
filterQueries: [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id' }]
|
||||
} as SearchConfiguration;
|
||||
|
||||
@@ -35,7 +35,7 @@ const buildConfig = (searchSettings = {}): AppConfigService => {
|
||||
};
|
||||
|
||||
describe('SearchQueryBuilder (runtime config)', () => {
|
||||
const runtimeConfig: SearchConfiguration = {};
|
||||
const runtimeConfig: SearchConfiguration = { id: 'runtime-config' };
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@@ -55,6 +55,7 @@ describe('SearchQueryBuilder (runtime config)', () => {
|
||||
|
||||
it('should prioritise runtime config over configuration file', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'file-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
|
||||
};
|
||||
@@ -96,6 +97,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should reset to defaults', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
|
||||
};
|
||||
@@ -133,6 +135,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should use only enabled categories', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: false } as any, { id: 'cat3', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -144,6 +147,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should fetch filter queries from config', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
|
||||
};
|
||||
@@ -212,6 +216,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should fetch facet query from config', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
@@ -229,6 +234,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should not fetch empty facet query from the config', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [{ query: 'q1', label: 'query1' }]
|
||||
@@ -245,6 +251,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should fetch facet from the config by label', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -262,6 +269,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should not fetch facet from the config by label', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -278,6 +286,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should fetch facets from the config by label with spaces and return field with request compatible label (escaped)', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [],
|
||||
facetFields: {
|
||||
fields: [{ field: 'content.size', mincount: 1, label: 'Label with spaces' }]
|
||||
@@ -292,6 +301,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should require a query fragment to build query', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -303,6 +313,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with single fragment', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -314,6 +325,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with multiple fragments', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -327,6 +339,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom fields', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
fields: ['field1', 'field2'],
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
@@ -340,6 +353,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with empty custom fields', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
fields: [],
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
@@ -352,6 +366,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom filter queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -364,6 +379,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom facet queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetQueries: {
|
||||
queries: [{ query: 'q1', label: 'q2', group: 'group-name' }]
|
||||
@@ -378,6 +394,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom facet fields', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -404,6 +421,7 @@ describe('SearchQueryBuilder', () => {
|
||||
};
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetFields: {
|
||||
fields: [
|
||||
@@ -438,6 +456,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with custom facet intervals', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetIntervals: {
|
||||
intervals: [
|
||||
@@ -482,6 +501,7 @@ describe('SearchQueryBuilder', () => {
|
||||
};
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any],
|
||||
facetIntervals: {
|
||||
intervals: [
|
||||
@@ -518,6 +538,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build query with sorting', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
fields: [],
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
|
||||
};
|
||||
@@ -533,6 +554,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should use pagination settings', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -548,6 +570,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should build final request with user and custom queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -581,6 +604,7 @@ describe('SearchQueryBuilder', () => {
|
||||
];
|
||||
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -598,6 +622,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should use highlight in the queries', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
highlight: {
|
||||
prefix: 'my-prefix',
|
||||
postfix: 'my-postfix',
|
||||
@@ -617,6 +642,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should emit error event', () => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -631,6 +657,7 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should emit empty results on error', (done) => {
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
categories: [{ id: 'cat1', enabled: true } as any]
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -656,6 +683,7 @@ describe('SearchQueryBuilder', () => {
|
||||
it('should fetch the include config from the app config', () => {
|
||||
const includeConfig = ['path', 'allowableOperations', 'properties'];
|
||||
const config: SearchConfiguration = {
|
||||
id: 'test-config',
|
||||
include: includeConfig
|
||||
};
|
||||
const builder = createQueryBuilder(config);
|
||||
@@ -706,10 +734,9 @@ describe('SearchQueryBuilder', () => {
|
||||
|
||||
it('should encode query from filter raw params and update query params on executing query', (done) => {
|
||||
spyOn(router, 'navigate');
|
||||
const builder = createQueryBuilder();
|
||||
builder.userQuery = 'nuka cola quantum';
|
||||
builder.executed.subscribe(() => {
|
||||
expect(builder.filterRawParams).toEqual({ userQuery: '(nuka cola quantum)' });
|
||||
service.userQuery = 'nuka cola quantum';
|
||||
service.filterRawParams = { userQuery: '(nuka cola quantum)' };
|
||||
service.executed.subscribe(() => {
|
||||
expect(router.navigate).toHaveBeenCalledWith([], {
|
||||
relativeTo: activatedRoute,
|
||||
queryParams: { q: 'eyJ1c2VyUXVlcnkiOiIobnVrYSBjb2xhIHF1YW50dW0pIn0=' },
|
||||
@@ -717,17 +744,15 @@ describe('SearchQueryBuilder', () => {
|
||||
});
|
||||
done();
|
||||
});
|
||||
builder.execute();
|
||||
service.execute();
|
||||
});
|
||||
|
||||
it('should encode query from filter raw params and update query params on navigating to search', async () => {
|
||||
spyOn(router, 'navigate');
|
||||
const builder = createQueryBuilder();
|
||||
await builder.navigateToSearch('test query', '/search');
|
||||
service.filterRawParams = { userQuery: '(test query)' };
|
||||
await service.navigateToSearch('test query', '/search');
|
||||
|
||||
expect(builder.filterRawParams).toEqual({ userQuery: '(test query)' });
|
||||
expect(router.navigate).toHaveBeenCalledWith([], {
|
||||
relativeTo: activatedRoute,
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/search'], {
|
||||
queryParams: { q: 'eyJ1c2VyUXVlcnkiOiIodGVzdCBxdWVyeSkifQ==' },
|
||||
queryParamsHandling: 'merge'
|
||||
});
|
||||
@@ -739,18 +764,21 @@ describe('SearchQueryBuilder', () => {
|
||||
beforeEach(() => {
|
||||
configs = [
|
||||
{
|
||||
id: 'config1',
|
||||
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }],
|
||||
name: 'config1',
|
||||
default: true
|
||||
},
|
||||
{
|
||||
id: 'config2',
|
||||
categories: [{ id: 'mouse', enabled: true } as any],
|
||||
filterQueries: [{ query: 'query1' }, { query: 'query2' }],
|
||||
name: 'config2',
|
||||
default: false
|
||||
},
|
||||
{
|
||||
id: 'config3',
|
||||
categories: [{ id: 'cat_and_mouse', enabled: true } as any],
|
||||
default: false
|
||||
}
|
||||
@@ -775,28 +803,28 @@ describe('SearchQueryBuilder', () => {
|
||||
it('should list available search form names', (done) => {
|
||||
builder.searchForms.subscribe((forms) => {
|
||||
expect(forms).toEqual([
|
||||
{ index: 0, name: 'config1', default: true, selected: true },
|
||||
{ index: 1, name: 'config2', default: false, selected: false },
|
||||
{ index: 2, name: 'SEARCH.UNKNOWN_CONFIGURATION', default: false, selected: false }
|
||||
{ id: 'config1', index: 0, name: 'config1', default: true, selected: true },
|
||||
{ id: 'config2', index: 1, name: 'config2', default: false, selected: false },
|
||||
{ id: 'config3', index: 2, name: 'SEARCH.UNKNOWN_CONFIGURATION', default: false, selected: false }
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow the user switch the form', () => {
|
||||
builder.updateSelectedConfiguration(1);
|
||||
builder.updateSelectedConfiguration('config2');
|
||||
|
||||
expect(builder.categories.length).toBe(1);
|
||||
expect(builder.filterQueries.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should keep the selected configuration value', (done) => {
|
||||
builder.updateSelectedConfiguration(1);
|
||||
builder.updateSelectedConfiguration('config2');
|
||||
builder.searchForms.subscribe((forms) => {
|
||||
expect(forms).toEqual([
|
||||
{ index: 0, name: 'config1', default: true, selected: false },
|
||||
{ index: 1, name: 'config2', default: false, selected: true },
|
||||
{ index: 2, name: 'SEARCH.UNKNOWN_CONFIGURATION', default: false, selected: false }
|
||||
{ id: 'config1', index: 0, name: 'config1', default: true, selected: false },
|
||||
{ id: 'config2', index: 1, name: 'config2', default: false, selected: true },
|
||||
{ id: 'config3', index: 2, name: 'SEARCH.UNKNOWN_CONFIGURATION', default: false, selected: false }
|
||||
]);
|
||||
done();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user