---
title: 测试文档
order: 4
category: pro
---

# PisellQuickFilter 测试文档

## 测试目标

确保 PisellQuickFilter 组件在各种场景下都能正常工作，包括：

- ✅ 基础渲染
- ✅ 属性传递
- ✅ 表单交互
- ✅ 边界情况

## 测试环境

- **测试框架**: Jest
- **测试工具**: React Testing Library
- **测试类型**: 单元测试、集成测试

## 测试用例

### 1. 基础渲染测试

#### 1.1 组件正常渲染

```
import { render } from '@testing-library/react';
import PisellQuickFilter from '../index';

test('should render without crashing', () => {
  const filterList = [
    {
      type: 'input',
      key: 'keyword',
      label: '关键词',
      props: {},
      other: {},
    },
  ];

  const { container } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="filters"
    />
  );

  expect(container).toBeInTheDocument();
});
```

#### 1.2 正确渲染 Form 组件

```
test('should render Form with correct props', () => {
  const filterList = [];
  const { container } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="filters"
    />
  );

  const form = container.querySelector('.filter-form-wrapper');
  expect(form).toBeInTheDocument();
});
```

### 2. 属性传递测试

#### 2.1 filterList 属性传递

```
test('should pass filterList to QuickFilter', () => {
  const filterList = [
    {
      type: 'input',
      key: 'keyword',
      label: '关键词',
      props: { placeholder: '请输入' },
      other: {},
    },
  ];

  const { getByPlaceholderText } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="filters"
    />
  );

  expect(getByPlaceholderText('请输入')).toBeInTheDocument();
});
```

#### 2.2 formFiltersPrefix 属性传递

```
test('should use correct form prefix', () => {
  const filterList = [
    {
      type: 'input',
      key: 'keyword',
      name: 'keyword',
      label: '关键词',
      props: {},
      other: {},
    },
  ];

  const { container } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="customPrefix"
    />
  );

  // 验证表单字段名包含前缀
  const input = container.querySelector('input[name*="customPrefix"]');
  expect(input).toBeInTheDocument();
});
```

### 3. 表单交互测试

#### 3.1 输入框交互

```
import { render, fireEvent } from '@testing-library/react';

test('should handle input change', async () => {
  const filterList = [
    {
      type: 'input',
      key: 'keyword',
      label: '关键词',
      props: { placeholder: '请输入关键词' },
      other: {},
    },
  ];

  const { getByPlaceholderText } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="filters"
    />
  );

  const input = getByPlaceholderText('请输入关键词');
  fireEvent.change(input, { target: { value: 'test keyword' } });

  expect(input.value).toBe('test keyword');
});
```

#### 3.2 下拉选择交互

```
test('should handle select change', async () => {
  const filterList = [
    {
      type: 'single',
      key: 'status',
      label: '状态',
      props: {
        options: [
          { label: '全部', value: '' },
          { label: '启用', value: '1' },
        ],
      },
      other: {},
    },
  ];

  const { getByText } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="filters"
    />
  );

  // 测试选择交互逻辑
  expect(getByText('状态')).toBeInTheDocument();
});
```

### 4. Ref 转发测试

#### 4.1 正确转发 ref

```
import { useRef } from 'react';

test('should forward ref correctly', () => {
  const formRef = useRef(null);
  const filterList = [];

  render(
    <PisellQuickFilter
      ref={formRef}
      filterList={filterList}
      formFiltersPrefix="filters"
    />
  );

  expect(formRef.current).not.toBeNull();
  expect(formRef.current.getFieldsValue).toBeDefined();
});
```

### 5. 边界情况测试

#### 5.1 空筛选项列表

```
test('should render with empty filterList', () => {
  const { container } = render(
    <PisellQuickFilter
      filterList={[]}
      formFiltersPrefix="filters"
    />
  );

  expect(container.querySelector('.filter-form-wrapper')).toBeInTheDocument();
});
```

#### 5.2 未定义 filterList

```
test('should render with undefined filterList', () => {
  const { container } = render(
    <PisellQuickFilter formFiltersPrefix="filters" />
  );

  expect(container.querySelector('.filter-form-wrapper')).toBeInTheDocument();
});
```

#### 5.3 空字符串前缀

```
test('should handle empty string prefix', () => {
  const filterList = [
    {
      type: 'input',
      key: 'keyword',
      label: '关键词',
      props: {},
      other: {},
    },
  ];

  const { container } = render(
    <PisellQuickFilter filterList={filterList} formFiltersPrefix="" />
  );

  expect(container).toBeInTheDocument();
});
```

### 6. 属性透传测试

#### 6.1 其他属性正确传递给 Form

```
test('should pass other props to Form', () => {
  const onFinish = jest.fn();
  const filterList = [];

  const { container } = render(
    <PisellQuickFilter
      filterList={filterList}
      formFiltersPrefix="filters"
      onFinish={onFinish}
      className="custom-class"
    />
  );

  const form = container.querySelector('.custom-class');
  expect(form).toBeInTheDocument();
});
```

## 测试覆盖率要求

- **语句覆盖率**: ≥ 80%
- **分支覆盖率**: ≥ 75%
- **函数覆盖率**: ≥ 80%
- **行覆盖率**: ≥ 80%

## 运行测试

### 运行所有测试

```bash
pnpm test
```

### 运行单个组件测试

```bash
pnpm test pisellQuickFilter
```

### 查看测试覆盖率

```bash
pnpm test:coverage
```

## 持续集成

测试会在以下情况自动运行：

- ✅ 提交代码时（pre-commit hook）
- ✅ 推送到远程仓库时（CI/CD pipeline）
- ✅ 创建 Pull Request 时

## 测试最佳实践

1. **隔离测试**: 每个测试用例应该独立，不依赖其他测试
2. **清晰命名**: 测试名称应该清楚描述测试内容
3. **测试真实场景**: 模拟用户实际使用场景
4. **避免测试实现细节**: 关注组件行为而非内部实现
5. **保持测试简单**: 一个测试只测试一个功能点

## 问题排查

### 测试失败常见原因

1. **DOM 未找到**: 检查选择器是否正确
2. **异步问题**: 使用 `waitFor` 等待异步操作完成
3. **Mock 不正确**: 确保 mock 数据符合实际情况
4. **环境问题**: 检查测试环境配置

### 调试技巧

```
import { render, screen } from '@testing-library/react';

test('debug test', () => {
  const { debug } = render(<PisellQuickFilter {...props} />);

  // 输出整个 DOM 树
  debug();

  // 输出特定元素
  screen.debug(screen.getByRole('form'));
});
```

## 未来改进

- [ ] 添加视觉回归测试
- [ ] 添加性能测试
- [ ] 添加可访问性测试
- [ ] 增加端到端测试
