| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import { fireEvent, render, screen, waitFor } from '@testing-library/react';
- import { beforeEach, expect, it, vi } from 'vitest';
- import PointsPage from '@/pages/Points';
- import { apiRequest } from '@/services/api';
- vi.mock('@/services/api', () => ({
- apiRequest: vi.fn(),
- downloadFile: vi.fn(),
- jsonOptions: (method: string, body: unknown) => ({ method, body: JSON.stringify(body) }),
- }));
- const rules = {
- enabled: true,
- timezone: 'Asia/Shanghai',
- checkin_enabled: true,
- checkin_button_enabled: true,
- checkin_points: 10,
- activity_enabled: true,
- activity_points: 1,
- activity_cooldown_seconds: 300,
- activity_daily_cap: 10,
- upvote_enabled: true,
- upvote_points: 2,
- upvote_pair_cooldown_seconds: 86400,
- upvote_daily_cap: 10,
- };
- beforeEach(() => {
- vi.clearAllMocks();
- vi.mocked(apiRequest).mockImplementation(async (path) => {
- if (path.startsWith('/chats?')) {
- return {
- items: [
- { chat_id: '-100999', title: '不可用积分群', type: 'supergroup', accessible: false },
- { chat_id: '-100123', title: '积分测试群', type: 'supergroup', accessible: true },
- ],
- total: 2,
- page: 1,
- page_size: 100,
- };
- }
- if (path.startsWith('/points/accounts?')) {
- return {
- items: [{ chat_id: '-100123', user_id: '10001', username: 'alice', display_name: '爱丽丝 示例', balance: 180, lifetime_earned: 220, lifetime_spent: 40 }],
- total: 1,
- page: 1,
- page_size: 20,
- };
- }
- if (path.startsWith('/points/transactions?')) {
- return {
- items: [{ transaction_id: 'tx-1', chat_id: '-100123', user_id: '10001', username: 'alice', display_name: '爱丽丝 示例', delta: 10, balance_after: 180, source: 'checkin', reason: 'Daily check-in', created_at: '2026-07-24T08:00:00Z' }],
- total: 1,
- page: 1,
- page_size: 20,
- };
- }
- if (path.endsWith('/points/settings')) return rules;
- if (path === '/points/adjustments') return { created: true };
- return {};
- });
- });
- it('展示余额排行、流水并保存积分规则', async () => {
- render(<PointsPage />);
- expect(await screen.findByText('爱丽丝 示例')).toBeInTheDocument();
- expect(screen.queryByText('@alice')).not.toBeInTheDocument();
- expect(
- vi.mocked(apiRequest).mock.calls.some(([path]) => path.includes('chat_id=-100999')),
- ).toBe(false);
- fireEvent.click(screen.getByRole('tab', { name: /流水/ }));
- expect(await screen.findByText('Daily check-in')).toBeInTheDocument();
- fireEvent.click(screen.getByRole('tab', { name: '自动积分规则' }));
- expect(await screen.findByRole('heading', { name: '签到' })).toBeInTheDocument();
- expect(screen.getByRole('switch', { name: '底部签到按钮' })).toBeChecked();
- await waitFor(() =>
- expect(apiRequest).toHaveBeenCalledWith('/chats/-100123/points/settings'),
- );
- const saveButton = screen.getByRole('button', { name: /保\s*存\s*规\s*则/ });
- await waitFor(() => expect(saveButton).toBeEnabled());
- fireEvent.click(saveButton);
- expect(
- vi.mocked(apiRequest).mock.calls.some(
- ([path, options]) => path === '/chats/-100123/points/settings' && options?.method === 'PUT',
- ),
- ).toBe(false);
- fireEvent.click(await screen.findByRole('button', { name: /确\s*认\s*保\s*存/ }));
- await waitFor(() => {
- const call = vi.mocked(apiRequest).mock.calls.find(
- ([path, options]) => path === '/chats/-100123/points/settings' && options?.method === 'PUT',
- );
- expect(call).toBeTruthy();
- expect(JSON.parse(String(call?.[1]?.body))).toMatchObject({
- checkin_button_enabled: true,
- confirm: true,
- });
- });
- });
- it('手工调整必须二次确认并携带确认标记', async () => {
- render(<PointsPage />);
- await screen.findByText('爱丽丝 示例');
- fireEvent.click(screen.getByRole('button', { name: /手\s*工\s*调\s*整/ }));
- fireEvent.change(screen.getByLabelText('用户 ID'), { target: { value: '10001' } });
- fireEvent.change(screen.getByLabelText('积分数值'), { target: { value: '25' } });
- fireEvent.change(screen.getByLabelText('原因'), { target: { value: '活动补发' } });
- fireEvent.click(screen.getByRole('button', { name: /继\s*续\s*确\s*认/ }));
- expect(vi.mocked(apiRequest).mock.calls.some(([path]) => path === '/points/adjustments')).toBe(false);
- fireEvent.click(await screen.findByRole('button', { name: /确\s*认\s*写\s*入/ }));
- await waitFor(() => {
- const call = vi.mocked(apiRequest).mock.calls.find(([path]) => path === '/points/adjustments');
- expect(call).toBeTruthy();
- expect(JSON.parse(String(call?.[1]?.body))).toMatchObject({
- chat_id: '-100123',
- user_id: '10001',
- amount: 25,
- reason: '活动补发',
- confirm: true,
- });
- });
- });
|