Services.test.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { fireEvent, render, screen, waitFor } from '@testing-library/react';
  2. import { beforeEach, expect, test, vi } from 'vitest';
  3. import ServicesPage from '@/pages/Services';
  4. import { apiRequest } from '@/services/api';
  5. vi.mock('@/services/api', () => ({
  6. apiRequest: vi.fn(),
  7. jsonOptions: vi.fn((method, body) => ({ method, body: JSON.stringify(body) })),
  8. }));
  9. const emptyPage = { items: [], total: 0, page: 1, page_size: 20 };
  10. beforeEach(() => {
  11. vi.mocked(apiRequest).mockImplementation(async (path) => {
  12. if (path === '/directory/fulfillment-metrics') {
  13. return {
  14. counts: {},
  15. valid_requests: 12,
  16. quoted_requests: 9,
  17. confirmed_requests: 6,
  18. request_submission_rate: 1,
  19. quote_rate: 0.75,
  20. customer_confirmation_rate: 0.6667,
  21. match_success_rate: 0.5,
  22. fulfillment_rate: 0.8333,
  23. cancellation_rate: 0.1,
  24. cancellation_distribution: { customer: 1, technician: 0 },
  25. scope_note: '仅统计平台服务单;直接 Telegram 私聊成交不在统计范围。',
  26. };
  27. }
  28. if (path === '/directory/service-settings') {
  29. return {
  30. customer_max_open_orders: 3,
  31. customer_daily_request_limit: 10,
  32. review_qr_expiry_hours: 24,
  33. review_forum_chat_id: '-1001234567890',
  34. review_forum_username: 'public_reviews',
  35. };
  36. }
  37. if (path.startsWith('/directory/package-templates')) {
  38. return {
  39. items: [
  40. {
  41. template_id: 'tpl1',
  42. version: 2,
  43. name: '基础护理模板',
  44. status: 'enabled',
  45. sort_order: 1,
  46. created_at: '2026-07-26T00:00:00Z',
  47. updated_at: '2026-07-26T00:00:00Z',
  48. package: {
  49. package_id: 'pkg1',
  50. name: '基础护理',
  51. category: '护理',
  52. description: '标准服务',
  53. tags: ['护理'],
  54. service_modes: ['at_store'],
  55. price_mode: 'fixed',
  56. currency: 'CNY',
  57. price_unit: 'per_service',
  58. min_price: '100.00',
  59. max_price: '100.00',
  60. price_display: '100 元/次',
  61. duration_minutes: 60,
  62. addons: [],
  63. travel_fee: { mode: 'quoted', description: '无额外费用' },
  64. },
  65. },
  66. ],
  67. total: 1,
  68. };
  69. }
  70. if (path.startsWith('/directory/service-orders')) return emptyPage;
  71. if (path.startsWith('/directory/reviews')) return emptyPage;
  72. if (path.startsWith('/directory/review-qrs')) return emptyPage;
  73. if (path.startsWith('/directory/leaderboard')) return emptyPage;
  74. if (path.startsWith('/directory/customer-blocks')) return emptyPage;
  75. if (path.startsWith('/directory/reports')) return emptyPage;
  76. if (path === '/directory/review-template') {
  77. return {
  78. template_id: 'review1',
  79. version: 1,
  80. status: 'active',
  81. published_at: '2026-07-26T00:00:00Z',
  82. questions: [
  83. {
  84. question_id: 'effect',
  85. type: 'single_choice',
  86. label: '服务效果',
  87. required: true,
  88. weight: 100,
  89. options: [
  90. { value: 'good', label: '满意', score: 5 },
  91. { value: 'bad', label: '不满意', score: 1 },
  92. ],
  93. },
  94. ],
  95. };
  96. }
  97. throw new Error(`Unexpected request: ${path}`);
  98. });
  99. });
  100. test('展示咨询评价说明、公开群设置和服务模板', async () => {
  101. render(<ServicesPage />);
  102. expect(screen.getByText('技师咨询与评价')).toBeInTheDocument();
  103. expect(screen.getByText('咨询平台模式')).toBeInTheDocument();
  104. expect(await screen.findByText('12')).toBeInTheDocument();
  105. await waitFor(() => {
  106. expect(screen.getByLabelText('公开群 Chat ID')).toHaveValue('-1001234567890');
  107. });
  108. expect(screen.getByText('仅统计平台服务单;直接 Telegram 私聊成交不在统计范围。')).toBeInTheDocument();
  109. fireEvent.click(screen.getByRole('tab', { name: /套餐模板/ }));
  110. expect(await screen.findByText('基础护理模板')).toBeInTheDocument();
  111. expect(screen.getByText('护理 · V2')).toBeInTheDocument();
  112. fireEvent.click(screen.getByRole('button', { name: '新建模板' }));
  113. expect(await screen.findByLabelText('默认服务价格')).toBeInTheDocument();
  114. expect(screen.getByLabelText('默认额外费用说明')).toBeInTheDocument();
  115. });