Jest模拟交叉点观察者

qc6wkl3g  于 2022-12-08  发布在  Jest
关注(0)|答案(4)|浏览(180)

我有以下方法:

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;
        }
      };

并且我尝试测试IntersectionObserver.观察调用,如下所示:

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();
      });

但是不能让它工作,我的mockObserveFn.observe没有被调用,任何建议

qvtsj1bj

qvtsj1bj1#

您的mockObserveFn.observe尚未被调用,因为它不存在。
可能会出现以下错误:

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

您可以像这样定义mock

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,
}))

然后你可以期待:

expect(observe).toHaveBeenCalled();
bxjv4tth

bxjv4tth2#

这个解决方案对我很有效。
基本上,您只需将IntersectionMock放在Each之前

beforeEach(() => {
  // IntersectionObserver isn't available in test environment
  const mockIntersectionObserver = jest.fn();
  mockIntersectionObserver.mockReturnValue({
    observe: () => null,
    unobserve: () => null,
    disconnect: () => null
  });
  window.IntersectionObserver = mockIntersectionObserver;
});
vd8tlhqk

vd8tlhqk3#

我建议使用维护良好的npm库jsdom-testing-mocks,而不是这些自定义解决方案。

import { screen, render } from '@testing-library/react'
import { mockIntersectionObserver } from 'jsdom-testing-mocks'
import React from 'react'

import App from './App'

mockIntersectionObserver()

describe('Test App component', () => {
  it('renders App heading', () => {
    render(<App />)
    const h1Elem = screen.getByText(/app heading/i)
    expect(h1Elem).toBeInTheDocument()
  })
})
at0kjp5o

at0kjp5o4#

实际上不应该调用处理程序,但这是我可以触发它的方式,因为我们不能真正触发视图。

const observeMock = jest.fn();
const disconnectMock = jest.fn();

beforeEach(() => {
    const mockIntersectionObserver = class IO {
        constructor(handler) {
            this.handler = handler;
        }

        observe(element) {
            observeMock();
            this.handler([{
                intersectionRatio: element.intersectionRatio,
                target: element
            }]);
        }

        disconnect() {
            disconnectMock();
        }
    };
    window.IntersectionObserver = mockIntersectionObserver;
});

相关问题