mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
#833 Fix Backspace Behaviour in Searchbar
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AutocompleteResultsComponent } from './autocomplete-results.component';
|
||||
import { ResultItemComponent } from './result-item';
|
||||
import { ActiveDescendantKeyManager, Highlightable } from '@angular/cdk/a11y';
|
||||
import { QueryList } from '@angular/core';
|
||||
|
||||
fdescribe('#AutocompleteResultsComponent', () => {
|
||||
let fixture: ComponentFixture<AutocompleteResultsComponent>;
|
||||
let component: AutocompleteResultsComponent;
|
||||
|
||||
let items: QueryList<Highlightable & ResultItemComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AutocompleteResultsComponent, ResultItemComponent],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AutocompleteResultsComponent);
|
||||
component = fixture.componentInstance;
|
||||
items = new QueryList();
|
||||
component['keyManager'] = new ActiveDescendantKeyManager<
|
||||
ResultItemComponent
|
||||
>(items).withWrap();
|
||||
|
||||
spyOn(component, 'ngAfterViewInit').and.callFake(() => {});
|
||||
component.results = [];
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component instanceof AutocompleteResultsComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('Deselect Items on keypress', () => {
|
||||
let activeItemMock: Highlightable & ResultItemComponent;
|
||||
beforeEach(() => {
|
||||
activeItemMock = ({
|
||||
result: 'Test Result',
|
||||
} as unknown) as Highlightable & ResultItemComponent;
|
||||
spyOn(component, 'onKeyDown').and.callThrough();
|
||||
spyOn(component.selectItem, 'emit').and.callFake(() => {});
|
||||
spyOnProperty(component['keyManager'], 'activeItem').and.returnValue(
|
||||
activeItemMock
|
||||
);
|
||||
spyOn(component['keyManager'], 'setActiveItem').and.callFake(() => {});
|
||||
});
|
||||
|
||||
it('should deselect the current active item if a letter is typed', () => {
|
||||
const event = new KeyboardEvent('keyup', { key: 'a' });
|
||||
window.dispatchEvent(event);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.onKeyDown).toHaveBeenCalled();
|
||||
expect(component['keyManager'].setActiveItem).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should deselect the current active item if backspace is typed', () => {
|
||||
const event = new KeyboardEvent('keyup', { key: 'Backspace' });
|
||||
window.dispatchEvent(event);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.onKeyDown).toHaveBeenCalled();
|
||||
expect(component['keyManager'].setActiveItem).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should not deselect if ArrowUp is pressed', () => {
|
||||
const event = new KeyboardEvent('keyup', { key: 'ArrowUp' });
|
||||
window.dispatchEvent(event);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.onKeyDown).toHaveBeenCalled();
|
||||
expect(component['keyManager'].setActiveItem).not.toHaveBeenCalledWith(
|
||||
null
|
||||
);
|
||||
expect(component.selectItem.emit).toHaveBeenCalledWith(
|
||||
activeItemMock.result
|
||||
);
|
||||
});
|
||||
|
||||
it('should not deselect if ArrowDown is pressed', () => {
|
||||
const event = new KeyboardEvent('keyup', { key: 'ArrowDown' });
|
||||
window.dispatchEvent(event);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.onKeyDown).toHaveBeenCalled();
|
||||
expect(component['keyManager'].setActiveItem).not.toHaveBeenCalledWith(
|
||||
null
|
||||
);
|
||||
expect(component.selectItem.emit).toHaveBeenCalledWith(
|
||||
activeItemMock.result
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -33,12 +33,16 @@ export class AutocompleteResultsComponent implements AfterViewInit {
|
||||
constructor() {}
|
||||
|
||||
@HostListener('window:keyup', ['$event']) onKeyDown(event: KeyboardEvent) {
|
||||
if (event.key === 'ArrowDown' || 'ArrowUp') {
|
||||
if (this.isUpOrDownKey(event.key)) {
|
||||
this.keyManager.onKeydown(event);
|
||||
if (this.keyManager.activeItem) {
|
||||
this.selectItem.emit(this.keyManager.activeItem.result);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shouldDeselectItem(event.key)) {
|
||||
this.keyManager.setActiveItem(null);
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
@@ -57,4 +61,16 @@ export class AutocompleteResultsComponent implements AfterViewInit {
|
||||
private getItemIndex(item: AutocompleteDTO): number {
|
||||
return this.results.indexOf(item);
|
||||
}
|
||||
|
||||
private shouldDeselectItem(key: string): boolean {
|
||||
const isBackspace = key === 'Backspace';
|
||||
const isLetter = key.length === 1 && /^[a-zA-Z]+$/.test(key);
|
||||
const isNumber = key.length === 1 && /^[0-9]+$/.test(key);
|
||||
|
||||
return isBackspace || isLetter || isNumber;
|
||||
}
|
||||
|
||||
private isUpOrDownKey(key: string): boolean {
|
||||
return key === 'ArrowDown' || key === 'ArrowUp';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user