import {DirtyGuard, FormComponent, RouterOutletDirtyWatchDirective} from './confirm-navigation-if-dirty.framework';
import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing';
import {RouterModule, RouterOutlet} from '@angular/router';
import {Observable, of} from 'rxjs';
import {Component, EventEmitter} from '@angular/core';
import {NgForm} from '@angular/forms';
import {environment} from '../environments/environment';
import {DialogService} from './modals/dialog/dialog.service';
@Component({
selector: 'app-dirty-form-test',
template: '
test form
'
})
class TestDialogComponent extends FormComponent {
public formMock = {
submitted: false,
dirty: false
};
public makeDirty(): void {
this.formMock.dirty = true;
}
get form(): NgForm | undefined {
return this.formMock as unknown as NgForm;
}
}
describe('Dirty checking frameworks', () => {
describe('RouterOutletPlugin', () => {
let fixture: ComponentFixture;
let component: TestDialogComponent;
let directive: RouterOutletDirtyWatchDirective;
beforeEach(() => {
environment.production = false;
fixture = TestBed.createComponent(TestDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
directive = new RouterOutletDirtyWatchDirective({
activateEvents: of(component) as EventEmitter,
deactivateEvents: of(undefined) as unknown as EventEmitter
} as unknown as RouterOutlet);
});
it('should create an instance', () => {
expect(directive).toBeTruthy();
});
it('prevents page reloads if component is dirty', fakeAsync(() => {
component.makeDirty();
fixture.detectChanges();
expect(component.isDirty()).toBeTrue();
// We're not in production mode, so we don't expect reloads to be blocked
expect(directive.canDeactivate(new Event('test'))).toBeTrue();
environment.production = true;
expect(directive.canDeactivate(new Event('test'))).toBeFalse();
}));
it('allows page reloads if component is not dirty', () => {
expect(directive.canDeactivate(new Event('test'))).toBeTrue();
});
});
describe('DirtyGuard', () => {
let service: DirtyGuard;
let fixture: ComponentFixture;
let component: TestDialogComponent;
let dialogChoice: boolean;
const dialogService = {show(): Observable { return of(dialogChoice); }, testInstance: true};
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestDialogComponent],
imports: [RouterModule],
providers: [
{provide: DialogService, useValue: dialogService},
]
});
dialogChoice = false;
service = TestBed.inject(DirtyGuard);
fixture = TestBed.createComponent(TestDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create an instance', () => {
expect(service).toBeTruthy();
});
it('prevents routing if component is dirty', (done) => {
const spy = spyOn(dialogService, 'show').and.callThrough();
component.makeDirty();
fixture.detectChanges();
const waitForUserToConfirmNavigation: Observable = service.canDeactivate(component) as Observable;
waitForUserToConfirmNavigation.subscribe((result) => {
expect(spy).toHaveBeenCalled();
expect(result).toBeFalse();
done();
});
});
it('allows routing if component is not dirty', () => {
const spy = spyOn(dialogService, 'show').and.callThrough();
const canNavigate: boolean = service.canDeactivate(component) as boolean;
expect(spy).not.toHaveBeenCalled();
expect(canNavigate).toBeTrue();
});
it('allows routing if component does not implement ConfirmIfDirty', () => {
const spy = spyOn(dialogService, 'show').and.callThrough();
const canNavigate: boolean = service.canDeactivate({}) as boolean;
expect(spy).not.toHaveBeenCalled();
expect(canNavigate).toBeTrue();
});
});
});