如何解决如何通过Jest和React-Testing-Library模拟和测试滚动?
给出以下组件:
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 Testing库编写测试以检查单击按钮时包装器上是否触发了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})
})
解决方法
由于 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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。