import { CardEventService, normalizeEventCode } from '../../../src/modules/card/service/event'; describe('P2 展会现场活动码与同场名片墙', () => { let eventService: CardEventService; let eventStore: any[]; let memberStore: any[]; let cardStore: any[]; function createRepo(store: any[], idStart = 1) { let seq = idStart; return { findOne: jest.fn(async (opts: { where?: Record }) => { const where = opts?.where || {}; return ( store.find(row => Object.keys(where).every(key => row[key] === (where as any)[key]) ) || null ); }), find: jest.fn(async (opts?: { where?: Record }) => { const where = opts?.where || {}; return store.filter(row => Object.keys(where).every(key => row[key] === (where as any)[key]) ); }), save: jest.fn(async (item: any) => { if (item.id) { const idx = store.findIndex(row => row.id === item.id); if (idx >= 0) { store[idx] = { ...store[idx], ...item }; return store[idx]; } } const saved = { ...item, id: item.id || seq++ }; store.push(saved); return saved; }), }; } beforeEach(() => { eventStore = []; memberStore = []; cardStore = [ { id: 101, userId: 11, tenantId: 1, name: 'Alex Rivera', title: 'VP', company: 'OmniCard', slug: 'alex', status: 'published', }, { id: 103, userId: 33, tenantId: 1, name: 'Chen Wei', title: 'Sales', company: 'OmniCard', slug: 'chen-wei', status: 'published', }, { id: 202, userId: 22, tenantId: 2, name: 'Tariq Mansour', title: 'Director', company: 'Dubai Energy', slug: 'tariq', status: 'published', }, ]; eventService = new CardEventService(); eventService.cardEventEntity = createRepo(eventStore) as any; eventService.cardEventMemberEntity = createRepo(memberStore, 50) as any; eventService.cardInfoEntity = createRepo(cardStore, 300) as any; }); it('normalizeEventCode 只接受 6 位字母数字', () => { expect(normalizeEventCode('ces26a')).toBe('CES26A'); expect(() => normalizeEventCode('12')).toThrow(/活动码/); expect(() => normalizeEventCode('CES-26')).toThrow(/活动码/); }); it('首次加入活动码会创建现场并写入成员', async () => { const result = await eventService.joinEvent({ userId: 11, code: 'ces26a', }); expect(result.event.code).toBe('CES26A'); expect(result.event.status).toBe('active'); expect(result.member.userId).toBe(11); expect(result.member.cardId).toBe(101); expect(eventStore).toHaveLength(1); expect(memberStore).toHaveLength(1); }); it('同一用户重复加入同一现场只保留一行成员', async () => { await eventService.joinEvent({ userId: 11, code: 'CES26A' }); await eventService.joinEvent({ userId: 11, code: 'ces26a' }); expect(eventStore).toHaveLength(1); expect(memberStore).toHaveLength(1); }); it('现场墙只返回同场他人已发布名片', async () => { await eventService.joinEvent({ userId: 11, code: 'CES26A' }); await eventService.joinEvent({ userId: 33, code: 'CES26A' }); await eventService.joinEvent({ userId: 22, code: 'GITEX1' }); const page = await eventService.pageEventFloor({ userId: 11, page: 1, size: 20, }); expect(page.list).toHaveLength(1); expect(page.list[0].peerCardId).toBe(103); expect(page.list[0].peerName).toBe('Chen Wei'); expect(page.list[0].source).toBe('event'); expect(page.list.find(row => row.peerCardId === 101)).toBeUndefined(); expect(page.list.find(row => row.peerCardId === 202)).toBeUndefined(); }); it('未加入现场时墙为空', async () => { const page = await eventService.pageEventFloor({ userId: 11, page: 1, size: 20, }); expect(page.list).toHaveLength(0); expect(page.pagination.total).toBe(0); }); });