Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 839
Jean Avatar asked Nov 15 '19 20:11

Jean


2 Answers

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();
like image 177
Teneff Avatar answered Sep 20 '22 09:09

Teneff


This solution works for me.

Basicly you just put IntersectionMock inside beforeEach

beforeEach(() => {
  // IntersectionObserver isn't available in test environment
  const mockIntersectionObserver = jest.fn();
  mockIntersectionObserver.mockReturnValue({
    observe: () => null,
    unobserve: () => null,
    disconnect: () => null
  });
  window.IntersectionObserver = mockIntersectionObserver;
});
like image 22
Yudi Krisnandi Avatar answered Sep 19 '22 09:09

Yudi Krisnandi