([
- { name: 'Folder', value: `TYPE:'cm:folder'`, checked: true },
- { name: 'Document', value: `TYPE:'cm:content'`, checked: true }
- ]);
-
- component.reset();
-
- expect(component.context.update).toHaveBeenCalled();
- expect(component.context.queryFragments[component.id]).toBe('');
- });
-
- describe('Pagination', () => {
- it('should show 5 items when pageSize not defined', async () => {
- component.id = 'checklist';
- component.context = {
- queryFragments: {
- checklist: 'query'
- },
- update: () => {}
- } as any;
- component.settings = { options: sizeOptions } as any;
-
- component.ngOnInit();
- fixture.detectChanges();
-
- const options = await loader.getAllHarnesses(MatCheckboxHarness);
- expect(options.length).toEqual(5);
-
- const labels = await Promise.all(Array.from(options).map(async (element) => element.getLabelText()));
- expect(labels).toEqual(stepOne);
- });
-
- it('should show all items when pageSize is high', async () => {
- component.id = 'checklist';
- component.context = {
- queryFragments: {
- checklist: 'query'
- },
- update: () => {}
- } as any;
- component.settings = { pageSize: 15, options: sizeOptions } as any;
- component.ngOnInit();
- fixture.detectChanges();
-
- const options = await loader.getAllHarnesses(MatCheckboxHarness);
- expect(options.length).toEqual(13);
-
- const labels = await Promise.all(Array.from(options).map(async (element) => element.getLabelText()));
- expect(labels).toEqual(stepThree);
- });
- });
-
- it('should able to check/reset the checkbox', async () => {
- component.id = 'checklist';
- component.context = {
- queryFragments: {
- checklist: 'query'
- },
- update: () => {}
- } as any;
- component.settings = { options: sizeOptions } as any;
- spyOn(component, 'submitValues').and.stub();
- component.ngOnInit();
- fixture.detectChanges();
-
- const checkbox = await loader.getHarness(MatCheckboxHarness);
- await checkbox.check();
-
- expect(component.submitValues).toHaveBeenCalled();
-
- const clearAllElement = fixture.debugElement.query(By.css('button[title="SEARCH.FILTER.ACTIONS.CLEAR-ALL"]'));
- clearAllElement.triggerEventHandler('click', {});
- fixture.detectChanges();
-
- expect(await checkbox.isChecked()).toBe(false);
+ expect(getSearchFilter()).toBeDefined();
});
});
diff --git a/lib/content-services/src/lib/search/components/search-properties/search-properties.component.html b/lib/content-services/src/lib/search/components/search-properties/search-properties.component.html
index 37e8ce454f..bd1995160c 100644
--- a/lib/content-services/src/lib/search/components/search-properties/search-properties.component.html
+++ b/lib/content-services/src/lib/search/components/search-properties/search-properties.component.html
@@ -46,6 +46,7 @@
{{ 'SEARCH.SEARCH_PROPERTIES.FILE_TYPE' | translate }}
{
let component: SearchPropertiesComponent;
@@ -66,6 +66,15 @@ describe('SearchPropertiesComponent', () => {
fixture = TestBed.createComponent(SearchPropertiesComponent);
component = fixture.componentInstance;
+ component.id = 'properties';
+ component.context = {
+ queryFragments: {
+ properties: ''
+ },
+ filterRawParams: {},
+ populateFilters: new ReplaySubject(1),
+ update: jasmine.createSpy('update')
+ } as any;
});
describe('File size', () => {
@@ -187,14 +196,11 @@ describe('SearchPropertiesComponent', () => {
const nameField = 'cm:name';
beforeEach(() => {
- component.id = 'properties';
component.settings = {
field: `${sizeField},${nameField}`
};
- component.context = TestBed.inject(SearchQueryBuilderService);
fixture.detectChanges();
spyOn(component.displayValue$, 'next');
- spyOn(component.context, 'update');
});
it('should not search when settings is not set', () => {
@@ -203,7 +209,6 @@ describe('SearchPropertiesComponent', () => {
component.submitValues();
expect(component.displayValue$.next).not.toHaveBeenCalled();
- expect(component.context.queryFragments[component.id]).toBeUndefined();
expect(component.context.update).not.toHaveBeenCalled();
});
@@ -219,6 +224,10 @@ describe('SearchPropertiesComponent', () => {
component.submitValues();
expect(component.displayValue$.next).toHaveBeenCalledWith('');
expect(component.context.queryFragments[component.id]).toBe('');
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: undefined,
+ fileSizeCondition: { fileSize: null, fileSizeOperator: FileSizeOperator.AT_LEAST, fileSizeUnit: FileSizeUnit.KB }
+ });
expect(component.context.update).toHaveBeenCalled();
});
@@ -230,6 +239,14 @@ describe('SearchPropertiesComponent', () => {
'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_LEAST 321 SEARCH.SEARCH_PROPERTIES.FILE_SIZE_UNIT_ABBREVIATION.KB'
);
expect(component.context.queryFragments[component.id]).toBe(`${sizeField}:[328704 TO MAX]`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: undefined,
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_LEAST',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.KB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
@@ -247,6 +264,14 @@ describe('SearchPropertiesComponent', () => {
'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST 321 SEARCH.SEARCH_PROPERTIES.FILE_SIZE_UNIT_ABBREVIATION.MB'
);
expect(component.context.queryFragments[component.id]).toBe(`${sizeField}:[0 TO 336592896]`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: undefined,
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.MB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
@@ -264,6 +289,14 @@ describe('SearchPropertiesComponent', () => {
'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.EXACTLY 321 SEARCH.SEARCH_PROPERTIES.FILE_SIZE_UNIT_ABBREVIATION.GB'
);
expect(component.context.queryFragments[component.id]).toBe(`${sizeField}:[344671125504 TO 344671125504]`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: undefined,
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.EXACTLY',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.GB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
@@ -274,6 +307,14 @@ describe('SearchPropertiesComponent', () => {
component.submitValues();
expect(component.displayValue$.next).toHaveBeenCalledWith('pdf');
expect(component.context.queryFragments[component.id]).toBe(`${nameField}:("*.${extension.value}")`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: ['pdf'],
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_LEAST',
+ fileSize: null,
+ fileSizeUnit: FileSizeUnit.KB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
@@ -283,6 +324,14 @@ describe('SearchPropertiesComponent', () => {
component.submitValues();
expect(component.displayValue$.next).toHaveBeenCalledWith('pdf, txt');
expect(component.context.queryFragments[component.id]).toBe(`${nameField}:("*.pdf" OR "*.txt")`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: ['pdf', 'txt'],
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_LEAST',
+ fileSize: null,
+ fileSizeUnit: FileSizeUnit.KB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
@@ -295,6 +344,14 @@ describe('SearchPropertiesComponent', () => {
'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_LEAST 321 SEARCH.SEARCH_PROPERTIES.FILE_SIZE_UNIT_ABBREVIATION.KB, pdf, txt'
);
expect(component.context.queryFragments[component.id]).toBe(`${sizeField}:[328704 TO MAX] AND ${nameField}:("*.pdf" OR "*.txt")`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: ['pdf', 'txt'],
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_LEAST',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.KB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
});
@@ -377,14 +434,12 @@ describe('SearchPropertiesComponent', () => {
});
it('should clear the queryFragments for the component id and call update', () => {
- component.context = TestBed.inject(SearchQueryBuilderService);
- component.id = 'test-id';
component.context.queryFragments[component.id] = 'test-query';
fixture.detectChanges();
- spyOn(component.context, 'update');
component.reset();
expect(component.context.queryFragments[component.id]).toBe('');
+ expect(component.context.filterRawParams[component.id]).toBeUndefined();
expect(component.context.update).toHaveBeenCalled();
});
});
@@ -411,20 +466,25 @@ describe('SearchPropertiesComponent', () => {
it('should search based on passed value', () => {
const sizeField = 'content.size';
const nameField = 'cm:name';
- component.id = 'properties';
component.settings = {
field: `${sizeField},${nameField}`
};
- component.context = TestBed.inject(SearchQueryBuilderService);
component.ngOnInit();
spyOn(component.displayValue$, 'next');
- spyOn(component.context, 'update');
component.setValue(searchProperties);
expect(component.displayValue$.next).toHaveBeenCalledWith(
'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST 321 SEARCH.SEARCH_PROPERTIES.FILE_SIZE_UNIT_ABBREVIATION.MB, pdf, txt'
);
expect(component.context.queryFragments[component.id]).toBe(`${sizeField}:[0 TO 336592896] AND ${nameField}:("*.pdf" OR "*.txt")`);
+ expect(component.context.filterRawParams[component.id]).toEqual({
+ fileExtensions: ['pdf', 'txt'],
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.MB
+ }
+ });
expect(component.context.update).toHaveBeenCalled();
});
});
@@ -470,4 +530,37 @@ describe('SearchPropertiesComponent', () => {
).toBeTrue();
});
});
+
+ it('should populate filter state when populate filters event has been observed', () => {
+ component.settings = {
+ field: 'field'
+ };
+ component.context.filterLoaded = new ReplaySubject(1);
+ spyOn(component.context.filterLoaded, 'next').and.stub();
+ spyOn(component.displayValue$, 'next').and.stub();
+ fixture.detectChanges();
+ component.context.populateFilters.next({
+ properties: {
+ fileExtensions: ['pdf', 'txt'],
+ fileSizeCondition: {
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.MB
+ }
+ }
+ });
+ fixture.detectChanges();
+
+ expect(component.displayValue$.next).toHaveBeenCalledWith(
+ 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST 321 SEARCH.SEARCH_PROPERTIES.FILE_SIZE_UNIT_ABBREVIATION.MB, pdf, txt'
+ );
+ expect(component.selectedExtensions).toEqual([{ value: 'pdf' }, { value: 'txt' }]);
+ expect(component.preselectedOptions).toEqual([{ value: 'pdf' }, { value: 'txt' }]);
+ expect(component.form.value).toEqual({
+ fileSizeOperator: 'SEARCH.SEARCH_PROPERTIES.FILE_SIZE_OPERATOR.AT_MOST',
+ fileSize: 321,
+ fileSizeUnit: FileSizeUnit.MB
+ });
+ expect(component.context.filterLoaded.next).toHaveBeenCalled();
+ });
});
diff --git a/lib/content-services/src/lib/search/components/search-properties/search-properties.component.ts b/lib/content-services/src/lib/search/components/search-properties/search-properties.component.ts
index 2ea947d3d7..538871f82e 100644
--- a/lib/content-services/src/lib/search/components/search-properties/search-properties.component.ts
+++ b/lib/content-services/src/lib/search/components/search-properties/search-properties.component.ts
@@ -20,7 +20,7 @@ import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { FileSizeCondition } from './file-size-condition';
import { FileSizeOperator } from './file-size-operator.enum';
import { FileSizeUnit } from './file-size-unit.enum';
-import { Subject } from 'rxjs';
+import { ReplaySubject, Subject } from 'rxjs';
import { SearchWidgetSettings } from '../../models/search-widget-settings.interface';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
import { SearchProperties } from './search-properties';
@@ -31,6 +31,7 @@ import { CommonModule } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { SearchChipAutocompleteInputComponent } from '../search-chip-autocomplete-input';
+import { first } from 'rxjs/operators';
@Component({
selector: 'adf-search-properties',
@@ -45,8 +46,9 @@ export class SearchPropertiesComponent implements OnInit, AfterViewChecked, Sear
settings?: SearchWidgetSettings;
context?: SearchQueryBuilderService;
startValue: SearchProperties;
- displayValue$ = new Subject();
+ displayValue$ = new ReplaySubject(1);
autocompleteOptions: AutocompleteOption[] = [];
+ preselectedOptions: AutocompleteOption[] = [];
private _form = this.formBuilder.nonNullable.group({
fileSizeOperator: FileSizeOperator.AT_LEAST,
@@ -85,6 +87,10 @@ export class SearchPropertiesComponent implements OnInit, AfterViewChecked, Sear
return this._reset$;
}
+ get selectedExtensions(): AutocompleteOption[] {
+ return this.parseToAutocompleteOptions(this._selectedExtensions);
+ }
+
set selectedExtensions(extensions: AutocompleteOption[]) {
this._selectedExtensions = this.parseFromAutocompleteOptions(extensions);
}
@@ -102,6 +108,22 @@ export class SearchPropertiesComponent implements OnInit, AfterViewChecked, Sear
if (this.startValue) {
this.setValue(this.startValue);
}
+ this.context.populateFilters
+ .asObservable()
+ .pipe(first())
+ .subscribe((filtersQueries) => {
+ if (filtersQueries[this.id]) {
+ filtersQueries[this.id].fileSizeCondition.fileSizeUnit = this.fileSizeUnits.find(
+ (fileSizeUnit) => fileSizeUnit.bytes === filtersQueries[this.id].fileSizeCondition.fileSizeUnit.bytes
+ );
+ this.form.patchValue(filtersQueries[this.id].fileSizeCondition);
+ this.form.updateValueAndValidity();
+ this._selectedExtensions = filtersQueries[this.id].fileExtensions ?? [];
+ this.preselectedOptions = this.parseToAutocompleteOptions(this._selectedExtensions);
+ this.submitValues(false);
+ this.context.filterLoaded.next();
+ }
+ });
}
ngAfterViewChecked() {
@@ -164,13 +186,20 @@ export class SearchPropertiesComponent implements OnInit, AfterViewChecked, Sear
this.form.reset();
if (this.id && this.context) {
this.context.queryFragments[this.id] = '';
+ this.context.filterRawParams[this.id] = undefined;
this.context.update();
}
this.reset$.next();
this.displayValue$.next('');
}
- submitValues() {
+ submitValues(updateContext = true) {
+ if (this.context?.filterRawParams) {
+ this.context.filterRawParams[this.id] = {
+ fileExtensions: this._selectedExtensions,
+ fileSizeCondition: this.form.value
+ };
+ }
if (this.settings && this.context) {
let query = '';
let displayedValue = '';
@@ -200,7 +229,9 @@ export class SearchPropertiesComponent implements OnInit, AfterViewChecked, Sear
}
this.displayValue$.next(displayedValue);
this.context.queryFragments[this.id] = query;
- this.context.update();
+ if (updateContext) {
+ this.context.update();
+ }
}
}
@@ -217,7 +248,7 @@ export class SearchPropertiesComponent implements OnInit, AfterViewChecked, Sear
setValue(searchProperties: SearchProperties) {
this.form.patchValue(searchProperties.fileSizeCondition);
- this.selectedExtensions = this.parseToAutocompleteOptions(searchProperties.fileExtensions);
+ this.selectedExtensions = this.parseToAutocompleteOptions(searchProperties.fileExtensions ?? []);
this.submitValues();
}
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
index 6626386a0c..758d78ced8 100644
--- 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
@@ -22,6 +22,7 @@ import { ContentTestingModule } from '../../../testing/content.testing.module';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatRadioButtonHarness, MatRadioGroupHarness } from '@angular/material/radio/testing';
+import { ReplaySubject } from 'rxjs';
describe('SearchRadioComponent', () => {
let loader: HarnessLoader;
@@ -36,20 +37,20 @@ describe('SearchRadioComponent', () => {
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
+ component.id = 'radio';
+ component.context = {
+ queryFragments: {
+ radio: 'query'
+ },
+ filterRawParams: {},
+ populateFilters: new ReplaySubject(1),
+ update: jasmine.createSpy('update')
+ } as any;
+ component.settings = { options: sizeOptions } as any;
});
describe('Pagination', () => {
it('should show 5 items when pageSize not defined', async () => {
- component.id = 'radio';
- component.context = {
- queryFragments: {
- radio: 'query'
- },
- update: () => {}
- } as any;
- component.settings = { options: sizeOptions } as any;
-
- component.ngOnInit();
fixture.detectChanges();
const options = await loader.getAllHarnesses(MatRadioButtonHarness);
@@ -60,15 +61,7 @@ describe('SearchRadioComponent', () => {
});
it('should show all items when pageSize is high', async () => {
- component.id = 'radio';
- component.context = {
- queryFragments: {
- radio: 'query'
- },
- update: () => {}
- } as any;
- component.settings = { pageSize: 15, options: sizeOptions } as any;
- component.ngOnInit();
+ component.settings['pageSize'] = 15;
fixture.detectChanges();
const options = await loader.getAllHarnesses(MatRadioButtonHarness);
@@ -80,18 +73,40 @@ describe('SearchRadioComponent', () => {
});
it('should able to check the radio button', async () => {
- component.id = 'radio';
- component.context = {
- queryFragments: {
- radio: 'query'
- },
- update: () => {}
- } as any;
- component.settings = { options: sizeOptions } as any;
-
const group = await loader.getHarness(MatRadioGroupHarness);
- await group.checkRadioButton({ selector: `[data-automation-id="search-radio-${sizeOptions[0].name}"]` });
+ await group.checkRadioButton({ selector: `[data-automation-id="search-radio-${sizeOptions[1].name}"]` });
+
+ expect(component.context.queryFragments[component.id]).toBe(sizeOptions[1].value);
+ expect(component.context.filterRawParams[component.id]).toBe(sizeOptions[1].value);
+ });
+
+ it('should reset to initial value ', async () => {
+ const group = await loader.getHarness(MatRadioGroupHarness);
+ await group.checkRadioButton({ selector: `[data-automation-id="search-radio-${sizeOptions[2].name}"]` });
+
+ expect(component.context.queryFragments[component.id]).toBe(sizeOptions[2].value);
+ expect(component.context.filterRawParams[component.id]).toBe(sizeOptions[2].value);
+
+ component.reset();
+ fixture.detectChanges();
expect(component.context.queryFragments[component.id]).toBe(sizeOptions[0].value);
+ expect(component.context.filterRawParams[component.id]).toBe(sizeOptions[0].value);
+ });
+
+ it('should populate filter state when populate filters event has been observed', async () => {
+ component.context.filterLoaded = new ReplaySubject(1);
+ spyOn(component.context.filterLoaded, 'next').and.stub();
+ spyOn(component.displayValue$, 'next').and.stub();
+ fixture.detectChanges();
+ component.context.populateFilters.next({ radio: sizeOptions[1].value });
+ fixture.detectChanges();
+ const group = await loader.getHarness(MatRadioGroupHarness);
+
+ expect(component.displayValue$.next).toHaveBeenCalledWith(sizeOptions[1].name);
+ expect(component.value).toEqual(sizeOptions[1].value);
+ expect(component.context.filterRawParams[component.id]).toBe(sizeOptions[1].value);
+ expect(component.context.filterLoaded.next).toHaveBeenCalled();
+ expect(await group.getCheckedValue()).toEqual(sizeOptions[1].value);
});
});
diff --git a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts
index 8f93a20798..ef341e9771 100644
--- a/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts
+++ b/lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts
@@ -22,7 +22,8 @@ import { SearchWidget } from '../../models/search-widget.interface';
import { SearchWidgetSettings } from '../../models/search-widget-settings.interface';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
import { SearchFilterList } from '../../models/search-filter-list.model';
-import { Subject } from 'rxjs';
+import { ReplaySubject } from 'rxjs';
+import { first } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
@@ -56,7 +57,7 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
isActive = false;
startValue: any;
enableChangeUpdate: boolean;
- displayValue$: Subject = new Subject();
+ displayValue$: ReplaySubject = new ReplaySubject(1);
constructor() {
this.options = new SearchFilterList();
@@ -82,6 +83,16 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
}
this.enableChangeUpdate = this.settings.allowUpdateOnChange ?? true;
this.updateDisplayValue();
+ this.context.populateFilters
+ .asObservable()
+ .pipe(first())
+ .subscribe((filtersQueries) => {
+ if (filtersQueries[this.id]) {
+ this.value = filtersQueries[this.id];
+ this.submitValues(false);
+ this.context.filterLoaded.next();
+ }
+ });
}
private getSelectedValue(): string {
@@ -98,10 +109,12 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
return null;
}
- submitValues() {
+ submitValues(updateContext = true) {
this.setValue(this.value);
this.updateDisplayValue();
- this.context.update();
+ if (updateContext) {
+ this.context.update();
+ }
}
hasValidValue() {
@@ -112,6 +125,7 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
setValue(newValue: string) {
this.value = newValue;
this.context.queryFragments[this.id] = newValue;
+ this.context.filterRawParams[this.id] = newValue;
if (this.enableChangeUpdate) {
this.updateDisplayValue();
this.context.update();
diff --git a/lib/content-services/src/lib/search/components/search-slider/search-slider.component.spec.ts b/lib/content-services/src/lib/search/components/search-slider/search-slider.component.spec.ts
index 34914ba1a4..6e38bfcefe 100644
--- a/lib/content-services/src/lib/search/components/search-slider/search-slider.component.spec.ts
+++ b/lib/content-services/src/lib/search/components/search-slider/search-slider.component.spec.ts
@@ -18,6 +18,7 @@
import { SearchSliderComponent } from './search-slider.component';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReplaySubject } from 'rxjs';
describe('SearchSliderComponent', () => {
let fixture: ComponentFixture;
@@ -29,101 +30,84 @@ describe('SearchSliderComponent', () => {
});
fixture = TestBed.createComponent(SearchSliderComponent);
component = fixture.componentInstance;
- });
-
- it('should setup slider from settings', () => {
- const settings: any = {
+ component.id = 'slider';
+ component.context = {
+ queryFragments: {
+ slider: ''
+ },
+ filterRawParams: {},
+ populateFilters: new ReplaySubject(1),
+ update: jasmine.createSpy('update')
+ } as any;
+ component.settings = {
+ field: 'field1',
min: 10,
max: 100,
step: 2,
thumbLabel: true
};
+ });
- component.settings = settings;
+ it('should setup slider from settings', () => {
fixture.detectChanges();
- expect(component.min).toEqual(settings.min);
- expect(component.max).toEqual(settings.max);
- expect(component.step).toEqual(settings.step);
- expect(component.thumbLabel).toEqual(settings.thumbLabel);
+ expect(component.min).toEqual(10);
+ expect(component.max).toEqual(100);
+ expect(component.step).toEqual(2);
+ expect(component.thumbLabel).toEqual(true);
});
it('should update its query part on slider change', () => {
- const context: any = {
- queryFragments: {},
- update: () => {}
- };
-
- spyOn(context, 'update').and.stub();
-
- component.context = context;
- component.id = 'contentSize';
- component.settings = { field: 'cm:content.size' };
+ component.settings['field'] = 'cm:content.size';
component.value = 10;
fixture.detectChanges();
component.onChangedHandler();
- expect(context.queryFragments[component.id]).toEqual('cm:content.size:[0 TO 10]');
- expect(context.update).toHaveBeenCalled();
+ expect(component.context.queryFragments[component.id]).toEqual('cm:content.size:[0 TO 10]');
+ expect(component.context.filterRawParams[component.id]).toEqual(10);
+ expect(component.context.update).toHaveBeenCalled();
component.value = 20;
component.onChangedHandler();
- expect(context.queryFragments[component.id]).toEqual('cm:content.size:[0 TO 20]');
+ expect(component.context.queryFragments[component.id]).toEqual('cm:content.size:[0 TO 20]');
+ expect(component.context.filterRawParams[component.id]).toEqual(20);
});
it('should reset the value for query builder', () => {
- const settings: any = {
- field: 'field1',
- min: 10,
- max: 100,
- step: 2,
- thumbLabel: true
- };
-
- const context: any = {
- queryFragments: {},
- update: () => {}
- };
-
- component.settings = settings;
- component.context = context;
component.value = 20;
- component.id = 'slider';
- spyOn(context, 'update').and.stub();
fixture.detectChanges();
component.reset();
- expect(component.value).toBe(settings.min);
- expect(context.queryFragments[component.id]).toBe('');
- expect(context.update).toHaveBeenCalled();
+ expect(component.value).toBe(10);
+ expect(component.context.queryFragments[component.id]).toBe('');
+ expect(component.context.filterRawParams[component.id]).toBe(null);
+ expect(component.context.update).toHaveBeenCalled();
});
it('should reset to 0 if min not provided', () => {
- const settings: any = {
- field: 'field1',
- min: null,
- max: 100,
- step: 2,
- thumbLabel: true
- };
-
- const context: any = {
- queryFragments: {},
- update: () => {}
- };
-
- component.settings = settings;
- component.context = context;
+ component.settings.min = null;
component.value = 20;
- component.id = 'slider';
- spyOn(context, 'update').and.stub();
fixture.detectChanges();
component.reset();
expect(component.value).toBe(0);
- expect(context.queryFragments['slider']).toBe('');
- expect(context.update).toHaveBeenCalled();
+ expect(component.context.queryFragments['slider']).toBe('');
+ expect(component.context.update).toHaveBeenCalled();
+ });
+
+ it('should populate filter state when populate filters event has been observed', async () => {
+ component.context.filterLoaded = new ReplaySubject(1);
+ spyOn(component.context.filterLoaded, 'next').and.stub();
+ spyOn(component.displayValue$, 'next').and.stub();
+ fixture.detectChanges();
+ component.context.populateFilters.next({ slider: 20 });
+ fixture.detectChanges();
+
+ expect(component.displayValue$.next).toHaveBeenCalledWith('20 ');
+ expect(component.value).toBe(20);
+ expect(component.context.filterRawParams[component.id]).toBe(20);
+ expect(component.context.filterLoaded.next).toHaveBeenCalled();
});
});
diff --git a/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts b/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts
index f65bd2fcbb..44f1bef52c 100644
--- a/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts
+++ b/lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts
@@ -19,7 +19,8 @@ import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { SearchWidget } from '../../models/search-widget.interface';
import { SearchWidgetSettings } from '../../models/search-widget-settings.interface';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
-import { Subject } from 'rxjs';
+import { ReplaySubject } from 'rxjs';
+import { first } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatSliderModule } from '@angular/material/slider';
import { FormsModule } from '@angular/forms';
@@ -47,7 +48,7 @@ export class SearchSliderComponent implements SearchWidget, OnInit {
max: number;
thumbLabel = false;
enableChangeUpdate: boolean;
- displayValue$: Subject = new Subject();
+ displayValue$: ReplaySubject = new ReplaySubject(1);
/** The numeric value represented by the slider. */
@Input()
@@ -74,6 +75,16 @@ export class SearchSliderComponent implements SearchWidget, OnInit {
if (this.startValue) {
this.setValue(this.startValue);
}
+ this.context.populateFilters
+ .asObservable()
+ .pipe(first())
+ .subscribe((filtersQueries) => {
+ if (filtersQueries[this.id]) {
+ this.value = filtersQueries[this.id];
+ this.updateQuery(this.value, false);
+ this.context.filterLoaded.next();
+ }
+ });
}
clear() {
@@ -111,7 +122,8 @@ export class SearchSliderComponent implements SearchWidget, OnInit {
this.submitValues();
}
- private updateQuery(value: number | null) {
+ private updateQuery(value: number | null, updateContext = true) {
+ this.context.filterRawParams[this.id] = value;
this.displayValue$.next(this.value ? `${this.value} ${this.settings.unit ?? ''}` : '');
if (this.id && this.context && this.settings && this.settings.field) {
if (value === null) {
@@ -119,7 +131,9 @@ export class SearchSliderComponent implements SearchWidget, OnInit {
} else {
this.context.queryFragments[this.id] = `${this.settings.field}:[0 TO ${value}]`;
}
- this.context.update();
+ if (updateContext) {
+ this.context.update();
+ }
}
}
}
diff --git a/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts b/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts
index 3e53f167c2..baf45b86e8 100644
--- a/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts
+++ b/lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.spec.ts
@@ -17,42 +17,45 @@
import { SearchSortingPickerComponent } from './search-sorting-picker.component';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
-import { AppConfigService } from '@alfresco/adf-core';
-import { SearchConfiguration } from '../../models/search-configuration.interface';
-import { TestBed } from '@angular/core/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../../testing/content.testing.module';
-import { AlfrescoApiService } from '../../../services/alfresco-api.service';
+import { SearchConfiguration } from '../../models';
describe('SearchSortingPickerComponent', () => {
- let queryBuilder: SearchQueryBuilderService;
+ let fixture: ComponentFixture;
let component: SearchSortingPickerComponent;
- const buildConfig = (searchSettings): AppConfigService => {
- const config = TestBed.inject(AppConfigService);
- config.config.search = searchSettings;
- return config;
+ const config: SearchConfiguration = {
+ sorting: {
+ options: [
+ { key: 'name', label: 'Name', type: 'FIELD', field: 'cm:name', ascending: true },
+ { key: 'content.sizeInBytes', label: 'Size', type: 'FIELD', field: 'content.size', ascending: true },
+ { key: 'description', label: 'Description', type: 'FIELD', field: 'cm:description', ascending: true }
+ ],
+ defaults: [{ key: 'name', type: 'FIELD', field: 'cm:name', ascending: false } as any]
+ },
+ categories: [{ id: 'cat1', enabled: true } as any]
+ };
+
+ const queryBuilder = {
+ getSortingOptions: () => config.sorting.options,
+ getPrimarySorting: () => config.sorting.defaults[0],
+ sorting: config.sorting.options,
+ update: jasmine.createSpy('update')
};
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [ContentTestingModule]
+ imports: [ContentTestingModule],
+ providers: [
+ {
+ provide: SearchQueryBuilderService,
+ useValue: queryBuilder
+ }
+ ]
});
-
- const config: SearchConfiguration = {
- sorting: {
- options: [
- { key: 'name', label: 'Name', type: 'FIELD', field: 'cm:name', ascending: true },
- { key: 'content.sizeInBytes', label: 'Size', type: 'FIELD', field: 'content.size', ascending: true },
- { key: 'description', label: 'Description', type: 'FIELD', field: 'cm:description', ascending: true }
- ],
- defaults: [{ key: 'name', type: 'FIELD', field: 'cm:name', ascending: false } as any]
- },
- categories: [{ id: 'cat1', enabled: true } as any]
- };
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- queryBuilder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
- component = new SearchSortingPickerComponent(queryBuilder);
+ fixture = TestBed.createComponent(SearchSortingPickerComponent);
+ component = fixture.componentInstance;
});
it('should load options from query builder', () => {
@@ -72,8 +75,6 @@ describe('SearchSortingPickerComponent', () => {
});
it('should update query builder each time selection is changed', () => {
- spyOn(queryBuilder, 'update').and.stub();
-
component.ngOnInit();
component.onValueChanged('description');
@@ -84,8 +85,6 @@ describe('SearchSortingPickerComponent', () => {
});
it('should update query builder each time sorting is changed', () => {
- spyOn(queryBuilder, 'update').and.stub();
-
component.ngOnInit();
component.onSortingChanged(false);
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 850ac804e5..5a86ec41d4 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
@@ -22,6 +22,7 @@ import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatInputHarness } from '@angular/material/input/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
+import { ReplaySubject } from 'rxjs';
describe('SearchTextComponent', () => {
let loader: HarnessLoader;
@@ -40,10 +41,13 @@ describe('SearchTextComponent', () => {
field: 'cm:name',
placeholder: 'Enter the name'
};
-
component.context = {
- queryFragments: {},
- update: () => {}
+ queryFragments: {
+ slider: ''
+ },
+ filterRawParams: {},
+ populateFilters: new ReplaySubject(1),
+ update: jasmine.createSpy('update')
} as any;
loader = TestbedHarnessEnvironment.loader(fixture);
@@ -65,8 +69,6 @@ describe('SearchTextComponent', () => {
});
it('should update query builder on change', () => {
- spyOn(component.context, 'update').and.stub();
-
component.onChangedHandler({
target: {
value: 'top-secret.doc'
@@ -75,6 +77,7 @@ describe('SearchTextComponent', () => {
expect(component.value).toBe('top-secret.doc');
expect(component.context.queryFragments[component.id]).toBe(`cm:name:'top-secret.doc'`);
+ expect(component.context.filterRawParams[component.id]).toBe('top-secret.doc');
expect(component.context.update).toHaveBeenCalled();
});
@@ -87,6 +90,7 @@ describe('SearchTextComponent', () => {
expect(component.value).toBe('top-secret.doc');
expect(component.context.queryFragments[component.id]).toBe(`cm:name:'top-secret.doc'`);
+ expect(component.context.filterRawParams[component.id]).toBe('top-secret.doc');
component.onChangedHandler({
target: {
@@ -96,6 +100,7 @@ describe('SearchTextComponent', () => {
expect(component.value).toBe('');
expect(component.context.queryFragments[component.id]).toBe('');
+ expect(component.context.filterRawParams[component.id]).toBe('');
});
it('should show the custom/default name', async () => {
@@ -118,10 +123,10 @@ describe('SearchTextComponent', () => {
expect(component.value).toBe('');
expect(component.context.queryFragments[component.id]).toBe('');
+ expect(component.context.filterRawParams[component.id]).toBeNull();
});
it('should update query with startValue on init, if provided', () => {
- spyOn(component.context, 'update');
component.startValue = 'mock-start-value';
fixture.detectChanges();
@@ -132,7 +137,6 @@ describe('SearchTextComponent', () => {
it('should parse value and set query context as blank, and not call query update, if no start value was provided', () => {
component.context.queryFragments[component.id] = `cm:name:'secret.pdf'`;
- spyOn(component.context, 'update');
component.startValue = undefined;
fixture.detectChanges();
@@ -140,4 +144,18 @@ describe('SearchTextComponent', () => {
expect(component.value).toBe('secret.pdf');
expect(component.context.update).not.toHaveBeenCalled();
});
+
+ it('should populate filter state when populate filters event has been observed', async () => {
+ component.context.filterLoaded = new ReplaySubject(1);
+ spyOn(component.context.filterLoaded, 'next').and.stub();
+ spyOn(component.displayValue$, 'next').and.stub();
+ fixture.detectChanges();
+ component.context.populateFilters.next({ text: 'secret.pdf' });
+ fixture.detectChanges();
+
+ expect(component.displayValue$.next).toHaveBeenCalledWith('secret.pdf');
+ expect(component.value).toBe('secret.pdf');
+ expect(component.context.filterRawParams[component.id]).toBe('secret.pdf');
+ expect(component.context.filterLoaded.next).toHaveBeenCalled();
+ });
});
diff --git a/lib/content-services/src/lib/search/components/search-text/search-text.component.ts b/lib/content-services/src/lib/search/components/search-text/search-text.component.ts
index cea0b98959..34a46ef482 100644
--- a/lib/content-services/src/lib/search/components/search-text/search-text.component.ts
+++ b/lib/content-services/src/lib/search/components/search-text/search-text.component.ts
@@ -19,7 +19,8 @@ import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { SearchWidget } from '../../models/search-widget.interface';
import { SearchWidgetSettings } from '../../models/search-widget-settings.interface';
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
-import { Subject } from 'rxjs';
+import { ReplaySubject } from 'rxjs';
+import { first } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { TranslateModule } from '@ngx-translate/core';
@@ -48,7 +49,7 @@ export class SearchTextComponent implements SearchWidget, OnInit {
startValue: string;
isActive = false;
enableChangeUpdate = true;
- displayValue$: Subject = new Subject();
+ displayValue$: ReplaySubject = new ReplaySubject(1);
ngOnInit() {
if (this.context && this.settings && this.settings.pattern) {
@@ -70,6 +71,16 @@ export class SearchTextComponent implements SearchWidget, OnInit {
}
}
}
+ this.context.populateFilters
+ .asObservable()
+ .pipe(first())
+ .subscribe((filtersQueries) => {
+ if (filtersQueries[this.id]) {
+ this.value = filtersQueries[this.id];
+ this.updateQuery(this.value, false);
+ this.context.filterLoaded.next();
+ }
+ });
}
clear() {
@@ -93,11 +104,14 @@ export class SearchTextComponent implements SearchWidget, OnInit {
}
}
- private updateQuery(value: string) {
+ private updateQuery(value: string, updateContext = true) {
+ this.context.filterRawParams[this.id] = value;
this.displayValue$.next(value);
if (this.context && this.settings && this.settings.field) {
this.context.queryFragments[this.id] = value ? `${this.settings.field}:'${this.getSearchPrefix()}${value}${this.getSearchSuffix()}'` : '';
- this.context.update();
+ if (updateContext) {
+ this.context.update();
+ }
}
}
diff --git a/lib/content-services/src/lib/search/models/search-widget.interface.ts b/lib/content-services/src/lib/search/models/search-widget.interface.ts
index c331ae26aa..3a911334e4 100644
--- a/lib/content-services/src/lib/search/models/search-widget.interface.ts
+++ b/lib/content-services/src/lib/search/models/search-widget.interface.ts
@@ -17,7 +17,7 @@
import { SearchWidgetSettings } from './search-widget-settings.interface';
import { SearchQueryBuilderService } from '../services/search-query-builder.service';
-import { Subject } from 'rxjs';
+import { ReplaySubject } from 'rxjs';
export interface SearchWidget {
id: string;
@@ -27,7 +27,7 @@ export interface SearchWidget {
isActive?: boolean;
startValue: any;
/* stream emit value on changes */
- displayValue$: Subject;
+ displayValue$: ReplaySubject;
/* reset the value and update the search */
reset(): void;
/* update the search with field value */
diff --git a/lib/content-services/src/lib/search/services/base-query-builder.service.ts b/lib/content-services/src/lib/search/services/base-query-builder.service.ts
index eb5eb72c5b..7f092a3efc 100644
--- a/lib/content-services/src/lib/search/services/base-query-builder.service.ts
+++ b/lib/content-services/src/lib/search/services/base-query-builder.service.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { Subject, Observable, from, ReplaySubject } from 'rxjs';
+import { Subject, Observable, from, ReplaySubject, BehaviorSubject } from 'rxjs';
import { AppConfigService } from '@alfresco/adf-core';
import {
SearchRequest,
@@ -37,8 +37,13 @@ import { FacetField } from '../models/facet-field.interface';
import { FacetFieldBucket } from '../models/facet-field-bucket.interface';
import { SearchForm } from '../models/search-form.interface';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
+import { Buffer } from 'buffer';
+import { inject } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
export abstract class BaseQueryBuilderService {
+ private router = inject(Router);
+ private activatedRoute = inject(ActivatedRoute);
private _searchApi: SearchApi;
get searchApi(): SearchApi {
this._searchApi = this._searchApi ?? new SearchApi(this.alfrescoApiService.getInstance());
@@ -48,6 +53,9 @@ export abstract class BaseQueryBuilderService {
/* Stream that emits the search configuration whenever the user change the search forms */
configUpdated = new Subject();
+ /* Stream that emits the event each time when search filter finishes loading initial value */
+ filterLoaded = new Subject();
+
/* Stream that emits the query before search whenever user search */
updated = new Subject();
@@ -60,12 +68,17 @@ export abstract class BaseQueryBuilderService {
/* Stream that emits search forms */
searchForms = new ReplaySubject(1);
+ /* Stream that emits the initial value for some or all search filters */
+ populateFilters = new BehaviorSubject<{ [key: string]: any }>({});
+
categories: SearchCategory[] = [];
queryFragments: { [id: string]: string } = {};
filterQueries: FilterQuery[] = [];
+ filterRawParams: { [key: string]: any } = {};
paging: { maxItems?: number; skipCount?: number } = null;
sorting: SearchSortingDefinition[] = [];
sortingOptions: SearchSortingDefinition[] = [];
+ private encodedQuery: string;
private scope: RequestScope;
private selectedConfiguration: number;
private _userQuery = '';
@@ -88,10 +101,7 @@ export abstract class BaseQueryBuilderService {
// TODO: to be supported in future iterations
ranges: { [id: string]: SearchRange } = {};
- protected constructor(
- protected appConfig: AppConfigService,
- protected alfrescoApiService: AlfrescoApiService
- ) {
+ protected constructor(protected appConfig: AppConfigService, protected alfrescoApiService: AlfrescoApiService) {
this.resetToDefaults();
}
@@ -297,12 +307,16 @@ export abstract class BaseQueryBuilderService {
/**
* Builds and executes the current query.
*
+ * @param updateQueryParams whether query params should be updated with encoded query
* @param queryBody query settings
*/
- async execute(queryBody?: SearchRequest) {
+ async execute(updateQueryParams = true, queryBody?: SearchRequest) {
try {
const query = queryBody ? queryBody : this.buildQuery();
if (query) {
+ if (updateQueryParams) {
+ this.updateSearchQueryParams();
+ }
const resultSetPaging: ResultSetPaging = await this.searchApi.search(query);
this.executed.next(resultSetPaging);
}
@@ -461,9 +475,9 @@ export abstract class BaseQueryBuilderService {
end: set.end,
startInclusive: set.startInclusive,
endInclusive: set.endInclusive
- }) as any
+ } as any)
)
- }) as any
+ } as any)
)
};
}
@@ -477,6 +491,9 @@ export abstract class BaseQueryBuilderService {
protected getFinalQuery(): string {
let query = '';
+ if (this.userQuery) {
+ this.filterRawParams['userQuery'] = this.userQuery;
+ }
this.categories.forEach((facet) => {
const customQuery = this.queryFragments[facet.id];
@@ -522,7 +539,7 @@ export abstract class BaseQueryBuilderService {
limit: facet.limit,
offset: facet.offset,
prefix: facet.prefix
- }) as any
+ } as any)
)
};
}
@@ -543,4 +560,38 @@ export abstract class BaseQueryBuilderService {
}
return configLabel;
}
+
+ /**
+ * Encodes filter configuration stored in filterRawParams object.
+ */
+ encodeQuery() {
+ this.encodedQuery = Buffer.from(JSON.stringify(this.filterRawParams)).toString('base64');
+ }
+
+ /**
+ * Encodes existing filters configuration and updates search query param value.
+ */
+ updateSearchQueryParams() {
+ this.encodeQuery();
+ this.router.navigate([], {
+ relativeTo: this.activatedRoute,
+ queryParams: { q: this.encodedQuery },
+ queryParamsHandling: 'merge'
+ });
+ }
+
+ /**
+ * Builds search query with provided user query, executes query, encodes latest filter config and navigates to search.
+ *
+ * @param query user query to search for
+ * @param searchUrl search url to navigate to
+ */
+ async navigateToSearch(query: string, searchUrl: string) {
+ this.userQuery = query;
+ await this.execute();
+ await this.router.navigate([searchUrl], {
+ queryParams: { q: this.encodedQuery },
+ queryParamsHandling: 'merge'
+ });
+ }
}
diff --git a/lib/content-services/src/lib/search/services/search-facet-filters.service.ts b/lib/content-services/src/lib/search/services/search-facet-filters.service.ts
index 22fa5a6fcf..d6cdc01294 100644
--- a/lib/content-services/src/lib/search/services/search-facet-filters.service.ts
+++ b/lib/content-services/src/lib/search/services/search-facet-filters.service.ts
@@ -69,7 +69,7 @@ export class SearchFacetFiltersService implements OnDestroy {
this.responseFacets = null;
});
- this.queryBuilder.updated.pipe(takeUntil(this.onDestroy$)).subscribe((query) => this.queryBuilder.execute(query));
+ this.queryBuilder.updated.pipe(takeUntil(this.onDestroy$)).subscribe((query) => this.queryBuilder.execute(true, query));
this.queryBuilder.executed.pipe(takeUntil(this.onDestroy$)).subscribe((resultSetPaging: ResultSetPaging) => {
this.onDataLoaded(resultSetPaging);
diff --git a/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts b/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts
index bbc6622f9d..72ab7f3d5e 100644
--- a/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts
+++ b/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts
@@ -23,7 +23,6 @@ import { ContentTestingModule } from '../../testing/content.testing.module';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
describe('SearchHeaderQueryBuilderService', () => {
-
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
@@ -36,21 +35,22 @@ describe('SearchHeaderQueryBuilderService', () => {
return config;
};
+ const createQueryBuilder = (searchSettings): SearchHeaderQueryBuilderService => {
+ let builder: SearchHeaderQueryBuilderService;
+ TestBed.runInInjectionContext(() => {
+ const alfrescoApiService = TestBed.inject(AlfrescoApiService);
+ builder = new SearchHeaderQueryBuilderService(buildConfig(searchSettings), alfrescoApiService, null);
+ });
+ return builder;
+ };
+
it('should load the configuration from app config', () => {
const config: SearchConfiguration = {
- categories: [
- { id: 'cat1', enabled: true } as any,
- { id: 'cat2', enabled: true } as any
- ],
+ categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchHeaderQueryBuilderService(
- buildConfig(config),
- alfrescoApiService,
- null
- );
+ const builder = createQueryBuilder(config);
builder.categories = [];
builder.filterQueries = [];
@@ -73,12 +73,7 @@ describe('SearchHeaderQueryBuilderService', () => {
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const service = new SearchHeaderQueryBuilderService(
- buildConfig(config),
- alfrescoApiService,
- null
- );
+ const service = createQueryBuilder(config);
const category = service.getCategoryForColumn('fake-key-1');
expect(category).not.toBeNull();
@@ -87,34 +82,19 @@ describe('SearchHeaderQueryBuilderService', () => {
});
it('should have empty user query by default', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchHeaderQueryBuilderService(
- buildConfig({}),
- alfrescoApiService,
- null
- );
+ const builder = createQueryBuilder({});
expect(builder.userQuery).toBe('');
});
it('should add the extra filter for the parent node', () => {
const config: SearchConfiguration = {
- categories: [
- { id: 'cat1', enabled: true } as any,
- { id: 'cat2', enabled: true } as any
- ],
+ categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
- const expectedResult = [
- { query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }
- ];
+ const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }];
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const searchHeaderService = new SearchHeaderQueryBuilderService(
- buildConfig(config),
- alfrescoApiService,
- null
- );
+ const searchHeaderService = createQueryBuilder(config);
searchHeaderService.setCurrentRootFolderId('fake-node-id');
@@ -122,52 +102,28 @@ describe('SearchHeaderQueryBuilderService', () => {
});
it('should not add again the parent filter if that node is already added', () => {
-
- const expectedResult = [
- { query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }
- ];
+ const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }];
const config: SearchConfiguration = {
- categories: [
- { id: 'cat1', enabled: true } as any,
- { id: 'cat2', enabled: true } as any
- ],
+ categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
filterQueries: expectedResult
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const searchHeaderService = new SearchHeaderQueryBuilderService(
- buildConfig(config),
- alfrescoApiService,
- null
- );
-
+ const searchHeaderService = createQueryBuilder(config);
searchHeaderService.setCurrentRootFolderId('fake-node-id');
- expect(searchHeaderService.filterQueries).toEqual(
- expectedResult,
- 'Filters are not as expected'
- );
+ expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected');
});
it('should not add duplicate column names in activeFilters', () => {
const activeFilter = 'FakeColumn';
const config: SearchConfiguration = {
- categories: [
- { id: 'cat1', enabled: true } as any
- ],
- filterQueries: [
- { query: 'PARENT:"workspace://SpacesStore/fake-node-id' }
- ]
+ categories: [{ id: 'cat1', enabled: true } as any],
+ filterQueries: [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id' }]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const searchHeaderService = new SearchHeaderQueryBuilderService(
- buildConfig(config),
- alfrescoApiService,
- null
- );
+ const searchHeaderService = createQueryBuilder(config);
expect(searchHeaderService.activeFilters.length).toBe(0);
diff --git a/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts b/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts
index d8a8027ab0..18aadf4d90 100644
--- a/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts
+++ b/lib/content-services/src/lib/search/services/search-query-builder.service.spec.ts
@@ -23,6 +23,16 @@ import { FacetField } from '../models/facet-field.interface';
import { TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { ADF_SEARCH_CONFIGURATION } from '../search-configuration.token';
+import { ActivatedRoute, Router } from '@angular/router';
+
+const buildConfig = (searchSettings = {}): AppConfigService => {
+ let config: AppConfigService;
+ TestBed.runInInjectionContext(() => {
+ config = TestBed.inject(AppConfigService);
+ });
+ config.config.search = searchSettings;
+ return config;
+};
describe('SearchQueryBuilder (runtime config)', () => {
const runtimeConfig: SearchConfiguration = {};
@@ -30,32 +40,32 @@ describe('SearchQueryBuilder (runtime config)', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule],
- providers: [
- { provide: ADF_SEARCH_CONFIGURATION, useValue: runtimeConfig }
- ]
+ providers: [{ provide: ADF_SEARCH_CONFIGURATION, useValue: runtimeConfig }]
});
});
- const buildConfig = (searchSettings): AppConfigService => {
- const config = TestBed.inject(AppConfigService);
- config.config.search = searchSettings;
- return config;
- };
-
it('should use custom search configuration via dependency injection', () => {
- const builder = TestBed.inject(SearchQueryBuilderService);
+ let builder: SearchQueryBuilderService;
+ TestBed.runInInjectionContext(() => {
+ builder = TestBed.inject(SearchQueryBuilderService);
+ });
const currentConfig = builder.loadConfiguration();
expect(currentConfig).toEqual(runtimeConfig);
});
it('should prioritise runtime config over configuration file', () => {
- const config: SearchConfiguration = {
+ const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService, runtimeConfig);
+
+ let alfrescoApiService: AlfrescoApiService;
+ let builder: SearchQueryBuilderService;
+ TestBed.runInInjectionContext(() => {
+ alfrescoApiService = TestBed.inject(AlfrescoApiService);
+ builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService, runtimeConfig);
+ });
const currentConfig = builder.loadConfiguration();
expect(currentConfig).toEqual(runtimeConfig);
@@ -63,16 +73,24 @@ describe('SearchQueryBuilder (runtime config)', () => {
});
describe('SearchQueryBuilder', () => {
+ let router: Router;
+ let activatedRoute: ActivatedRoute;
+
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
});
+ router = TestBed.inject(Router);
+ activatedRoute = TestBed.inject(ActivatedRoute);
});
- const buildConfig = (searchSettings = {}): AppConfigService => {
- const config = TestBed.inject(AppConfigService);
- config.config.search = searchSettings;
- return config;
+ const createQueryBuilder = (config?: any) => {
+ let builder: SearchQueryBuilderService;
+ TestBed.runInInjectionContext(() => {
+ const alfrescoApiService = TestBed.inject(AlfrescoApiService);
+ builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ });
+ return builder;
};
it('should reset to defaults', () => {
@@ -80,8 +98,8 @@ describe('SearchQueryBuilder', () => {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+
+ const builder = createQueryBuilder(config);
builder.categories = [];
builder.filterQueries = [];
@@ -96,23 +114,18 @@ describe('SearchQueryBuilder', () => {
});
it('should have empty user query by default', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
expect(builder.userQuery).toBe('');
});
it('should wrap user query with brackets', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
builder.userQuery = 'my query';
expect(builder.userQuery).toEqual('(my query)');
});
it('should trim user query value', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
builder.userQuery = ' something ';
expect(builder.userQuery).toEqual('(something)');
});
@@ -121,9 +134,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: false } as any, { id: 'cat3', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
expect(builder.categories.length).toBe(2);
expect(builder.categories[0].id).toBe('cat1');
@@ -135,8 +146,7 @@ describe('SearchQueryBuilder', () => {
categories: [],
filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
expect(builder.filterQueries.length).toBe(2);
expect(builder.filterQueries[0].query).toBe('query1');
@@ -144,10 +154,7 @@ describe('SearchQueryBuilder', () => {
});
it('should add new filter query', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
-
+ const builder = createQueryBuilder();
builder.addFilterQuery('q1');
expect(builder.filterQueries.length).toBe(1);
@@ -155,10 +162,7 @@ describe('SearchQueryBuilder', () => {
});
it('should not add empty filter query', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
-
+ const builder = createQueryBuilder();
builder.addFilterQuery(null);
builder.addFilterQuery('');
@@ -166,10 +170,7 @@ describe('SearchQueryBuilder', () => {
});
it('should not add duplicate filter query', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
-
+ const builder = createQueryBuilder();
builder.addFilterQuery('q1');
builder.addFilterQuery('q1');
builder.addFilterQuery('q1');
@@ -179,10 +180,7 @@ describe('SearchQueryBuilder', () => {
});
it('should remove filter query', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
-
+ const builder = createQueryBuilder();
builder.addFilterQuery('q1');
builder.addFilterQuery('q2');
expect(builder.filterQueries.length).toBe(2);
@@ -193,9 +191,7 @@ describe('SearchQueryBuilder', () => {
});
it('should not remove empty query', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
builder.addFilterQuery('q1');
builder.addFilterQuery('q2');
expect(builder.filterQueries.length).toBe(2);
@@ -215,9 +211,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
const query = builder.getFacetQuery('query2');
expect(query.query).toBe('q2');
@@ -231,9 +225,7 @@ describe('SearchQueryBuilder', () => {
queries: [{ query: 'q1', label: 'query1' }]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
const query1 = builder.getFacetQuery('');
expect(query1).toBeNull();
@@ -252,9 +244,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
const field = builder.getFacetField('Size');
expect(field.label).toBe('Size');
@@ -271,9 +261,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
const field = builder.getFacetField('Missing');
expect(field).toBeFalsy();
@@ -286,9 +274,7 @@ describe('SearchQueryBuilder', () => {
fields: [{ field: 'content.size', mincount: 1, label: 'Label with spaces' }]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
const field = builder.getFacetField('Label with spaces');
expect(field.label).toBe('"Label with spaces"');
@@ -299,9 +285,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = null;
const compiled = builder.buildQuery();
@@ -312,10 +296,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
-
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -326,9 +307,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
builder.queryFragments['cat2'] = 'NOT cm:creator:System';
@@ -342,9 +321,7 @@ describe('SearchQueryBuilder', () => {
fields: ['field1', 'field2'],
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
@@ -357,10 +334,7 @@ describe('SearchQueryBuilder', () => {
fields: [],
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
-
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -371,9 +345,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
builder.addFilterQuery('query1');
@@ -388,9 +360,7 @@ describe('SearchQueryBuilder', () => {
queries: [{ query: 'q1', label: 'q2', group: 'group-name' }]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -407,9 +377,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -449,9 +417,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -485,9 +451,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -531,9 +495,7 @@ describe('SearchQueryBuilder', () => {
]
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
@@ -550,8 +512,7 @@ describe('SearchQueryBuilder', () => {
fields: [],
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
const sorting: any = { type: 'FIELD', field: 'cm:name', ascending: true };
builder.sorting = [sorting];
@@ -565,8 +526,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.queryFragments['cat1'] = 'cm:name:test';
builder.paging = { maxItems: 5, skipCount: 5 };
@@ -581,8 +541,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.userQuery = 'my query';
builder.queryFragments['cat1'] = 'cm:name:test';
@@ -615,9 +574,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.addUserFacetBucket(field1.field, field1buckets[0]);
builder.addUserFacetBucket(field1.field, field1buckets[1]);
@@ -630,7 +587,7 @@ describe('SearchQueryBuilder', () => {
expect(compiledQuery.query.query).toBe(expectedResult);
});
- it('should use highlight in the queries', () => {
+ it('should use highlight in the queries', () => {
const config: SearchConfiguration = {
highlight: {
prefix: 'my-prefix',
@@ -638,9 +595,7 @@ describe('SearchQueryBuilder', () => {
mergeContiguous: true
}
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.userQuery = 'my query';
builder.queryFragments['cat1'] = 'cm:name:test';
@@ -655,9 +610,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
spyOn(builder, 'buildQuery').and.throwError('some error');
builder.error.subscribe((error) => {
@@ -671,9 +624,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any]
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
spyOn(builder, 'buildQuery').and.throwError('some error');
builder.executed.subscribe((data) => {
@@ -686,9 +637,7 @@ describe('SearchQueryBuilder', () => {
});
it('should include contain the path and allowableOperations by default', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
builder.userQuery = 'nuka cola quantum';
const searchRequest = builder.buildQuery();
@@ -700,9 +649,7 @@ describe('SearchQueryBuilder', () => {
const config: SearchConfiguration = {
include: includeConfig
};
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(config), alfrescoApiService);
+ const builder = createQueryBuilder(config);
builder.userQuery = 'nuka cola quantum';
const searchRequest = builder.buildQuery();
@@ -710,9 +657,7 @@ describe('SearchQueryBuilder', () => {
});
it('should the query contain the pagination', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
builder.userQuery = 'nuka cola quantum';
const mockPagination = {
maxItems: 10,
@@ -725,9 +670,7 @@ describe('SearchQueryBuilder', () => {
});
it('should the query contain the scope in case it is defined', () => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(), alfrescoApiService);
+ const builder = createQueryBuilder();
const mockScope = { locations: 'mock-location' };
builder.userQuery = 'nuka cola quantum';
builder.setScope(mockScope);
@@ -737,15 +680,50 @@ describe('SearchQueryBuilder', () => {
});
it('should return empty if array of search config not found', (done) => {
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- const builder = new SearchQueryBuilderService(buildConfig(null), alfrescoApiService);
+ const builder = createQueryBuilder(null);
builder.searchForms.subscribe((forms) => {
expect(forms).toEqual([]);
done();
});
});
+ it('should add user query to filter raw params when query is built', () => {
+ const builder = createQueryBuilder();
+ builder.userQuery = 'nuka cola quantum';
+ builder.buildQuery();
+
+ expect(builder.filterRawParams).toEqual({ userQuery: '(nuka cola quantum)' });
+ });
+
+ 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)' });
+ expect(router.navigate).toHaveBeenCalledWith([], {
+ relativeTo: activatedRoute,
+ queryParams: { q: 'eyJ1c2VyUXVlcnkiOiIobnVrYSBjb2xhIHF1YW50dW0pIn0=' },
+ queryParamsHandling: 'merge'
+ });
+ done();
+ });
+ builder.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');
+
+ expect(builder.filterRawParams).toEqual({ userQuery: '(test query)' });
+ expect(router.navigate).toHaveBeenCalledWith([], {
+ relativeTo: activatedRoute,
+ queryParams: { q: 'eyJ1c2VyUXVlcnkiOiIodGVzdCBxdWVyeSkifQ==' },
+ queryParamsHandling: 'merge'
+ });
+ });
+
describe('Multiple search configuration', () => {
let configs: SearchConfiguration[];
let builder: SearchQueryBuilderService;
@@ -768,9 +746,7 @@ describe('SearchQueryBuilder', () => {
default: false
}
];
- const alfrescoApiService = TestBed.inject(AlfrescoApiService);
-
- builder = new SearchQueryBuilderService(buildConfig(configs), alfrescoApiService);
+ builder = createQueryBuilder(configs);
});
it('should pick the default configuration from list', () => {