Search code examples
javascriptangularjestjsjasmine

How to test HostListener window scroll on Angular?


I'm having difficulties to test this function and both conditions, does anyone can help?

@HostListener('window:scroll', ['$event'])
onWindowScroll(event: Event) {
    const numb = window.scrollY;
    if (numb >= 50){
        this.scrolled = true;
    }
    else {
        this.scrolled = false;
    }
}

Solution

  • I would recommend injecting the window by doing something like:

    constructor(@Inject(DOCUMENT) private readonly document: Document) {
      this.window = this.document.defaultView;
    }
    
    @HostListener('window:scroll', ['$event'])
    onWindowScroll(event: Event) {
      this.scrolled = this.window.scrollY >= 50;
    }
    

    Then, assuming you are using something like Jasmine/Karma to write your tests, in your spec you can inject the window and dispatch fake scroll events to test the response.

    let mockWindow: any;
    beforeEach(() => {
      mockWindow = document.createElement('div');
      TestBed.configureTestingModule({
        declarations: [TestComponent],
        providers: [{ provide: DOCUMENT, useValue: { defaultView: mockWindow } }]
      });
    });
    
    it('responds to scroll events' () => {
      Object.defineProperty(mockWindow, 'scrollY', { value: 100 });
      mockWindow.dispatchEvent(new Event('scroll'));
      expect(fixture.componentInstance.scrolled).toBe(true);
    });
    

    Here I have also faked the scrollY with defineProperty in order to make the tests sane.

    Caveat: I have not done this with the @HostListener('window:scroll'), but it has worked for me using @HostListener('window:resize') so I imagine it will work similarly. I wrote this all freehand, so I wouldn't expect it to run perfectly if copy/pasted.