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

如何在Jest中测试包含window.print()的React函数组件?

我来帮你梳理下如何用Jest结合React Testing Library测试这个SixLabelReport组件,核心要覆盖模态框激活时触发打印、打印后自动关闭模态框这两个关键逻辑,话不多说直接上步骤和代码:

1. 准备测试依赖

首先确保你已经安装了常规的React测试套件:@testing-library/react、@testing-library/jest-dom以及Jest本身。另外,因为测试环境没有真实的浏览器打印功能,我们需要提前模拟window.print方法。

2. 核心测试用例设计

用例1:模态框激活时触发打印并关闭模态框

这个是组件的核心逻辑,我们需要验证当modalIsVisible为true时,window.print被调用,且setModalIsVisible会被传入false来关闭模态框。

import { render, waitFor } from '@testing-library/react';
import SixLabelReport from './SixLabelReport';
import type { LabelProps } from './your-types-path'; // 替换成你的类型文件路径

describe('SixLabelReport Component', () => {
  // 构造符合LabelProps的测试数据,根据实际类型调整
  const mockLabelData: LabelProps = {
    deliveryData: { id: 'test-delivery', trackingNo: '12345' },
    recipientData: { name: 'Test Recipient', address: 'Test Address' },
    senderData: { name: 'Test Sender', address: 'Test Sender Address' }
  };
  const mockLabels = [mockLabelData];

  // 每次测试前重置window.print的模拟
  beforeEach(() => {
    jest.spyOn(window, 'print').mockImplementation(() => {});
  });

  // 测试后恢复原方法,避免影响其他测试
  afterEach(() => {
    jest.restoreAllMocks();
  });

  it('triggers window.print and closes modal when modal is visible', async () => {
    const mockSetModalIsVisible = jest.fn();

    // 渲染组件,传入激活状态的模态框参数
    render(
      <SixLabelReport
        labels={mockLabels}
        modalIsVisible={true}
        setModalIsVisible={mockSetModalIsVisible}
      />
    );

    // 断言print方法被调用一次
    expect(window.print).toHaveBeenCalledTimes(1);

    // 等待useEffect异步执行完成,断言模态框被关闭
    await waitFor(() => {
      expect(mockSetModalIsVisible).toHaveBeenCalledWith(false);
    });
  });

用例2:模态框隐藏时不触发任何打印逻辑

验证当modalIsVisible为false时,组件不会调用window.print,也不会触发模态框状态更新:

it('does not trigger print or modal close when modal is hidden', () => {
    const mockSetModalIsVisible = jest.fn();

    render(
      <SixLabelReport
        labels={mockLabels}
        modalIsVisible={false}
        setModalIsVisible={mockSetModalIsVisible}
      />
    );

    // 确认print没被调用
    expect(window.print).not.toHaveBeenCalled();
    // 确认模态框状态更新函数没被触发
    expect(mockSetModalIsVisible).not.toHaveBeenCalled();
  });

用例3:渲染正确数量的Label子组件

验证组件能根据传入的labels数组,渲染对应数量的Label组件:

it('renders correct number of Label components', () => {
    // 构造2条测试数据
    const testLabels = [mockLabelData, mockLabelData];
    const { getAllByTestId } = render(
      <SixLabelReport
        labels={testLabels}
        modalIsVisible={false}
        setModalIsVisible={jest.fn()}
      />
    );

    // 通过组件上的data-testid获取所有Label实例,断言数量匹配
    expect(getAllByTestId('six-label-report-label')).toHaveLength(testLabels.length);
  });
});

3. 额外注意事项

  • 关于waitFor:因为useEffect是在组件挂载后异步执行的,所以必须用waitFor包裹状态更新的断言,确保逻辑完全执行完毕后再验证。
  • 样式组件的处理:如果S.Modal和S.Container是styled-components这类样式组件,测试时不需要额外处理,React Testing Library会正常渲染它们,我们只需要关注组件的行为逻辑即可。
  • 测试数据准确性:一定要保证mockLabels的结构完全符合LabelProps的类型定义,避免出现类型错误影响测试结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:44:07