programing

리액트 테스트 라이브러리를 사용하여 장치 테스트에서 작동하도록 RizeObserver를 시뮬레이션하는 방법

iphone6s 2023. 4. 2. 10:07
반응형

리액트 테스트 라이브러리를 사용하여 장치 테스트에서 작동하도록 RizeObserver를 시뮬레이션하는 방법

만약 누군가가 도움을 준다면, ResizeObserver를 사용하여 컴포넌트의 폭을 변경하는 커스텀 훅이 있습니다.문제는 유닛 테스트를 실행하려고 하면 모든 테스트가 중단되고 스냅샷을 보면 돔 내의 모든 요소가 렌더링되지 않는다는 것입니다.ResizeObserver를 구현하기 전까지는 동작하고 있었습니다.ResizeObserver를 정의되지 않도록 joking.mock 하는 방법이 있는지 아는 사람 있나요?아니면 다른 제안들.

import * as React from 'react';
import ResizeObserver from 'resize-observer-polyfill';

const useResizeObserver = (ref: { current: any }) => {
    const [dimensions, setDimensions] = React.useState<DOMRectReadOnly>();
    React.useEffect(() => {
        const observeTarget = ref.current;
        const resizeObserver = new ResizeObserver((entries) => {
            entries.forEach((entry) => {
                setDimensions(entry.contentRect);
            });
        });
        resizeObserver.observe(observeTarget);
        return () => {
            resizeObserver.unobserve(observeTarget);
        };
    }, [ref]);
    return dimensions;
};

export default useResizeObserver;



import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';

import mockFetchProfileActivity from '../../../services/mocks/fetch-profile-activity';
import BarChart from './BarChart';

const component = <BarChart userActivity={mockFetchProfileActivity} />;

describe('Render barElement Chart component', () => {
    const observers: any[] = [];
    let resizeHandler: (observers: any[]) => void;
    (window as any).ResizeObserver = (e: any) => {
        resizeHandler = e;

        return {
            observe(element: any) {
                observers.push(element);
            },
            unobserve(element: any) {
                const i = observers.indexOf(element);
                if (i !== -1) {
                    observers.splice(i, 1);
                }
            }
        };
    };

    it('Matches the snapshot', () => {
        // resizeHandler(observers);
        const container = render(component);
        expect(container).toMatchSnapshot();
    });

    it('when clicking on a chart barElement drilldown "challenges" are shown', async () => {
        // arrange
        const componentRender = render(component);
        waitFor(() => resizeHandler(observers));

        // act
        const barElement = componentRender.container.querySelector('svg rect');

        if (barElement) userEvent.click(barElement);

        // assert
        expect(screen.getByText('Challenge 1')).toBeInTheDocument();
    });
});

개발 종속성으로 polyfill을 추가하고 설정에 다음 행을 추가하도록 선택했습니다.Tests.js/ts:

global.ResizeObserver = require('resize-observer-polyfill')

ResizeObserver를 조롱합니다.

class ResizeObserver {
    observe() {
        // do nothing
    }
    unobserve() {
        // do nothing
    }
    disconnect() {
        // do nothing
    }
}

window.ResizeObserver = ResizeObserver;
export default ResizeObserver;

sample.test.disples

import ResizeObserver from './__mocks__/ResizeObserver';
import module from 'sample';

describe('module', ()=> {
     it('returns an instance of ResizeObserver', () => {
           // do something that uses the resize observer
           // NOTE: The actual observe handler would not be called in jsdom anyway as no resize would be triggered.
           // e.g.
           expect(module.somethingThatReturnAReference to the resize observer).toBeInstanceOf(ResizeObserver);
        });
});

원천

셋업에 추가했습니다.Tests.js/ts 다음 코드:

global.ResizeObserver = jest.fn().mockImplementation(() => ({
    observe: jest.fn(),
    unobserve: jest.fn(),
    disconnect: jest.fn(),
}))

편집: 위의 Import 아래에 다음 행을 추가합니다.describe방법

Create React App 셋업에서도 비슷한 문제가 있었습니다.

이 경우 루트 디렉토리에 다음과 같은 파일을 만들 수 있습니다.setupTest.js다음 코드를 추가합니다.

  import '@testing-library/jest-dom/extend-expect';
  import 'jest-extended';
    
  jest.mock('./hooks/useResizeObserver', () => () => ({
    __esModule: true,
    default: jest.fn().mockImplementation(() => ({
        observe: jest.fn(),
        unobserve: jest.fn(),
        disconnect: jest.fn(),
    })),
  }));

Create React App의 테스트 환경을 구성하기 위한 자세한 내용은 여기를 참조하고 ResizeObserver API를 참조하십시오.

이미 우수한 답변을 바탕으로 리액트 테스트 라이브러리 테스트를 실행하기 위해 다음과 같은 작업을 수행했습니다.

필요한 폴리필 인에 의존합니다.package.json

"devDependencies": {
  ...
  "resize-observer-polyfill": "^1.5.1",
  ...
}

의 갱신setupTests.ts다음과 같이 제출합니다.

import * as ResizeObserverModule from 'resize-observer-polyfill';

(global as any).ResizeObserver = ResizeObserverModule.default;

이제 검사도 잘 될 거야

리액트 프로젝트에서도 같은 문제가 있습니다.저는 이 문제를 아래의 순서로 해결했습니다.

  1. npm i -D resize-observer-polyfill
  2. global.ResizeObserver = require("resize-observer-polyfill");함정에 빠져서Tests.ts

폴리필을 다운로드하는 대신 이 방법을 따를 수 있습니다.

class ResizeObserver {
  constructor(observerCallback) {
    this.observerCallback = observerCallback;
  }

  observe = () => {
    // using actual dom element as mutation observer requires
    // an actual node in dom
    const scrollContainer = document.querySelector(
      '.horizontal-scroll-view__items',
    );
    // Mutation observer observer any changes in DOM tree
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.type === 'attributes') {
          this.observerCallback();
        }
      });
    });

    observer.observe(scrollContainer, { attributes: true });
  };
}

global.ResizeObserver = ResizeObserver;

변환 옵서버를 사용하면 div의 크기를 하드코드로 변경할 수 있으며, 그 속성은 변환 옵서버로 감시됩니다.따라서 콜백 트리거가 발생합니다.

언급URL : https://stackoverflow.com/questions/64558062/how-to-mock-resizeobserver-to-work-in-unit-tests-using-react-testing-library

반응형