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

如何用JEST+React Testing Library测试自定义Filter组件及各字段功能

React Filter 组件 Jest + React Testing Library 测试方案

前置依赖确认

确保项目已安装以下测试依赖:

  • @testing-library/react v14+
  • @testing-library/jest-dom
  • @testing-library/user-event v14+
  • jest v28+

以下测试用例基于Filter组件常规props逻辑编写,你可以根据实际组件的入参配置调整对应参数。

核心测试场景覆盖

1. 基础渲染校验

  • 所有配置的字段(文本框、下拉框、日期选择器等)按预期渲染
  • 字段标签、占位符、默认值与配置一致

2. 交互逻辑校验

  • 各类型字段输入/选择后值实时同步
  • 重置、查询按钮点击后对应逻辑正常触发

3. 格式规则校验

  • 邮箱、手机号等特殊字段非法格式触发对应错误提示
  • 必填字段空值提交触发必填校验

可运行测试代码示例

Filter 组件完整测试代码

import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Filter from './Filter';

// 替换为你实际的Filter组件配置
const mockFilterConfig = [
  {
    type: 'text',
    name: 'username',
    label: '用户名',
    placeholder: '请输入用户名'
  },
  {
    type: 'email',
    name: 'email',
    label: '邮箱',
    placeholder: '请输入绑定邮箱',
    validation: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val) ? '' : '邮箱格式不正确'
  },
  {
    type: 'select',
    name: 'role',
    label: '用户角色',
    options: [
      { label: '超级管理员', value: 'super_admin' },
      { label: '普通用户', value: 'general_user' }
    ]
  }
];

describe('Filter 组件全场景测试', () => {
  const user = userEvent.setup();

  // 基础渲染测试
  test('所有配置字段正常渲染', () => {
    render(<Filter config={mockFilterConfig} />);
    // 校验用户名文本框存在
    expect(screen.getByRole('textbox', { name: /用户名/ })).toBeInTheDocument();
    // 校验邮箱文本框存在
    expect(screen.getByRole('textbox', { name: /邮箱/ })).toBeInTheDocument();
    // 校验角色下拉框存在
    expect(screen.getByRole('combobox', { name: /用户角色/ })).toBeInTheDocument();
  });

  // 文本框输入交互测试
  test('文本框输入内容正常同步', async () => {
    render(<Filter config={mockFilterConfig} />);
    const usernameInput = screen.getByRole('textbox', { name: /用户名/ });
    await user.type(usernameInput, 'test001');
    expect(usernameInput).toHaveValue('test001');
  });

  // 邮箱格式校验测试
  test('邮箱字段非法格式触发错误提示', async () => {
    render(<Filter config={mockFilterConfig} />);
    const emailInput = screen.getByRole('textbox', { name: /邮箱/ });
    // 输入非法邮箱触发失焦校验
    await user.type(emailInput, 'test-wrong-format');
    await user.tab();
    await waitFor(() => {
      expect(screen.getByText('邮箱格式不正确')).toBeInTheDocument();
    });
    // 输入合法邮箱后错误提示消失
    await user.clear(emailInput);
    await user.type(emailInput, 'test@example.com');
    await user.tab();
    await waitFor(() => {
      expect(screen.queryByText('邮箱格式不正确')).not.toBeInTheDocument();
    });
  });

  // 下拉框选择交互测试
  test('下拉框选项选择后值正常更新', async () => {
    render(<Filter config={mockFilterConfig} />);
    const roleSelect = screen.getByRole('combobox', { name: /用户角色/ });
    await user.selectOptions(roleSelect, 'super_admin');
    expect(roleSelect).toHaveValue('super_admin');
  });

  // 重置功能测试
  test('点击重置按钮后所有字段值清空', async () => {
    const mockResetCallback = jest.fn();
    render(<Filter config={mockFilterConfig} onReset={mockResetCallback} />);
    // 先填充字段内容
    await user.type(screen.getByRole('textbox', { name: /用户名/ }), 'test001');
    await user.selectOptions(screen.getByRole('combobox', { name: /用户角色/ }), 'super_admin');
    // 点击重置
    const resetBtn = screen.getByRole('button', { name: /重置/ });
    await user.click(resetBtn);
    // 校验字段清空、回调触发
    expect(screen.getByRole('textbox', { name: /用户名/ })).toHaveValue('');
    expect(screen.getByRole('combobox', { name: /用户角色/ })).toHaveValue('');
    expect(mockResetCallback).toHaveBeenCalled();
  });
});

RenderTextBox 单独测试代码

import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import RenderTextBox from './RenderTextBox';

test('RenderTextBox 邮箱校验逻辑正常运行', async () => {
  const mockChangeCallback = jest.fn();
  const user = userEvent.setup();
  render(
    <RenderTextBox
      label="邮箱"
      name="email"
      validation={(val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val) ? '' : '格式错误'}
      onChange={mockChangeCallback}
    />
  );
  const input = screen.getByRole('textbox', { name: /邮箱/ });
  await user.type(input, 'wrong-format');
  await user.tab();
  await waitFor(() => {
    expect(screen.getByText('格式错误')).toBeInTheDocument();
  });
  expect(mockChangeCallback).toHaveBeenCalledWith('wrong-format');
});

断言逻辑说明

  • 元素存在校验优先使用getBy*系列API配合toBeInTheDocument(),元素不存在校验使用queryBy*系列API
  • 输入/选择后的值校验使用toHaveValue(),回调触发校验使用jest mock函数配合toHaveBeenCalled()/toHaveBeenCalledWith()
  • 异步场景(错误提示延迟展示、接口联动过滤)使用waitFor包裹断言,等待状态更新完成后再做校验

内容的提问来源于stack exchange,提问作者Arslaan Muhammad Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:27:01