| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- import { describe, it, expect, vi, beforeEach } from 'vitest';
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
- import userEvent from '@testing-library/user-event';
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
- import { AreaSelect } from '../../src/components/AreaSelect';
- // Mock API 调用
- vi.mock('../../src/api/areaClient', () => ({
- areaClientManager: {
- get: vi.fn(() => ({
- index: {
- $get: vi.fn(async ({ query }) => {
- const filters = JSON.parse(query.filters);
- if (filters.level === 1) {
- // 省份数据
- return {
- status: 200,
- json: async () => ({
- data: [
- { id: 1, name: '北京市', level: 1, parentId: null },
- { id: 2, name: '上海市', level: 1, parentId: null }
- ]
- })
- };
- } else if (filters.level === 2 && filters.parentId === 1) {
- // 北京市的城市数据
- return {
- status: 200,
- json: async () => ({
- data: [
- { id: 3, name: '北京市', level: 2, parentId: 1 }
- ]
- })
- };
- } else if (filters.level === 2 && filters.parentId === 2) {
- // 上海市的城市数据
- return {
- status: 200,
- json: async () => ({
- data: [
- { id: 4, name: '上海市', level: 2, parentId: 2 }
- ]
- })
- };
- } else if (filters.level === 3 && filters.parentId === 3) {
- // 北京市的区县数据
- return {
- status: 200,
- json: async () => ({
- data: [
- { id: 5, name: '东城区', level: 3, parentId: 3 },
- { id: 6, name: '西城区', level: 3, parentId: 3 }
- ]
- })
- };
- } else if (filters.level === 3 && filters.parentId === 4) {
- // 上海市的区县数据
- return {
- status: 200,
- json: async () => ({
- data: [
- { id: 7, name: '黄浦区', level: 3, parentId: 4 },
- { id: 8, name: '徐汇区', level: 3, parentId: 4 }
- ]
- })
- };
- }
- return {
- status: 200,
- json: async () => ({ data: [] })
- };
- })
- }
- }))
- }
- }));
- // 创建测试用的 QueryClient
- const createTestQueryClient = () => new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- });
- // 测试组件包装器
- const TestWrapper = ({ children }: { children: React.ReactNode }) => {
- return (
- <QueryClientProvider client={createTestQueryClient()}>
- {children}
- </QueryClientProvider>
- );
- };
- describe('AreaSelect 集成测试', () => {
- beforeEach(() => {
- vi.clearAllMocks();
- });
- it('应该正确渲染 AreaSelect 组件', async () => {
- render(
- <TestWrapper>
- <AreaSelect />
- </TestWrapper>
- );
- // 等待省份数据加载 - AreaSelect 显示的是"选择所在省份"
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- expect(screen.getByText('省份')).toBeInTheDocument();
- expect(screen.getByText('城市')).toBeInTheDocument();
- expect(screen.getByText('区县')).toBeInTheDocument();
- });
- it('应该显示必填标记当 required=true 时', async () => {
- render(
- <TestWrapper>
- <AreaSelect required={true} />
- </TestWrapper>
- );
- // 等待省份数据加载 - AreaSelect 显示的是"选择所在省份"
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 检查省份标签是否包含星号
- const provinceLabel = screen.getByText('省份');
- expect(provinceLabel.innerHTML).toContain('*');
- // 城市和区县不应该显示星号(初始状态)
- const cityLabel = screen.getByText('城市');
- expect(cityLabel.innerHTML).not.toContain('*');
- const districtLabel = screen.getByText('区县');
- expect(districtLabel.innerHTML).not.toContain('*');
- });
- it('应该正确处理省份选择并加载城市数据', async () => {
- const user = userEvent.setup();
- const handleChange = vi.fn();
- render(
- <TestWrapper>
- <AreaSelect onChange={handleChange} />
- </TestWrapper>
- );
- // 等待省份数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 使用test ID查找省份选择框
- const provinceSelect = screen.getByTestId('area-select-province');
- await user.click(provinceSelect);
- // 等待下拉菜单出现并选择北京市
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 验证onChange被调用
- expect(handleChange).toHaveBeenCalledWith({
- provinceId: 1,
- cityId: undefined,
- districtId: undefined
- });
- // 验证城市选择框应该被启用(因为选择了省份)
- const citySelect = screen.getByTestId('area-select-city');
- expect(citySelect).toBeInTheDocument();
- });
- it('应该正确处理城市选择并加载区县数据', async () => {
- const user = userEvent.setup();
- const handleChange = vi.fn();
- render(
- <TestWrapper>
- <AreaSelect onChange={handleChange} />
- </TestWrapper>
- );
- // 等待省份数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 先选择省份(北京市)
- const provinceSelect = screen.getByTestId('area-select-province');
- await user.click(provinceSelect);
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 等待城市数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在城市')).toBeInTheDocument();
- });
- // 点击城市选择框
- const citySelect = screen.getByTestId('area-select-city');
- await user.click(citySelect);
- // 选择北京市(城市)
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 验证onChange被调用
- expect(handleChange).toHaveBeenCalledWith({
- provinceId: 1,
- cityId: 3,
- districtId: undefined
- });
- // 验证区县选择框应该被启用(因为选择了城市)
- const districtSelect = screen.getByTestId('area-select-district');
- expect(districtSelect).toBeInTheDocument();
- });
- it('应该正确处理区县选择', async () => {
- const user = userEvent.setup();
- const handleChange = vi.fn();
- render(
- <TestWrapper>
- <AreaSelect onChange={handleChange} />
- </TestWrapper>
- );
- // 等待省份数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 先选择省份(北京市)
- const provinceSelect = screen.getByTestId('area-select-province');
- await user.click(provinceSelect);
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 等待城市数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在城市')).toBeInTheDocument();
- });
- // 选择城市(北京市)
- const citySelect = screen.getByTestId('area-select-city');
- await user.click(citySelect);
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 等待区县数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在区县')).toBeInTheDocument();
- });
- // 点击区县选择框
- const districtSelect = screen.getByTestId('area-select-district');
- await user.click(districtSelect);
- // 选择东城区
- await waitFor(() => {
- expect(screen.getByText('东城区')).toBeInTheDocument();
- });
- await user.click(screen.getByText('东城区'));
- // 验证onChange被调用
- expect(handleChange).toHaveBeenCalledWith({
- provinceId: 1,
- cityId: 3,
- districtId: 5
- });
- });
- it('应该支持禁用状态', async () => {
- render(
- <TestWrapper>
- <AreaSelect disabled={true} />
- </TestWrapper>
- );
- // 等待省份数据加载 - AreaSelect 显示的是"选择所在省份"
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 检查组件渲染正常
- expect(screen.getByText('省份')).toBeInTheDocument();
- expect(screen.getByText('城市')).toBeInTheDocument();
- expect(screen.getByText('区县')).toBeInTheDocument();
- });
- it('应该正确处理初始值', async () => {
- const initialValue = {
- provinceId: 1,
- cityId: 3,
- districtId: 5
- };
- render(
- <TestWrapper>
- <AreaSelect value={initialValue} />
- </TestWrapper>
- );
- // 等待省份数据加载 - AreaSelect 显示的是"选择所在省份"
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 组件应该能正常渲染,初始值会在组件内部处理
- expect(screen.getByText('省份')).toBeInTheDocument();
- expect(screen.getByText('城市')).toBeInTheDocument();
- expect(screen.getByText('区县')).toBeInTheDocument();
- });
- it('当选择新省份时应该清空城市和区县选择', async () => {
- const user = userEvent.setup();
- const handleChange = vi.fn();
- render(
- <TestWrapper>
- <AreaSelect onChange={handleChange} />
- </TestWrapper>
- );
- // 等待省份数据加载
- await waitFor(() => {
- expect(screen.getByText('选择所在省份')).toBeInTheDocument();
- });
- // 先选择省份(北京市)
- const provinceSelect = screen.getByTestId('area-select-province');
- await user.click(provinceSelect);
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 等待城市数据加载并选择城市
- await waitFor(() => {
- expect(screen.getByText('选择所在城市')).toBeInTheDocument();
- });
- const citySelect = screen.getByTestId('area-select-city');
- await user.click(citySelect);
- await waitFor(() => {
- expect(screen.getByText('北京市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('北京市'));
- // 等待区县数据加载并选择区县
- await waitFor(() => {
- expect(screen.getByText('选择所在区县')).toBeInTheDocument();
- });
- const districtSelect = screen.getByTestId('area-select-district');
- await user.click(districtSelect);
- await waitFor(() => {
- expect(screen.getByText('东城区')).toBeInTheDocument();
- });
- await user.click(screen.getByText('东城区'));
- // 验证已经选择了完整的省市区
- expect(handleChange).toHaveBeenLastCalledWith({
- provinceId: 1,
- cityId: 3,
- districtId: 5
- });
- // 现在选择新的省份(上海市)
- await user.click(screen.getByTestId('area-select-province')); // 重新打开省份选择
- await waitFor(() => {
- expect(screen.getByText('上海市')).toBeInTheDocument();
- });
- await user.click(screen.getByText('上海市'));
- // 验证onChange被调用,城市和区县被清空
- expect(handleChange).toHaveBeenLastCalledWith({
- provinceId: 2,
- cityId: undefined,
- districtId: undefined
- });
- // 验证城市选择框应该显示"选择城市"(被清空)
- expect(screen.getByTestId('area-select-city')).toBeInTheDocument();
- // 验证区县选择框应该显示"选择区县"(被清空)
- expect(screen.getByTestId('area-select-district')).toBeInTheDocument();
- });
- });
|