import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { beforeEach, expect, test, vi } from 'vitest'; import TechnicianMiniApp from '@/pages/TechnicianMiniApp'; import { technicianApiRequest, technicianJsonOptions, } from '@/services/technicianApi'; vi.mock('@/services/technicianApi', () => ({ initializeTelegramMiniApp: vi.fn(), TechnicianApiError: class TechnicianApiError extends Error { code = ''; status = 400; }, technicianApiRequest: vi.fn(), technicianJsonOptions: vi.fn((method, body) => ({ method, body: JSON.stringify(body), })), })); const packageTemplate = { package_id: 'template-package', name: '标准到店服务', category: '通用服务', description: '一次标准到店服务', tags: ['到店'], service_modes: ['at_store'] as const, price_mode: 'fixed' as const, currency: 'CNY', price_unit: 'per_service' as const, min_price: '200.00', max_price: '200.00', duration_minutes: 60, included_items: '基础服务', excluded_items: '', preparation: '', addons: [], travel_fee: { mode: 'included' as const, amount: '0', per_km: '0', description: '无额外费用', }, service_radius_km: null, out_of_range_policy: '', source_type: 'template' as const, }; const bootstrap = { technician: { user_id: '700', display_name: '测试技师', username: 'technician700', eligibility: { ready: true, issues: [] }, service_profile: null, }, templates: [ { template_id: 'builtin_quick_at_store', version: 1, name: '快速到店服务', builtin: true, package: packageTemplate, }, ], limits: { max_packages: 5 }, }; beforeEach(() => { vi.mocked(technicianApiRequest).mockImplementation(async (path) => { if (path === '/bootstrap') return bootstrap; if (path === '/profile') { return { ...bootstrap.technician, service_profile: { headline: '标准到店服务', bio: '一次标准到店服务', tags: ['到店'], contact_hours: '请通过 Telegram 私聊确认服务时间', service_modes: ['at_store'], accepting_requests: true, public_area_text: '测试城区及附近', venue: { name: '工作地点', address_hint: '测试路 100 号' }, onsite_policy: { description: '' }, packages: [packageTemplate], is_complete: true, }, }; } throw new Error(`Unexpected request: ${path}`); }); }); test('模板创建只要求技师确认五项信息并可直接发布', async () => { render(); expect(await screen.findByText('你好,测试技师')).toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: /快速到店服务/ })); expect(await screen.findByText('发布服务')).toBeInTheDocument(); expect(screen.getByLabelText('服务价格')).toHaveValue('CNY 200.00/次'); expect(screen.getByLabelText('服务内容')).toHaveValue('一次标准到店服务'); expect(screen.getByLabelText('额外费用说明')).toHaveValue('无额外费用'); expect(screen.queryByText('per_service')).not.toBeInTheDocument(); fireEvent.change(screen.getByLabelText('大概服务区域'), { target: { value: '测试城区及附近' }, }); fireEvent.click(screen.getByRole('button', { name: /直接发布/ })); await waitFor(() => { expect(technicianApiRequest).toHaveBeenCalledWith( '/profile', expect.objectContaining({ method: 'PUT' }), ); }); expect(technicianJsonOptions).toHaveBeenCalledWith( 'PUT', expect.objectContaining({ service_profile: expect.objectContaining({ public_area_text: '测试城区及附近', }), }), ); });