Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test Window beforeunload event method - Angular Unit Test

I'm working in an Angular 8 project.

I wanted to have the window throw a confirm prompt if the user tried to navigate away from the site, I was able to do this by adding this function to my component.

@HostListener("window:beforeunload", ["$event"])
  unloadNotification($event: any) {
    if (this.confirmNavigation) {
      $event.returnValue = true;
    }
  }

Now I'm trying to figure out how to unit test this, and I'm not sure how to do it. Would I need to mock the window in order to trigger the event? Would I make some sort of event object and call unloadNotification with it directly (not sure how to verify the result of it though)?

I'm even sure if this is needed in unit testing, would it be more of an integration test?

I also need to make sure this prompt isn't actually triggered when I run the tests in karma (because it'll stop the test). So I need to mock that?

Also, I think I want to destroy this listener in the afterEach of my tests, but not sure how.

Any help would be appreciated, thanks.

like image 915
ineedtoknow Avatar asked Jun 08 '26 21:06

ineedtoknow


1 Answers

This solution for unit test is using the mocking concept. This solution works if the method that has unload notification is an abstract class. and which is extended in another component.

File which has unloadNotification method

     export abstract class ComponentCanDeactivate {
      abstract canDeactivate(): Observable<boolean>;
    
      constructor() { }
    
      @HostListener('window:beforeunload', ['$event'])
      async unloadNotification($event: any) {
        this.canDeactivate().subscribe(data => {
          if (data) {
            $event.returnValue = true;
          }
        });
      }

}

Test Component which extends the abstract class

@Component({
    selector: 'test-can-deactivate-mock-host',
    template: '<div></div>',
})
export class CanDeactivateTestComponent extends ComponentCanDeactivate {
    returnValue: boolean;

    constructor() {
        super();
    }

    canDeactivate(): Observable<boolean> {
        return of(this.returnValue);
    }
}

Unit Test

describe('ComponentCanDeactivate', () => {
    let componentCanDeactivate: ComponentCanDeactivate;
    let canDeactivateTestComponent: CanDeactivateTestComponent;
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [MatDialogModule],
            providers: [
                ComponentCanDeactivate,
                CanDeactivateTestComponent
            ],
        });
        componentCanDeactivate = TestBed.get(ComponentCanDeactivate);
        canDeactivateTestComponent = TestBed.get(CanDeactivateTestComponent);
    });

    it('should be created', () => {
        expect(componentCanDeactivate).toBeDefined();
    });

    it('unloadNotification() should perform close event ', () => {
        const canDeactivateSpy = spyOn(canDeactivateTestComponent, 'canDeactivate').and.returnValue(of(true));
        canDeactivateTestComponent.unloadNotification({});
        expect(canDeactivateTestComponent).toBeDefined();
        expect(canDeactivateSpy).toHaveBeenCalled();
    });
});
like image 57
Ashwin Avatar answered Jun 11 '26 11:06

Ashwin