You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"
/>

解答

出现这个问题主要有两个核心原因:

  1. Plotly是异步渲染的
    react-plotly.js内部依赖Plotly.js完成图表渲染,这个过程是异步的——组件挂载后,Plotly需要时间解析数据、生成SVG/Canvas元素。而你的测试是同步执行的,调用render后立刻执行screen.debug()和快照断言,这时候Plotly还没完成渲染,自然看不到内部内容。

  2. 测试环境缺少必要的浏览器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能正常初始化:

  1. 安装依赖:npm install --save-dev jest-canvas-mock
  2. 在Jest配置文件(jest.config.js)中添加:
module.exports = {
  setupFiles: ['jest-canvas-mock'],
};

之后再运行测试,Plotly应该能生成基本的DOM结构了。


内容的提问来源于stack exchange,提问作者ijyu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:33:27