| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- 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 { OrderManagement } from '../../src/components/OrderManagement';
- import { adminOrderClient } from '../../src/api/orderClient';
- // 完整的mock响应对象
- const createMockResponse = (status: number, data?: any) => ({
- status,
- ok: status >= 200 && status < 300,
- body: null,
- bodyUsed: false,
- statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
- headers: new Headers(),
- url: '',
- redirected: false,
- type: 'basic' as ResponseType,
- json: async () => data || {},
- text: async () => '',
- blob: async () => new Blob(),
- arrayBuffer: async () => new ArrayBuffer(0),
- formData: async () => new FormData(),
- clone: function() { return this; }
- });
- // Mock API client
- vi.mock('../../src/api/orderClient', () => {
- const mockAdminOrderClient = {
- $get: vi.fn(() => Promise.resolve({ status: 200, body: null })),
- ':id': {
- $put: vi.fn(() => Promise.resolve({ status: 200, body: null })),
- },
- };
- const mockOrderClientManager = {
- getAdminOrderClient: vi.fn(() => mockAdminOrderClient),
- };
- return {
- orderClientManager: mockOrderClientManager,
- adminOrderClient: mockAdminOrderClient,
- };
- });
- // Mock toast
- vi.mock('sonner', () => ({
- toast: {
- success: vi.fn(() => {}),
- error: vi.fn(() => {}),
- },
- }));
- const createTestQueryClient = () =>
- new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
- });
- const renderWithProviders = (component: React.ReactElement) => {
- const queryClient = createTestQueryClient();
- return render(
- <QueryClientProvider client={queryClient}>
- {component as any}
- </QueryClientProvider>
- );
- };
- describe('订单管理集成测试', () => {
- beforeEach(() => {
- vi.clearAllMocks();
- });
- it('应该加载订单列表并显示数据', async () => {
- const mockOrders = {
- data: [
- {
- id: 1,
- orderNo: 'ORDER001',
- user: { username: 'testuser' },
- userPhone: '13800138000',
- recevierName: '张三',
- receiverMobile: '13800138001',
- amount: 100.00,
- payAmount: 100.00,
- freightAmount: 0.00,
- state: 0,
- payState: 2,
- orderType: 1,
- payType: 1,
- address: '北京市朝阳区',
- remark: '测试订单',
- createdAt: '2024-01-01T00:00:00Z',
- },
- ],
- pagination: {
- total: 1,
- page: 1,
- pageSize: 10,
- },
- };
- // Mock initial order list
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- renderWithProviders(<OrderManagement />);
- // Wait for initial data to load
- await waitFor(() => {
- expect(screen.getByText('ORDER001')).toBeInTheDocument();
- expect(screen.getByText('testuser')).toBeInTheDocument();
- expect(screen.getByText('张三')).toBeInTheDocument();
- // Use getAllByText for amount since there are multiple elements with the same text
- const amountElements = screen.getAllByText('¥100.00');
- expect(amountElements.length).toBeGreaterThan(0);
- });
- // Verify API was called with correct parameters
- expect(adminOrderClient.$get).toHaveBeenCalledWith({
- query: {
- page: 1,
- pageSize: 10,
- keyword: '',
- filters: undefined,
- },
- });
- });
- it('应该处理订单搜索功能', async () => {
- const mockOrders = {
- data: [],
- pagination: { total: 0, page: 1, pageSize: 10 },
- };
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- renderWithProviders(<OrderManagement />);
- // Wait for search elements to be available (search area is always available even during loading)
- await waitFor(() => {
- expect(screen.getByTestId('order-search-input')).toBeInTheDocument();
- expect(screen.getByTestId('order-search-button')).toBeInTheDocument();
- });
- // Test search
- const searchInput = screen.getByTestId('order-search-input');
- fireEvent.change(searchInput, { target: { value: 'ORDER001' } });
- const searchButton = screen.getByTestId('order-search-button');
- fireEvent.click(searchButton);
- await waitFor(() => {
- expect(adminOrderClient.$get).toHaveBeenCalledWith({
- query: {
- page: 1,
- pageSize: 10,
- keyword: 'ORDER001',
- filters: undefined,
- },
- });
- });
- });
- it('应该处理订单状态过滤', async () => {
- const mockOrders = {
- data: [],
- pagination: { total: 0, page: 1, pageSize: 10 },
- };
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- renderWithProviders(<OrderManagement />);
- // Wait for component to load
- await waitFor(() => {
- expect(screen.getByTestId('order-status-select')).toBeInTheDocument();
- });
- // Test status filter
- const statusSelect = screen.getByTestId('order-status-select');
- fireEvent.click(statusSelect);
- const statusOption = screen.getByText('已发货');
- fireEvent.click(statusOption);
- await waitFor(() => {
- expect(adminOrderClient.$get).toHaveBeenCalledWith({
- query: {
- page: 1,
- pageSize: 10,
- keyword: '',
- filters: expect.stringContaining('"state":1'),
- },
- });
- });
- });
- it('应该处理支付状态过滤', async () => {
- const mockOrders = {
- data: [],
- pagination: { total: 0, page: 1, pageSize: 10 },
- };
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- renderWithProviders(<OrderManagement />);
- // Wait for component to load
- await waitFor(() => {
- expect(screen.getByTestId('order-pay-status-select')).toBeInTheDocument();
- });
- // Test pay status filter
- const payStatusSelect = screen.getByTestId('order-pay-status-select');
- fireEvent.click(payStatusSelect);
- const payStatusOption = screen.getByText('支付成功');
- fireEvent.click(payStatusOption);
- await waitFor(() => {
- expect(adminOrderClient.$get).toHaveBeenCalledWith({
- query: {
- page: 1,
- pageSize: 10,
- keyword: '',
- filters: expect.stringContaining('"payState":2'),
- },
- });
- });
- });
- it('应该处理订单编辑功能', async () => {
- const { toast } = await import('sonner');
- const mockOrders = {
- data: [
- {
- id: 1,
- orderNo: 'ORDER001',
- state: 0,
- payState: 2,
- remark: '原始备注',
- user: { username: 'testuser' },
- userPhone: '13800138000',
- recevierName: '张三',
- receiverMobile: '13800138001',
- amount: 100.00,
- payAmount: 100.00,
- freightAmount: 0.00,
- orderType: 1,
- payType: 1,
- address: '北京市朝阳区',
- createdAt: '2024-01-01T00:00:00Z',
- },
- ],
- pagination: {
- total: 1,
- page: 1,
- pageSize: 10,
- },
- };
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- renderWithProviders(<OrderManagement />);
- // Wait for data to load
- await waitFor(() => {
- expect(screen.getByText('ORDER001')).toBeInTheDocument();
- });
- // Click edit button using test ID
- const editButtons = screen.getAllByTestId('order-edit-button');
- fireEvent.click(editButtons[0]);
- // Wait for edit modal to open and form elements to be available
- await waitFor(() => {
- expect(screen.getByText('编辑订单')).toBeInTheDocument();
- expect(screen.getByTestId('edit-order-status-select')).toBeInTheDocument();
- expect(screen.getByTestId('edit-remark-textarea')).toBeInTheDocument();
- }, { timeout: 5000 });
- // Change order status
- const statusSelect = screen.getByTestId('edit-order-status-select');
- fireEvent.click(statusSelect);
- // Use getAllByText and select the first option
- const newStatusOptions = screen.getAllByText('已发货');
- fireEvent.click(newStatusOptions[0]);
- // Change remark
- const remarkTextarea = screen.getByTestId('edit-remark-textarea');
- fireEvent.change(remarkTextarea, { target: { value: '更新后的备注' } });
- // Mock successful update
- (adminOrderClient[':id']['$put'] as any).mockResolvedValue(createMockResponse(200));
- // Submit form using test ID
- const saveButton = screen.getByTestId('order-save-button');
- fireEvent.click(saveButton);
- await waitFor(() => {
- expect(adminOrderClient[':id']['$put']).toHaveBeenCalledWith({
- param: { id: '1' },
- json: {
- state: 0,
- payState: 2,
- remark: '更新后的备注',
- },
- });
- expect(toast.success).toHaveBeenCalledWith('订单更新成功');
- });
- });
- it('应该处理订单详情查看', async () => {
- const mockOrders = {
- data: [
- {
- id: 1,
- orderNo: 'ORDER001',
- state: 0,
- payState: 2,
- remark: '测试订单',
- user: { username: 'testuser' },
- userPhone: '13800138000',
- recevierName: '张三',
- receiverMobile: '13800138001',
- amount: 100.00,
- payAmount: 100.00,
- freightAmount: 0.00,
- orderType: 1,
- payType: 1,
- address: '北京市朝阳区',
- createdAt: '2024-01-01T00:00:00Z',
- },
- ],
- pagination: {
- total: 1,
- page: 1,
- pageSize: 10,
- },
- };
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- renderWithProviders(<OrderManagement />);
- // Wait for data to load
- await waitFor(() => {
- expect(screen.getByText('ORDER001')).toBeInTheDocument();
- });
- // Click view details button using test ID
- const viewButtons = screen.getAllByTestId('order-view-button');
- fireEvent.click(viewButtons[0]);
- // Wait for detail modal to open
- await waitFor(() => {
- expect(screen.getByText('订单详情')).toBeInTheDocument();
- }, { timeout: 5000 });
- // Check modal content
- expect(screen.getByText('订单详情')).toBeInTheDocument();
- // Use getAllByText for ORDER001 since there are multiple elements with the same text
- const orderNoElements = screen.getAllByText('ORDER001');
- expect(orderNoElements.length).toBeGreaterThan(0);
- // Use getAllByText for 实物订单 since there are multiple elements with the same text
- const orderTypeElements = screen.getAllByText('实物订单');
- expect(orderTypeElements.length).toBeGreaterThan(0);
- // Use getAllByText for amount since there are multiple elements with the same text
- const amountElements = screen.getAllByText('¥100.00');
- expect(amountElements.length).toBeGreaterThan(0);
- expect(screen.getByText('测试订单')).toBeInTheDocument();
- });
- it('应该优雅处理API错误', async () => {
- const { toast } = await import('sonner');
- // Mock API error
- (adminOrderClient.$get as any).mockRejectedValue(new Error('API Error'));
- renderWithProviders(<OrderManagement />);
- // Should handle error without crashing
- await waitFor(() => {
- expect(screen.getByText('订单管理')).toBeInTheDocument();
- });
- // Test edit error scenario
- const mockOrders = {
- data: [
- {
- id: 1,
- orderNo: 'ORDER001',
- state: 0,
- payState: 2,
- remark: '测试订单',
- user: { username: 'testuser' },
- userPhone: '13800138000',
- recevierName: '张三',
- receiverMobile: '13800138001',
- amount: 100.00,
- payAmount: 100.00,
- freightAmount: 0.00,
- orderType: 1,
- payType: 1,
- address: '北京市朝阳区',
- createdAt: '2024-01-01T00:00:00Z',
- },
- ],
- pagination: {
- total: 1,
- page: 1,
- pageSize: 10,
- },
- };
- // Mock successful data load
- (adminOrderClient.$get as any).mockResolvedValue(createMockResponse(200, mockOrders));
- // Re-render with data
- renderWithProviders(<OrderManagement />);
- await waitFor(() => {
- expect(screen.getByText('ORDER001')).toBeInTheDocument();
- });
- // Click edit button using test ID
- const editButtons = screen.getAllByTestId('order-edit-button');
- fireEvent.click(editButtons[0]);
- await waitFor(() => {
- expect(screen.getByText('编辑订单')).toBeInTheDocument();
- });
- // Mock update error
- (adminOrderClient[':id']['$put'] as any).mockRejectedValue(new Error('Update failed'));
- // Submit form using test ID
- const saveButton = screen.getByTestId('order-save-button');
- fireEvent.click(saveButton);
- await waitFor(() => {
- expect(toast.error).toHaveBeenCalledWith('更新失败,请重试');
- });
- });
- });
|