| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import { describe, it, expect, vi, beforeEach } from 'vitest'
- import { render, screen, fireEvent, waitFor } from '@testing-library/react'
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
- import { ChannelSelector } from '../../src/components/ChannelSelector'
- import { channelClient } from '../../src/api/channelClient'
- // Mock the channel client
- vi.mock('../../src/api/channelClient', () => {
- const channelClient = {
- getAllChannels: {
- $get: vi.fn(),
- },
- }
- return {
- channelClient,
- channelClientManager: {
- get: vi.fn(() => channelClient),
- },
- }
- })
- const mockChannels = {
- data: [
- { id: 1, channelName: '微信小程序渠道', channelType: '小程序', contactPerson: '张三', contactPhone: '13800138000', description: '微信小程序渠道', status: 1, createTime: '2024-01-01T00:00:00Z', updateTime: '2024-01-01T00:00:00Z' },
- { id: 2, channelName: '抖音广告渠道', channelType: '广告', contactPerson: '李四', contactPhone: '13900139000', description: '抖音广告渠道', status: 1, createTime: '2024-01-01T00:00:00Z', updateTime: '2024-01-01T00:00:00Z' },
- { id: 3, channelName: '快手直播渠道', channelType: '直播', contactPerson: '王五', contactPhone: '13700137000', description: '快手直播渠道', status: 0, createTime: '2024-01-01T00:00:00Z', updateTime: '2024-01-01T00:00:00Z' },
- ],
- pagination: {
- total: 3,
- page: 1,
- pageSize: 10,
- totalPages: 1,
- },
- }
- const TestWrapper = ({ children }: { children: React.ReactNode }) => {
- const queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- })
- return (
- <QueryClientProvider client={queryClient}>
- {children as any}
- </QueryClientProvider>
- )
- }
- describe('ChannelSelector 集成测试', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
- it('应该正确渲染渠道选择器', async () => {
- (channelClient.getAllChannels.$get as any).mockResolvedValue({
- status: 200,
- json: async () => mockChannels,
- })
- render(
- <TestWrapper>
- <ChannelSelector testId="channel-selector" />
- </TestWrapper>
- )
- // 验证加载状态
- expect(screen.getByTestId('channel-selector')).toBeInTheDocument()
- expect(screen.getByText('加载中...')).toBeInTheDocument()
- // 等待数据加载完成
- await waitFor(() => {
- expect(screen.getByText('请选择渠道')).toBeInTheDocument()
- })
- // 点击选择器打开下拉菜单
- const selectTrigger = screen.getByTestId('channel-selector')
- fireEvent.click(selectTrigger)
- // 验证下拉菜单中的选项
- await waitFor(() => {
- expect(screen.getByText('微信小程序渠道')).toBeInTheDocument()
- expect(screen.getByText('抖音广告渠道')).toBeInTheDocument()
- expect(screen.getByText('快手直播渠道')).toBeInTheDocument()
- })
- })
- it('应该处理加载状态', () => {
- // Mock 延迟响应
- (channelClient.getAllChannels.$get as any).mockImplementation(
- () => new Promise(() => {}) // 永不解析的Promise
- )
- render(
- <TestWrapper>
- <ChannelSelector testId="channel-selector" />
- </TestWrapper>
- )
- // 验证加载状态
- expect(screen.getByTestId('channel-selector')).toBeInTheDocument()
- expect(screen.getByText('加载中...')).toBeInTheDocument()
- })
- it('应该处理错误状态', async () => {
- (channelClient.getAllChannels.$get as any).mockRejectedValue(new Error('API错误'))
- render(
- <TestWrapper>
- <ChannelSelector testId="channel-selector" />
- </TestWrapper>
- )
- // 等待错误状态
- await waitFor(() => {
- expect(screen.getByText('加载渠道列表失败')).toBeInTheDocument()
- })
- })
- it('应该处理选择器值变化', async () => {
- (channelClient.getAllChannels.$get as any).mockResolvedValue({
- status: 200,
- json: async () => mockChannels,
- })
- const mockOnChange = vi.fn()
- render(
- <TestWrapper>
- <ChannelSelector onChange={mockOnChange} testId="channel-selector" />
- </TestWrapper>
- )
- // 等待数据加载完成
- await waitFor(() => {
- expect(screen.getByTestId('channel-selector')).toBeEnabled()
- })
- // 点击选择器打开下拉菜单
- const selectTrigger = screen.getByTestId('channel-selector')
- fireEvent.click(selectTrigger)
- // 选择第一个选项
- await waitFor(() => {
- const firstOption = screen.getByText('微信小程序渠道')
- fireEvent.click(firstOption)
- })
- // 验证onChange被调用
- expect(mockOnChange).toHaveBeenCalledWith(1)
- })
- it('应该支持自定义占位符', async () => {
- (channelClient.getAllChannels.$get as any).mockResolvedValue({
- status: 200,
- json: async () => mockChannels,
- })
- render(
- <TestWrapper>
- <ChannelSelector placeholder="选择渠道" testId="channel-selector" />
- </TestWrapper>
- )
- // 等待数据加载完成
- await waitFor(() => {
- expect(screen.getByText('选择渠道')).toBeInTheDocument()
- })
- })
- it('应该支持禁用状态', async () => {
- (channelClient.getAllChannels.$get as any).mockResolvedValue({
- status: 200,
- json: async () => mockChannels,
- })
- render(
- <TestWrapper>
- <ChannelSelector disabled={true} testId="channel-selector" />
- </TestWrapper>
- )
- // 等待数据加载完成
- await waitFor(() => {
- const selectTrigger = screen.getByTestId('channel-selector')
- expect(selectTrigger).toBeDisabled()
- })
- })
- it('应该支持预选值', async () => {
- (channelClient.getAllChannels.$get as any).mockResolvedValue({
- status: 200,
- json: async () => mockChannels,
- })
- render(
- <TestWrapper>
- <ChannelSelector value={2} testId="channel-selector" />
- </TestWrapper>
- )
- // 等待数据加载完成
- await waitFor(() => {
- expect(screen.getByTestId('channel-selector')).toBeEnabled()
- })
- // 验证预选值已正确设置
- // 在Radix UI Select中,预选值会显示在选择器触发器中
- const selectTrigger = screen.getByTestId('channel-selector')
- expect(selectTrigger).toHaveTextContent('抖音广告渠道')
- })
- })
|