Add test for mat-error on empty search term and handle loading state properly

This commit is contained in:
Shivangi917
2025-07-28 08:04:42 -04:00
parent b7e6bef8cf
commit 029e824d87
6 changed files with 31 additions and 30 deletions
@@ -1,5 +1,6 @@
<div class="app-search-container"> <div class="app-search-container">
<mat-form-field class="app-input-form-field" appearance="outline"> <mat-form-field class="app-input-form-field" appearance="outline">
<button <button
mat-icon-button mat-icon-button
matPrefix matPrefix
@@ -19,6 +20,7 @@
id="app-control-input" id="app-control-input"
[formControl]="searchFieldFormControl" [formControl]="searchFieldFormControl"
(keydown.enter)="searchSubmit()" (keydown.enter)="searchSubmit()"
(blur)="onBlur()" (blur)="onBlur()"
[placeholder]="'SEARCH.INPUT.PLACEHOLDER' | translate" [placeholder]="'SEARCH.INPUT.PLACEHOLDER' | translate"
autocomplete="off" autocomplete="off"
@@ -54,7 +54,6 @@ describe('SearchInputControlComponent', () => {
it('should not emit submit event if form is invalid', () => { it('should not emit submit event if form is invalid', () => {
component.searchTerm = ''; component.searchTerm = '';
spyOn(component.submit, 'emit'); spyOn(component.submit, 'emit');
component.searchSubmit(); component.searchSubmit();
expect(component.submit.emit).not.toHaveBeenCalled(); expect(component.submit.emit).not.toHaveBeenCalled();
@@ -90,6 +90,7 @@ export class SearchInputControlComponent implements OnInit {
searchSubmit() { searchSubmit() {
this.searchFieldFormControl.markAsTouched(); this.searchFieldFormControl.markAsTouched();
const trimmedTerm = this.searchTerm?.trim(); const trimmedTerm = this.searchTerm?.trim();
if (this.searchFieldFormControl.valid && trimmedTerm?.length > 0) { if (this.searchFieldFormControl.valid && trimmedTerm?.length > 0) {
this.submit.emit(trimmedTerm); this.submit.emit(trimmedTerm);
@@ -1,12 +1,10 @@
<button class="app-search-container" [matMenuTriggerFor]="searchOptionsMenu" (menuOpened)="onMenuOpened()" (menuClosed)="syncInputValues()"> <button class="app-search-container"
[matMenuTriggerFor]="searchOptionsMenu"
(menuOpened)="onMenuOpened()"
(menuClosed)="syncInputValues()"
>
<mat-form-field class="app-input-form-field" appearance="outline"> <mat-form-field class="app-input-form-field" appearance="outline">
<button <button class="aca-search-input--search-button" mat-icon-button matPrefix (click)="searchByOption()" [title]="'SEARCH.BUTTON.TOOLTIP' | translate">
class="aca-search-input--search-button"
mat-icon-button
matPrefix
(click)="searchByOption()"
[title]="'SEARCH.BUTTON.TOOLTIP' | translate"
>
<mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon> <mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon>
</button> </button>
@@ -22,12 +20,7 @@
<div matSuffix> <div matSuffix>
<mat-icon class="app-suffix-icon">arrow_drop_down</mat-icon> <mat-icon class="app-suffix-icon">arrow_drop_down</mat-icon>
<button <button class="aca-search-input--close-button" mat-icon-button [attr.aria-label]="'SEARCH.CLOSE_BUTTON.ARIA_LABEL' | translate" (click)="exitSearch()">
class="aca-search-input--close-button"
mat-icon-button
[attr.aria-label]="'SEARCH.CLOSE_BUTTON.ARIA_LABEL' | translate"
(click)="exitSearch()"
>
<mat-icon class="app-suffix-icon">close</mat-icon> <mat-icon class="app-suffix-icon">close</mat-icon>
</button> </button>
</div> </div>
@@ -43,13 +36,15 @@
(submit)="onSearchSubmit($event)" (submit)="onSearchSubmit($event)"
(searchChange)="onSearchChange($event)" (searchChange)="onSearchChange($event)"
/> />
<mat-error *ngIf="hasLibrariesConstraint" class="app-search-hint"> <div class="app-search-feedback">
{{ 'SEARCH.INPUT.HINT' | translate }} <mat-hint *ngIf="hasLibrariesConstraint" class="app-search-hint">
</mat-error> {{ 'SEARCH.INPUT.HINT' | translate }}
<mat-error </mat-hint>
*ngIf="searchInputControl.searchFieldFormControl.errors?.required && searchInputControl.searchFieldFormControl.touched" class="app-search-error"> <mat-error *ngIf="searchInputControl.searchFieldFormControl.hasError('required') && searchInputControl.searchFieldFormControl.touched" class="app-search-error">
{{ 'SEARCH.INPUT.REQUIRED' | translate }} {{ 'SEARCH.INPUT.REQUIRED' | translate }}
</mat-error> </mat-error>
</div>
<div id="search-options" class="app-search-options"> <div id="search-options" class="app-search-options">
<mat-checkbox *ngFor="let option of searchOptions" <mat-checkbox *ngFor="let option of searchOptions"
id="{{ option.id }}" id="{{ option.id }}"
@@ -71,6 +71,7 @@ describe('SearchInputComponent', () => {
component.searchInputControl.searchFieldFormControl.setValue(''); component.searchInputControl.searchFieldFormControl.setValue('');
component.searchInputControl.searchFieldFormControl.markAsTouched(); component.searchInputControl.searchFieldFormControl.markAsTouched();
fixture.detectChanges(); fixture.detectChanges();
expect(getFirstError()).toBe('SEARCH.INPUT.REQUIRED'); expect(getFirstError()).toBe('SEARCH.INPUT.REQUIRED');
}); });
@@ -79,6 +80,7 @@ describe('SearchInputComponent', () => {
component.searchInputControl.searchFieldFormControl.setValue('test'); component.searchInputControl.searchFieldFormControl.setValue('test');
component.searchInputControl.searchFieldFormControl.markAsTouched(); component.searchInputControl.searchFieldFormControl.markAsTouched();
fixture.detectChanges(); fixture.detectChanges();
const error = fixture.debugElement.query(By.directive(MatError)); const error = fixture.debugElement.query(By.directive(MatError));
expect(error).toBeNull(); expect(error).toBeNull();
}); });
@@ -88,6 +90,7 @@ describe('SearchInputComponent', () => {
component.searchInputControl.searchFieldFormControl.setValue(''); component.searchInputControl.searchFieldFormControl.setValue('');
component.searchInputControl.searchFieldFormControl.markAsUntouched(); component.searchInputControl.searchFieldFormControl.markAsUntouched();
fixture.detectChanges(); fixture.detectChanges();
const error = fixture.debugElement.query(By.directive(MatError)); const error = fixture.debugElement.query(By.directive(MatError));
expect(error).toBeNull(); expect(error).toBeNull();
}); });
@@ -96,8 +99,10 @@ describe('SearchInputComponent', () => {
spyOn(component as any, 'isLibrariesChecked').and.returnValue(true); spyOn(component as any, 'isLibrariesChecked').and.returnValue(true);
spyOn(component as any, 'isFoldersChecked').and.returnValue(false); spyOn(component as any, 'isFoldersChecked').and.returnValue(false);
spyOn(component as any, 'isFilesChecked').and.returnValue(false); spyOn(component as any, 'isFilesChecked').and.returnValue(false);
component.searchedWord = 'test'; component.searchedWord = 'test';
component.onSearchSubmit('Enter'); component.onSearchSubmit('Enter');
expect(store.dispatch).toHaveBeenCalled(); expect(store.dispatch).toHaveBeenCalled();
}); });
@@ -204,8 +204,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
this.syncInputValues(); this.syncInputValues();
this.has400LibraryError = false; this.has400LibraryError = false;
const searchTerm = this.searchedWord?.trim(); if (!this.searchedWord.trim()) {
if (!searchTerm) {
return; return;
} }
@@ -213,8 +212,8 @@ export class SearchInputComponent implements OnInit, OnDestroy {
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint(); this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
if (this.onLibrariesSearchResults && this.isSameSearchTerm()) { if (this.onLibrariesSearchResults && this.isSameSearchTerm()) {
this.queryLibrariesBuilder.update(); this.queryLibrariesBuilder.update();
} else if (searchTerm) { } else if (this.searchedWord) {
this.store.dispatch(new SearchByTermAction(searchTerm, this.searchOptions)); this.store.dispatch(new SearchByTermAction(this.searchedWord, this.searchOptions));
} }
} else { } else {
if (this.isFoldersChecked() && !this.isFilesChecked()) { if (this.isFoldersChecked() && !this.isFilesChecked()) {
@@ -227,8 +226,8 @@ export class SearchInputComponent implements OnInit, OnDestroy {
if (this.onSearchResults && this.isSameSearchTerm()) { if (this.onSearchResults && this.isSameSearchTerm()) {
this.queryBuilder.update(); this.queryBuilder.update();
} else if (searchTerm) { } else if (this.searchedWord) {
this.store.dispatch(new SearchByTermAction(searchTerm, this.searchOptions)); this.store.dispatch(new SearchByTermAction(this.searchedWord, this.searchOptions));
} }
} }
} }