import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {ModalComponent} from './modal.component'; import {By} from '@angular/platform-browser'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {DirtyGuard} from '../../confirm-navigation-if-dirty.framework'; import createSpy = jasmine.createSpy; import createSpyObj = jasmine.createSpyObj; import {of} from 'rxjs'; import {delay} from 'rxjs/operators'; import SpyObj = jasmine.SpyObj; describe('ModalComponent', () => { let component: ModalComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ ModalComponent ], imports: [ BrowserAnimationsModule ], providers: [ {provide: DirtyGuard, useValue: {canDeactivate: () => true}} ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(ModalComponent); component = fixture.componentInstance; component.setVisible(true); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should close when clicking on the overlay', () => { expect(component.isModalVisible).toBeTruthy(); const overlay = fixture.debugElement.query(By.css('.overlay')).nativeElement; overlay.dispatchEvent(new Event('click')); expect(component.isModalVisible).toBeFalse(); }); it('emits modalClosed-event when closed', () => { expect(component.isModalVisible).toBeTruthy(); const onClose = () => undefined; const spy = createSpy('onClose', onClose); component.modalClosed.subscribe(() => spy()); const overlay = fixture.debugElement.query(By.css('.overlay')).nativeElement; overlay.dispatchEvent(new Event('click')); expect(component.isModalVisible).toBeFalse(); expect(spy).toHaveBeenCalled(); }); it('does not emit modalClosed-event when opened', () => { expect(component.isModalVisible).toBeTruthy(); const onClose = () => undefined; const spy = createSpy('onClose', onClose); component.modalClosed.subscribe(() => spy()); const overlay = fixture.debugElement.query(By.css('.overlay')).nativeElement; overlay.dispatchEvent(new Event('click')); expect(component.isModalVisible).toBeFalse(); expect(spy).toHaveBeenCalledTimes(1); component.setVisible(true); fixture.detectChanges(); expect(spy).toHaveBeenCalledTimes(1); }); }); describe('ModalComponents way of hooking in to dirty-checking framework', () => { let component: ModalComponent; let fixture: ComponentFixture; let spy: SpyObj; beforeEach(async () => { spy = createSpyObj(['canDeactivate']); await TestBed.configureTestingModule({ declarations: [ ModalComponent ], imports: [ BrowserAnimationsModule ], providers: [ {provide: DirtyGuard, useValue: spy} ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(ModalComponent); component = fixture.componentInstance; component.setVisible(true); fixture.detectChanges(); }); it('just closes if it does not have a form', () => { expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeFalse(); }); it('closes if form is dirty and user accepts warning', fakeAsync(() => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(of(true)); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); tick(); expect(component.isModalVisible).toBeFalse(); })); it('does not close if form is dirty and user want s to stay', fakeAsync(() => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(of(false)); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); tick(); expect(component.isModalVisible).toBeTrue(); })); it('does not open more than one "diry-check"-dialog at any given time', fakeAsync(() => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(of(true).pipe(delay(200))); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); tick(); component.setVisible(false); tick(200); expect(component.isModalVisible).toBeFalse(); expect(spy.canDeactivate).toHaveBeenCalledTimes(1); })); it('handles that guard returns boolean', () => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(true); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeFalse(); }); it('handles that guard returns promise', fakeAsync(() => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(Promise.resolve(true).then(x => new Promise(resolve => setTimeout(() => resolve(x), 200)))); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeTrue(); tick(200); expect(component.isModalVisible).toBeFalse(); })); it('handles that guard returns boolean', () => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(true); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeFalse(); }); it('handles that guard returns promise', fakeAsync(() => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(Promise.resolve(true).then(x => new Promise(resolve => setTimeout(() => resolve(x), 200)))); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeTrue(); tick(200); expect(component.isModalVisible).toBeFalse(); })); it('handles that guard returns boolean and user wants to stay', () => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(false); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeTrue(); }); it('handles that guard returns promise and user wants to stay', fakeAsync(() => { component.forms = {first: {submitted: false, dirty: true}} as any; spy.canDeactivate.and.returnValue(Promise.resolve(false).then(x => new Promise(resolve => setTimeout(() => resolve(x), 200)))); fixture.detectChanges(); expect(component.isModalVisible).toBeTrue(); component.setVisible(false); expect(component.isModalVisible).toBeTrue(); tick(200); expect(component.isModalVisible).toBeTrue(); })); });