| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import { fireEvent, render, screen, waitFor } from '@testing-library/react';
- import { beforeEach, expect, it, vi } from 'vitest';
- import GiveawaysPage from '@/pages/Giveaways';
- import { apiRequest } from '@/services/api';
- import { mockLocation } from '../umiMock';
- vi.mock('@/services/api', () => ({
- apiRequest: vi.fn(),
- downloadFile: vi.fn(),
- jsonOptions: (method: string, body: unknown) => ({ method, body: JSON.stringify(body) }),
- }));
- beforeEach(() => {
- vi.clearAllMocks();
- mockLocation.search = '';
- 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('/giveaways?')) {
- return {
- items: [{
- giveaway_id: 'draw-1',
- chat_id: '-100123',
- title: '七月抽奖',
- status: 'running',
- prizes: [{ name: '一等奖', count: 1, points_reward: 50 }],
- minimum_points: 20,
- entry_cost: 5,
- participation_reward: 2,
- starts_at: '2026-07-24T00:00:00Z',
- ends_at: '2026-07-25T08:00:00Z',
- created_at: '2026-07-24T08:00:00Z',
- }],
- total: 1,
- page: 1,
- page_size: 20,
- };
- }
- if (path.includes('/participants?')) {
- return {
- items: [{ giveaway_id: 'draw-1', chat_id: '-100123', user_id: '10001', username: 'alice', display_name: '爱丽丝 示例', active: true, entry_cost: 5, joined_at: '2026-07-24T08:00:00Z' }],
- total: 1,
- page: 1,
- page_size: 100,
- };
- }
- if (path.endsWith('/finish')) return { status: 'finished' };
- return {};
- });
- });
- it('参与者优先显示 Telegram 昵称', async () => {
- render(<GiveawaysPage />);
- await screen.findByText('七月抽奖');
- fireEvent.click(screen.getByRole('button', { name: '参与者' }));
- expect(await screen.findByText('爱丽丝 示例')).toBeInTheDocument();
- expect(screen.queryByText('@alice')).not.toBeInTheDocument();
- });
- it('展示抽奖积分配置并在危险操作确认后开奖', async () => {
- render(<GiveawaysPage />);
- expect(await screen.findByText('七月抽奖')).toBeInTheDocument();
- expect(screen.getByText('门槛 20')).toBeInTheDocument();
- expect(screen.getByText('消耗 5')).toBeInTheDocument();
- expect(screen.getByText('参与 +2')).toBeInTheDocument();
- fireEvent.click(screen.getByRole('button', { name: /开\s*奖/ }));
- expect(vi.mocked(apiRequest).mock.calls.some(([path]) => path.endsWith('/finish'))).toBe(false);
- fireEvent.click(await screen.findByRole('button', { name: /确\s*认\s*执\s*行/ }));
- await waitFor(() => {
- const call = vi.mocked(apiRequest).mock.calls.find(([path]) => path.endsWith('/finish'));
- expect(call).toBeTruthy();
- expect(JSON.parse(String(call?.[1]?.body))).toEqual({ confirm: true });
- });
- });
- it('创建表单包含积分联动字段且发布前必须二次确认', async () => {
- mockLocation.search = '?chat_id=-100123';
- render(<GiveawaysPage />);
- await screen.findByText('七月抽奖');
- fireEvent.click(screen.getByRole('button', { name: /创\s*建\s*抽\s*奖/ }));
- expect(await screen.findByLabelText('最低积分')).toBeInTheDocument();
- expect(screen.getByLabelText('报名消耗')).toBeInTheDocument();
- expect(screen.getByLabelText('参与奖励')).toBeInTheDocument();
- expect(screen.getByLabelText('报名开始时间')).toBeInTheDocument();
- expect(screen.getByLabelText('开奖时间')).toBeInTheDocument();
- expect(screen.getByPlaceholderText('中奖积分')).toBeInTheDocument();
- fireEvent.change(screen.getByLabelText('标题'), { target: { value: '八月抽奖' } });
- fireEvent.click(screen.getByRole('button', { name: /创\s*建\s*并\s*发\s*布/ }));
- expect(
- vi.mocked(apiRequest).mock.calls.some(
- ([path, options]) => path === '/giveaways' && options?.method === 'POST',
- ),
- ).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 === '/giveaways' && options?.method === 'POST',
- );
- expect(call).toBeTruthy();
- expect(JSON.parse(String(call?.[1]?.body))).toMatchObject({
- chat_id: '-100123',
- title: '八月抽奖',
- minimum_points: 0,
- entry_cost: 0,
- participation_reward: 0,
- starts_at: expect.any(String),
- ends_at: expect.any(String),
- confirm: true,
- });
- expect(JSON.parse(String(call?.[1]?.body))).not.toHaveProperty('duration_minutes');
- });
- });
- it('不可用群不会成为筛选或创建目标', async () => {
- mockLocation.search = '?chat_id=-100999';
- render(<GiveawaysPage />);
- await waitFor(() => {
- const requests = vi.mocked(apiRequest).mock.calls
- .map(([path]) => path)
- .filter((path) => path.startsWith('/giveaways?'));
- expect(requests.length).toBeGreaterThan(0);
- expect(requests.every((path) => !path.includes('chat_id=-100999'))).toBe(true);
- });
- fireEvent.click(screen.getByRole('button', { name: /创\s*建\s*抽\s*奖/ }));
- fireEvent.mouseDown(await screen.findByLabelText('群组'));
- expect(screen.queryByText('不可用抽奖群')).not.toBeInTheDocument();
- expect(screen.getByText('抽奖测试群')).toBeInTheDocument();
- });
- it('选择群组后提供抽奖资格封禁管理', async () => {
- mockLocation.search = '?chat_id=-100123';
- vi.mocked(apiRequest).mockImplementation(async (path) => {
- if (path.startsWith('/chats?')) {
- return {
- items: [{ chat_id: '-100123', title: '抽奖测试群', type: 'supergroup', accessible: true }],
- total: 1,
- page: 1,
- page_size: 100,
- };
- }
- if (path.startsWith('/giveaways?')) return { items: [], total: 0, page: 1, page_size: 20 };
- if (path.includes('/giveaway-bans?')) {
- return {
- items: [{ chat_id: '-100123', user_id: '10009', reason: '恶意刷报名', created_at: '2026-07-24T08:00:00Z' }],
- total: 1,
- page: 1,
- page_size: 20,
- };
- }
- return {};
- });
- render(<GiveawaysPage />);
- fireEvent.click(await screen.findByRole('button', { name: /资\s*格\s*封\s*禁/ }));
- expect(await screen.findByText('恶意刷报名')).toBeInTheDocument();
- expect(screen.getByRole('button', { name: /添\s*加\s*封\s*禁/ })).toBeInTheDocument();
- });
|