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