mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2026-09-09 18:02:54 +00:00
[MNT-25411] Fix clearing filters when search input is empty (#4878)
* [MNT-25411] Fix clearing filters when search input is empty * [MNT-25411] Fixed unit test * [MNT-25411] Fixed unit test * [MNT-25411] XAT-5589 fix * [MNT-24511] fixes for XAT-5581 and XAT-5546 excluded --------- Co-authored-by: Adam Świderski <adam.tomasz.swiderski@gmail.com>
This commit is contained in:
co-authored by
Adam Świderski
parent
bceaf89e6b
commit
9d3c80ffee
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"XAT-5523": "https://hyland.atlassian.net/browse/ACA-4697",
|
||||
"XAT-5516": "https://hyland.atlassian.net/browse/ACS-9889"
|
||||
"XAT-5516": "https://hyland.atlassian.net/browse/ACS-9889",
|
||||
"XAT-5546": "https://hyland.atlassian.net/browse/ACS-10621"
|
||||
}
|
||||
|
||||
+42
-1
@@ -23,9 +23,11 @@
|
||||
*/
|
||||
|
||||
import { SearchInputControlComponent } from './search-input-control.component';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
describe('SearchInputControlComponent', () => {
|
||||
let fixture: ComponentFixture<SearchInputControlComponent>;
|
||||
@@ -87,4 +89,43 @@ describe('SearchInputControlComponent', () => {
|
||||
fixture.detectChanges();
|
||||
expect(component.isTermTooShort()).toBe(false);
|
||||
});
|
||||
|
||||
describe('ngOnInit', () => {
|
||||
let route: ActivatedRoute;
|
||||
let router: Router;
|
||||
|
||||
beforeEach(() => {
|
||||
route = TestBed.inject(ActivatedRoute);
|
||||
router = TestBed.inject(Router);
|
||||
spyOnProperty(router, 'events').and.returnValue(of(new NavigationStart(1, '')));
|
||||
});
|
||||
|
||||
it('should set * as value when url params has q parameter and input is empty', fakeAsync(() => {
|
||||
spyOn(component.searchFieldFormControl, 'setValue');
|
||||
route.queryParams = of({ q: 'someQueryParams' });
|
||||
|
||||
component.ngOnInit();
|
||||
tick();
|
||||
expect(component.searchFieldFormControl.setValue).toHaveBeenCalledWith('*');
|
||||
}));
|
||||
|
||||
it('should not set * as value when url params has missing q parameter and input is empty', fakeAsync(() => {
|
||||
spyOn(component.searchFieldFormControl, 'setValue');
|
||||
route.queryParams = of({ otherQueryParam: 'someQueryParams' });
|
||||
|
||||
component.ngOnInit();
|
||||
tick();
|
||||
expect(component.searchFieldFormControl.setValue).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should not set * as value when url params has q parameter and input is not empty', fakeAsync(() => {
|
||||
component.searchFieldFormControl.setValue('some value');
|
||||
spyOn(component.searchFieldFormControl, 'setValue');
|
||||
route.queryParams = of({ q: 'someQueryParams' });
|
||||
|
||||
component.ngOnInit();
|
||||
tick();
|
||||
expect(component.searchFieldFormControl.setValue).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
+18
@@ -45,6 +45,9 @@ import { MatInputModule } from '@angular/material/input';
|
||||
import { FormControl, FormsModule, ReactiveFormsModule, StatusChangeEvent, TouchedChangeEvent, Validators } from '@angular/forms';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { noWhitespaceValidator } from '@alfresco/aca-shared';
|
||||
import { combineLatest } from 'rxjs';
|
||||
import { filter, startWith } from 'rxjs/operators';
|
||||
import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule],
|
||||
@@ -56,6 +59,8 @@ import { noWhitespaceValidator } from '@alfresco/aca-shared';
|
||||
})
|
||||
export class SearchInputControlComponent implements OnInit, OnChanges {
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
/** Type of the input field to render, e.g. "search" or "text" (default). */
|
||||
@Input()
|
||||
@@ -115,6 +120,19 @@ export class SearchInputControlComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
});
|
||||
combineLatest([
|
||||
this.route.queryParams,
|
||||
this.router.events.pipe(
|
||||
filter((e): e is NavigationStart => e instanceof NavigationStart),
|
||||
startWith(null)
|
||||
)
|
||||
])
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(([params]) => {
|
||||
if (params['q'] && !this.searchFieldFormControl.value) {
|
||||
setTimeout(() => this.searchFieldFormControl.setValue('*'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
|
||||
+14
-3
@@ -271,12 +271,11 @@ describe('SearchComponent', () => {
|
||||
expect(queryBuilder.userQuery).toBe(`((cm:tag:"orange*"))`);
|
||||
});
|
||||
|
||||
it('should get initial saved search when url matches', fakeAsync(() => {
|
||||
it('should get initial saved search when url matches', () => {
|
||||
route.queryParams = of({ q: encodeQuery({ name: 'test' }) });
|
||||
component.ngOnInit();
|
||||
tick();
|
||||
expect(component.initialSavedSearch).toEqual({ name: 'test', encodedUrl: encodeQuery({ name: 'test' }), order: 0 });
|
||||
}));
|
||||
});
|
||||
|
||||
it('should render a menu with 2 options when initial saved search is found', async () => {
|
||||
route.queryParams = of({ q: encodeQuery({ name: 'test' }) });
|
||||
@@ -369,5 +368,17 @@ describe('SearchComponent', () => {
|
||||
expect(executeSpy).toHaveBeenCalledTimes(1);
|
||||
}));
|
||||
|
||||
it('should format userQuery when url parameters changed and userQuery is not contained by url', () => {
|
||||
routerEvents.next(new NavigationStart(1, ''));
|
||||
queryParams.next({ q: encodeQuery('') });
|
||||
expect(queryBuilder.userQuery).toBe('((cm:name:"*"))');
|
||||
});
|
||||
|
||||
it('should not format userQuery when url parameters changed when userQuery is already contained by url', () => {
|
||||
routerEvents.next(new NavigationStart(1, ''));
|
||||
queryParams.next({ q: encodeQuery({ userQuery: 'test' }) });
|
||||
expect(queryBuilder.userQuery).toBe('(test)');
|
||||
});
|
||||
|
||||
testHeader(SearchResultsComponent, false);
|
||||
});
|
||||
|
||||
+13
-5
@@ -251,6 +251,9 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
.subscribe((navigationStartEvent) => {
|
||||
const shouldExecuteQuery = this.shouldExecuteQuery(navigationStartEvent, this.encodedQuery);
|
||||
this.queryBuilder.userQuery = extractUserQueryFromEncodedQuery(this.encodedQuery);
|
||||
if (!this.searchedWord && !this.queryBuilder.userQuery && this.encodedQuery) {
|
||||
this.queryBuilder.userQuery = formatSearchTerm('*', this.searchConfig['app:fields']);
|
||||
}
|
||||
|
||||
if (shouldExecuteQuery) {
|
||||
this.queryBuilder.execute(false);
|
||||
@@ -260,13 +263,18 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
}
|
||||
|
||||
onSearchError(error: { message: any }) {
|
||||
const { statusCode } = JSON.parse(error.message).error;
|
||||
let message: string;
|
||||
try {
|
||||
const { statusCode } = JSON.parse(error.message).error;
|
||||
|
||||
const messageKey = `APP.BROWSE.SEARCH.ERRORS.${statusCode}`;
|
||||
let message = this.translationService.instant(messageKey);
|
||||
const messageKey = `APP.BROWSE.SEARCH.ERRORS.${statusCode}`;
|
||||
message = this.translationService.instant(messageKey);
|
||||
|
||||
if (message === messageKey) {
|
||||
message = this.translationService.instant(`APP.BROWSE.SEARCH.ERRORS.GENERIC`);
|
||||
if (message === messageKey) {
|
||||
message = this.translationService.instant(`APP.BROWSE.SEARCH.ERRORS.GENERIC`);
|
||||
}
|
||||
} catch {
|
||||
message = error.message;
|
||||
}
|
||||
|
||||
this.notificationService.showError(message);
|
||||
|
||||
@@ -65,7 +65,8 @@ export const getGlobalConfig: PlaywrightTestConfig = {
|
||||
screenshot: 'only-on-failure',
|
||||
launchOptions: {
|
||||
devtools: false,
|
||||
args: ['--no-sandbox', '--disable-site-isolation-trials']
|
||||
args: ['--no-sandbox', '--disable-site-isolation-trials'],
|
||||
slowMo: 300
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
+6
-2
@@ -24,7 +24,7 @@
|
||||
|
||||
import { SearchPage } from '../../../pages';
|
||||
import { BaseComponent } from '../../base.component';
|
||||
import { Page } from '@playwright/test';
|
||||
import { Page, Locator } from '@playwright/test';
|
||||
|
||||
export class SearchFiltersTags extends BaseComponent {
|
||||
private static rootElement = '.adf-search-filter-menu-card';
|
||||
@@ -35,10 +35,14 @@ export class SearchFiltersTags extends BaseComponent {
|
||||
|
||||
public addOptionInput = this.getChild(`[data-automation-id$='adf-search-chip-autocomplete-input']`);
|
||||
|
||||
private searchOption(value: string): Locator {
|
||||
return this.page.locator(`[data-automation-id="option-${value}"]`);
|
||||
}
|
||||
|
||||
async filterByTag(page: SearchPage, tag: string): Promise<void> {
|
||||
await page.searchFilters.tagsFilter.click();
|
||||
await page.searchFiltersTags.addOptionInput.fill(tag);
|
||||
await page.page.keyboard.press('Enter');
|
||||
await this.searchOption(tag).click();
|
||||
await page.searchFilters.menuCardApply.click();
|
||||
await page.dataTable.progressBarWaitForReload();
|
||||
}
|
||||
|
||||
+1
@@ -89,6 +89,7 @@ export class SearchOverlayComponent extends BaseComponent {
|
||||
}
|
||||
|
||||
async searchFor(input: string): Promise<void> {
|
||||
await this.searchInput.clear();
|
||||
await this.searchInput.fill(input);
|
||||
await this.searchButton.click({ force: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user