import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing'; import {CprSearchComponent} from './cpr-search.component'; import {MatIconModule} from '@angular/material/icon'; import {FormsModule} from '@angular/forms'; import {PatientContextService} from '../services/patient-context.service'; import {CprSearchEventService} from '../services/cpr-search-event.service'; import {Subject} from 'rxjs'; import {MatRipple} from '@angular/material/core'; describe('CprSearchComponent', () => { let component: CprSearchComponent; let fixture: ComponentFixture; let input: HTMLInputElement; let cprSubjectStub: Subject; let patientExistsSubjectStub: Subject; let patientContextServiceStub: PatientContextService; let cprSearchFabClickedSubjectStub: Subject; let cprSearchEventServiceStub: CprSearchEventService; let cprStringStub: string; let rippleStub: MatRipple; beforeEach(async () => { rippleStub = { launch: () => {} } as any; cprSubjectStub = new Subject(); patientExistsSubjectStub = new Subject(); patientContextServiceStub = { cpr$: cprSubjectStub.asObservable(), setCpr: () => {}, patientExists$: patientExistsSubjectStub.asObservable(), } as any; cprSearchFabClickedSubjectStub = new Subject(); cprSearchEventServiceStub = { cprSearchFabClick$: cprSearchFabClickedSubjectStub.asObservable(), emitCprSearchFocusedEvent: () => {}, } as any; await TestBed.configureTestingModule({ declarations: [ CprSearchComponent ], imports: [MatIconModule, FormsModule], providers: [ {provide: CprSearchEventService, useValue: cprSearchEventServiceStub}, {provide: PatientContextService, useValue: patientContextServiceStub}, ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(CprSearchComponent); component = fixture.componentInstance; fixture.detectChanges(); input = fixture.elementRef.nativeElement.querySelector('input'); cprStringStub = '0101010101'; // valid by default; }); it('should create', () => { expect(component).toBeTruthy(); }); it('focuses when component.focus is called', () => { spyOn(input, 'focus'); component.focus(); expect(input.focus).toHaveBeenCalledTimes(1); }); describe('when a value is typed into input', () => { beforeEach(() => { input.value = cprStringStub; input.dispatchEvent(new Event('input')); }); it('should update internal cpr', () => { expect(component.cpr).toBe(cprStringStub); }); describe('and then patientContext emits new cpr', () => { beforeEach(() => { cprSubjectStub.next(cprStringStub); }); it('should set internal cpr to empty string', () => { expect(component.cpr).toBe(''); }); }); }); it('sets patientContext when valid cpr is searched', () => { spyOn(patientContextServiceStub, 'setCpr'); component.search(cprStringStub); expect(patientContextServiceStub.setCpr).toHaveBeenCalledTimes(1); expect(patientContextServiceStub.setCpr).toHaveBeenCalledWith(cprStringStub); }); it('aborts search if search string is empty', () => { spyOn(patientContextServiceStub, 'setCpr'); component.search(''); expect(patientContextServiceStub.setCpr).toHaveBeenCalledTimes(0); }); describe('when handleEnterPressed is called', () => { beforeEach(() => { // @ts-ignore component.submitButton.ripple = rippleStub; spyOn(component, 'search'); spyOn(rippleStub, 'launch'); component.handleEnterPressed(); }); it('launches a ripple effect on submitButton', () => { expect(rippleStub.launch).toHaveBeenCalledTimes(1); }); it('returns an object with a function that calls this.search', () => { const returnObject = component.handleEnterPressed(); expect(returnObject.andSearch).toBeDefined(); returnObject.andSearch(cprStringStub); expect(component.search).toHaveBeenCalledTimes(1); expect(component.search).toHaveBeenCalledWith(cprStringStub); }); }); describe('when text input is focused', () => { beforeEach((done) => { fixture.whenStable().then(() => { spyOn(cprSearchEventServiceStub, 'emitCprSearchFocusedEvent'); input.dispatchEvent(new Event('focus')); fixture.detectChanges(); done(); }); }); it('adds styling', () => { fixture.detectChanges(); expect(component.wrapper?.nativeElement.classList).toContain('focused'); }); it('emits focused event with value true', () => { expect(cprSearchEventServiceStub.emitCprSearchFocusedEvent).toHaveBeenCalledTimes(1); expect(cprSearchEventServiceStub.emitCprSearchFocusedEvent).toHaveBeenCalledWith(true); }); describe('and then text input is blurred', () => { beforeEach((done) => { fixture.whenStable().then(() => { input.dispatchEvent(new Event('blur')); fixture.detectChanges(); done(); }); }); it('removes styling', () => { fixture.detectChanges(); expect(component.wrapper?.nativeElement.classList.contains('focused')).toBeFalse(); }); it('emits focused event with value false', () => { expect(cprSearchEventServiceStub.emitCprSearchFocusedEvent).toHaveBeenCalledTimes(2); expect(cprSearchEventServiceStub.emitCprSearchFocusedEvent).toHaveBeenCalledWith(false); }); }); }); describe('when cprSearchFabClicked event is emitted', () => { beforeEach(() => { spyOn(component, 'focus'); cprSearchFabClickedSubjectStub.next(); }); it('calls focus function', fakeAsync(() => { expect(component.focus).toHaveBeenCalledTimes(1); })); }); describe('when patientContext.patientExists$ emits true', () => { beforeEach(() => { spyOn(component, 'focus'); patientExistsSubjectStub.next(true); }); it('does not call cprSearchComponent.focus', () => { expect(component.focus).toHaveBeenCalledTimes(0); }); }); describe('when patientContext.patientExists$ emits false', () => { beforeEach(() => { spyOn(component, 'focus'); patientExistsSubjectStub.next(false); }); it('calls cprSearchComponent.focus', () => { expect(component.focus).toHaveBeenCalledTimes(1); }); }); describe('when patientContext.patientExists$ emits undefined', () => { beforeEach(() => { spyOn(component, 'focus'); patientExistsSubjectStub.next(undefined); }); it('calls cprSearchComponent.focus', () => { expect(component.focus).toHaveBeenCalledTimes(1); }); }); });