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

如何用React Testing Library和Jest测试React组件中的D3缩放行为?

解决方案

1. 确保事件监听器完成绑定

D3的事件绑定在useEffect中执行,React Testing Library的render完成后可能需要等待DOM更新完成。可以用requestAnimationFrame确保绑定完成,同时补充D3需要的事件属性:

import { render, fireEvent, waitFor } from '@testing-library/react';
import MyD3Component from './MyD3Component';

test('zoom behavior triggers on wheel event', async () => {
  const { getByTestId } = render(<MyD3Component />);
  const svgElement = getByTestId('graph-container');

  // 等待D3完成事件绑定
  await new Promise(resolve => requestAnimationFrame(resolve));

  fireEvent.wheel(svgElement, {
    deltaY: -100,
    deltaMode: 0, // D3依赖该属性判断缩放单位(0=像素)
    clientX: 150, // 提供缩放中心点,D3默认需要这个计算变换
    clientY: 150,
    bubbles: true,
    cancelable: true
  });

  // 此处添加你的断言逻辑
});

2. 显式跟踪缩放状态,便于断言

在组件中用useState跟踪缩放比例,同时渲染可查询的元素,让测试能直接验证状态变化:

修改后的组件

import React, { useMemo, useRef, useEffect, useState } from 'react';
import * as d3 from 'd3';

const MyD3Component = () => {
  const svgRef = useRef(null);
  const [scale, setScale] = useState(1);

  const zoomBehavior = useMemo(() => d3.zoom()
    .on('zoom', (event) => {
      setScale(event.transform.k);
      // 其他缩放逻辑...
    }), []);

  useEffect(() => {
    const svg = d3.select(svgRef.current);
    svg.call(zoomBehavior);
  }, [zoomBehavior]);

  return (
    <svg ref={svgRef} data-testid="graph-container" width={300} height={300}>
      {/* 渲染缩放值,供测试查询 */}
      <text data-testid="current-scale" x={10} y={20}>{scale.toFixed(2)}</text>
    </svg>
  );
};

export default MyD3Component;

修改后的测试

test('zoom increases scale on wheel event', async () => {
  const { getByTestId } = render(<MyD3Component />);
  const svgElement = getByTestId('graph-container');

  await new Promise(resolve => requestAnimationFrame(resolve));

  fireEvent.wheel(svgElement, {
    deltaY: -100,
    deltaMode: 0,
    clientX: 150,
    clientY: 150
  });

  // 等待缩放状态更新
  await waitFor(() => {
    expect(getByTestId('current-scale').textContent).toBeGreaterThan('1.00');
  });
});

3. 直接调用D3缩放方法(绕过原生事件)

如果原生事件模拟存在环境兼容问题,可以直接通过D3的API触发缩放变换,跳过事件模拟步骤:

import { render, waitFor } from '@testing-library/react';
import * as d3 from 'd3';
import MyD3Component from './MyD3Component';

test('zoom behavior updates scale correctly', async () => {
  const { getByTestId } = render(<MyD3Component />);
  const svgElement = getByTestId('graph-container');
  const d3Svg = d3.select(svgElement);

  // 直接应用缩放变换
  d3Svg.call(d3.zoom().transform, d3.zoomIdentity.scale(2));

  await waitFor(() => {
    expect(getByTestId('current-scale').textContent).toBe('2.00');
  });
});

内容的提问来源于stack exchange,提问作者Syed Usama Amer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:55:53