Search code examples
mockingjestjsstenciljs

Jest Mock IntersectionObserver


I have the following method:

    componentDidLoad() {
        this.image = this.element.shadowRoot.querySelector('.lazy-img');
        this.observeImage();
      }

    observeImage = () => {
        if ('IntersectionObserver' in window) {
          const options = {
            rootMargin: '0px',
            threshold: 0.1
          };
    
          this.observer = new window.IntersectionObserver(
            this.handleIntersection,
            options
          );
    
          this.observer.observe(this.image);
        } else {
          this.image.src = this.src;
        }
      };

and I trying to test for IntersectionObserver.observe call like this:

    it('should create an observer if IntersectionObserver is available', async () => {
        await newSpecPage({
          components: [UIImageComponent],
          html: `<ui-image alt="Lorem ipsum dolor sit amet" src="http://image.example.com"></ui-image>`
        });
    
        const mockObserveFn = () => {
          return {
            observe: jest.fn(),
            unobserve: jest.fn()
          };
        };
    
        window.IntersectionObserver = jest
          .fn()
          .mockImplementation(mockObserveFn);
    
        const imageComponent = new UIImageComponent();
        imageComponent.src = 'http://image.example.com';
    
        const mockImg = document.createElement('img');
        mockImg.setAttribute('src', null);
        mockImg.setAttribute('class', 'lazy-img');
    
        imageComponent.element.shadowRoot['querySelector'] = jest.fn(() => {
          return mockImg;
        });
        expect(imageComponent.image).toBeNull();
        imageComponent.componentDidLoad();
    
        expect(mockObserveFn['observe']).toHaveBeenCalled();
      });

But can't make it work, my mockObserveFn.observe have not been call, any suggestion


Solution

  • Your mockObserveFn.observe has not been called, because it does not exists.

    probably you're getting the following error:

    Matcher error: received value must be a mock or spy function
    

    You can define your mock like this

    const observe = jest.fn();
    const unobserve = jest.fn();
    
    // you can also pass the mock implementation
    // to jest.fn as an argument
    window.IntersectionObserver = jest.fn(() => ({
      observe,
      unobserve,
    }))
    

    and then you can expect:

    expect(observe).toHaveBeenCalled();