【问题标题】:How to mock and test scrollBy with Jest and React-Testing-Library?如何使用 Jest 和 React-Testing-Library 模拟和测试 scrollBy?
【发布时间】:2020-09-02 08:57:22
【问题描述】:

给定以下组件:

import * as React from "react";
import "./styles.css";

export default function App() {
  const scrollContainerRef = React.useRef<HTMLDivElement | null>(null);

  const handleClick = () => {
    scrollContainerRef?.current?.scrollBy({ top: 0, left: 100 });
  };

  return (
    <div aria-label="wrapper" ref={scrollContainerRef}>
      <button onClick={handleClick}>click</button>
    </div>
  );
}

如何使用 Jest 和 React 测试库编写测试以检查单击按钮时是否在包装器上触发 scrollBy

我尝试了以下方法,但它似乎不起作用:

test('Clicking on button should trigger scroll',() => {
  const myMock = jest.fn();
  Object.defineProperty(HTMLElement.prototype, 'scrollBy', {
    configurable: true,
    value: myMock(),
  })
  render(<MyComponent />)
  fireEvent.click(screen.getByText(/click/i))
  expect(myMock).toHaveBeenCalledWith({top: 0, left: 100})
})

【问题讨论】:

    标签: reactjs mocking jestjs react-hooks react-testing-library


    【解决方案1】:

    由于jsdom 没有实现Element.scrollBy() 方法,请参阅PR。我们可以用getter和setter创建一个mocked ref对象来拦截React对ref.current的赋值过程,并在过程中安装spy或者添加mock。

    例如

    App.tsx:

    import * as React from 'react';
    
    export default function App() {
      const scrollContainerRef = React.useRef<HTMLDivElement | null>(null);
    
      const handleClick = () => {
        scrollContainerRef?.current?.scrollBy({ top: 0, left: 100 });
      };
    
      return (
        <div aria-label="wrapper" ref={scrollContainerRef}>
          <button onClick={handleClick}>click</button>
        </div>
      );
    }
    

    App.test.tsx:

    import React, { useRef } from 'react';
    import { render, screen, fireEvent } from '@testing-library/react';
    import { mocked } from 'ts-jest/utils';
    import App from './App';
    
    jest.mock('react', () => {
      return {
        ...jest.requireActual<typeof React>('react'),
        useRef: jest.fn(),
      };
    });
    
    const useMockRef = mocked(useRef);
    
    describe('63702104', () => {
      afterAll(() => {
        jest.resetAllMocks();
      });
      test('should pass', () => {
        const ref = { current: {} };
        const mScrollBy = jest.fn();
        Object.defineProperty(ref, 'current', {
          set(_current) {
            if (_current) {
              _current.scrollBy = mScrollBy;
            }
            this._current = _current;
          },
          get() {
            return this._current;
          },
        });
        useMockRef.mockReturnValueOnce(ref);
        render(<App />);
        fireEvent.click(screen.getByText(/click/i));
        expect(mScrollBy).toBeCalledWith({ top: 0, left: 100 });
      });
    });
    

    测试结果:

     PASS  examples/63702104/App.test.tsx (9.436 s)
      63702104
        ✓ should pass (33 ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |     100 |       75 |     100 |     100 |                   
     App.tsx  |     100 |       75 |     100 |     100 | 7                 
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        10.21 s
    

    【讨论】:

      猜你喜欢
      • 2021-02-11
      • 2020-03-22
      • 2021-02-28
      • 1970-01-01
      • 2020-05-14
      • 2020-03-24
      • 2023-03-17
      • 2021-12-29
      • 1970-01-01
      相关资源
      最近更新 更多