react-plotly.js单元测试问题:Jest+RTL无法显示组件内容
我正在使用react-plotly.js开发图表组件,想用Jest和React Testing Library完成两个测试目标:一是验证传入数据后线条是否绘制正确,二是测试组件渲染耗时。但运行测试代码时,完全看不到Plotly组件的内部内容,测试结果里只有外层的div[data-testid="plotly"],这是为什么?
我的图表组件
import Plotly from 'react-plotly.js'; const Chart = ({chartData, layout}) => { // ... return ( <div data-testid='plotly'> <Plotly data={chartData} layout={layout} /> </div> ); };
测试代码
import { render } from '@testing-library/react'; describe('<PuiChart /> test', () => { it('matches snapshot', () => { const chart = render( <Chart data={[ { x: [1, 2, 3], y: [4, 5, 6], name: '', mode: 'lines+markers' as const, type: 'scatter' as const, marker: { color: '#cacaca', line: { color: 'black', width: 1 } }, }, ]} layout={{ title: { text: 'TITLE EXAMPLE' }, }} /> ); screen.debug(); expect(chart.container).toMatchSnapshot(); }); });
测试结果
<div data-testid="plotly" />
出现这个问题主要有两个核心原因:
Plotly是异步渲染的
react-plotly.js内部依赖Plotly.js完成图表渲染,这个过程是异步的——组件挂载后,Plotly需要时间解析数据、生成SVG/Canvas元素。而你的测试是同步执行的,调用render后立刻执行screen.debug()和快照断言,这时候Plotly还没完成渲染,自然看不到内部内容。测试环境缺少必要的浏览器API
Jest默认用jsdom模拟浏览器环境,但jsdom没有完全实现Plotly渲染需要的Canvas、SVG相关API,比如Canvas的绘图上下文、SVG的某些布局属性。这会导致Plotly在测试环境中无法正常初始化渲染,直接跳过了内部DOM的生成。
解决办法
方法一:等待异步渲染完成
用React Testing Library的waitFor或findBy*系列查询方法,等待Plotly生成的DOM元素出现后再做断言:
import { render, screen, waitFor } from '@testing-library/react'; describe('<Chart /> test', () => { it('renders plot content correctly', async () => { render( <Chart data={[/* 你的测试数据 */]} layout={{/* 你的测试布局 */}} /> ); // 等待Plotly生成的图表容器出现(Plotly通常会生成带role="img"的元素) await waitFor(() => { const plotElement = screen.getByRole('img'); expect(plotElement).toBeInTheDocument(); }); // 此时再执行快照或其他断言 screen.debug(); expect(screen.getByTestId('plotly')).toMatchSnapshot(); }); });
方法二:Mock react-plotly.js组件
如果不需要测试Plotly本身的渲染逻辑,只需要验证组件是否正确传递props给Plotly,可以直接Mock掉这个组件:
// 在测试文件顶部Mock react-plotly.js jest.mock('react-plotly.js', () => { return function MockPlotly({ data, layout }) { return ( <div data-testid="mock-plotly" data-data={JSON.stringify(data)} data-layout={JSON.stringify(layout)} /> ); }; }); describe('<Chart /> test', () => { it('passes correct props to Plotly', () => { const testData = [/* 你的测试数据 */]; const testLayout = {/* 你的测试布局 */}; render(<Chart chartData={testData} layout={testLayout} />); const mockPlot = screen.getByTestId('mock-plotly'); expect(JSON.parse(mockPlot.dataset.data)).toEqual(testData); expect(JSON.parse(mockPlot.dataset.layout)).toEqual(testLayout); }); });
方法三:补充测试环境的API支持
安装jest-canvas-mock来模拟Canvas环境,让Plotly能正常初始化:
- 安装依赖:
npm install --save-dev jest-canvas-mock - 在Jest配置文件(
jest.config.js)中添加:
module.exports = { setupFiles: ['jest-canvas-mock'], };
之后再运行测试,Plotly应该能生成基本的DOM结构了。
内容的提问来源于stack exchange,提问作者ijyu

