/** * OmniCard AI - 名片大厅人脉驱动层测试 */ import * as fs from 'fs'; import * as path from 'path'; const HALL_PAGE = path.resolve( __dirname, '../../../mpuniapp/pages/owner/hall/index.uvue' ); const HALL_UTS = path.resolve( __dirname, '../../../mpuniapp/pages/owner/hall/useHall.uts' ); describe('OmniCard AI 名片大厅 (useHall.uts)', () => { function loadHall() { jest.resetModules(); const storage = new Map(); (global as { uni?: Record }).uni = { getLocale: () => 'zh-CN', navigateTo: jest.fn(), setStorageSync: (key: string, val: string) => storage.set(key, val), getStorageSync: (key: string) => storage.get(key) || '', removeStorageSync: (key: string) => storage.delete(key), }; // eslint-disable-next-line @typescript-eslint/no-require-imports return require('../../../mpuniapp/pages/owner/hall/useHall.uts'); } it('toHallItem 映射对方名片摘要', () => { const { toHallItem } = loadHall(); const item = toHallItem({ id: 9, ownerUserId: 11, peerCardId: 202, source: 'exchange', peerName: 'Tariq Mansour', peerCompany: 'Dubai Energy', peerSlug: 'tariq', }); expect(item.peerCardId).toBe(202); expect(item.peerName).toBe('Tariq Mansour'); expect(item.peerSlug).toBe('tariq'); }); it('未登录带走名片会写入待收藏,登录后可消费', () => { const { setPendingCollectCard, consumePendingCollectCard } = loadHall(); setPendingCollectCard(202); expect(consumePendingCollectCard()).toBe('202'); expect(consumePendingCollectCard()).toBe(''); }); it('buildHallPortalUrl 优先使用 slug', () => { const { buildHallPortalUrl } = loadHall(); expect( buildHallPortalUrl({ peerCardId: 202, peerName: 'Tariq', peerSlug: 'tariq', }) ).toBe('/pages/portal/index?slug=tariq'); expect( buildHallPortalUrl({ peerCardId: 202, peerName: 'Tariq', }) ).toBe('/pages/portal/index?id=202'); }); it('现场分段走 floorPage,加入活动码后刷新同场名片', async () => { const { createHallState, applyHallTab, refreshHall, submitHallEventJoin } = loadHall(); const state = createHallState(); applyHallTab(state, 'event'); let usedFloor = false; let joined = ''; await refreshHall(state, { fetchHallContactPage: async () => ({ list: [], pagination: { page: 1, size: 20, total: 0 }, }), fetchEventFloorPage: async () => { usedFloor = true; return { list: [ { ownerUserId: 11, peerCardId: 103, source: 'event', peerName: 'Chen Wei', }, ], pagination: { page: 1, size: 20, total: 1 }, }; }, }); expect(usedFloor).toBe(true); expect(state.list[0].peerName).toBe('Chen Wei'); state.eventCode = 'ces26a'; const ok = await submitHallEventJoin(state, { fetchHallContactPage: async () => ({ list: [], pagination: { page: 1, size: 20, total: 0 }, }), fetchEventFloorPage: async () => ({ list: [], pagination: { page: 1, size: 20, total: 0 }, }), joinHallEvent: async (code: string) => { joined = code; return { event: { code }, member: { cardId: 101 } }; }, }); expect(ok).toBe(true); expect(joined).toBe('ces26a'); expect(state.eventCode).toBe(''); }); it('团队分段走 teamWall 接口', async () => { const { createHallState, applyHallTab, refreshHall } = loadHall(); const state = createHallState(); applyHallTab(state, 'team'); let usedTeam = false; await refreshHall(state, { fetchHallContactPage: async () => ({ list: [], pagination: { page: 1, size: 20, total: 0 }, }), fetchTeamWallPage: async () => { usedTeam = true; return { list: [ { ownerUserId: 11, peerCardId: 103, source: 'collect', peerName: 'Chen Wei', }, ], pagination: { page: 1, size: 20, total: 1 }, }; }, }); expect(usedTeam).toBe(true); expect(state.tab).toBe('team'); expect(state.list[0].peerName).toBe('Chen Wei'); }); it('refreshHall 只展示当前用户人脉', async () => { const { createHallState, refreshHall } = loadHall(); const state = createHallState(); await refreshHall(state, { fetchHallContactPage: async () => ({ list: [ { id: 1, ownerUserId: 11, peerCardId: 202, source: 'exchange', peerName: 'Tariq Mansour', }, ], pagination: { page: 1, size: 20, total: 1 }, }), }); expect(state.list).toHaveLength(1); expect(state.empty).toBe(false); expect(state.list[0].peerName).toBe('Tariq Mansour'); }); it('P48: 空列表标记空态,刷新不注入示例联系人', async () => { const { createHallState, refreshHall, resolveHallText } = loadHall(); const state = createHallState(); await refreshHall(state, { fetchHallContactPage: async () => ({ list: [], pagination: { page: 1, size: 20, total: 0 }, }), }); expect(state.empty).toBe(true); expect(state.list).toHaveLength(0); expect(state.errorMessage).toBe(''); expect(state.list.some((row: { peerName?: string }) => row.peerName === 'Tariq Mansour')).toBe( false ); expect(resolveHallText('empty')).toBeTruthy(); expect(resolveHallText('refresh')).toBeTruthy(); await refreshHall(state, { fetchHallContactPage: async () => ({ list: [], pagination: { page: 1, size: 20, total: 0 }, }), }); expect(state.empty).toBe(true); expect(state.list).toEqual([]); }); }); describe('OmniCard AI 名片大厅页契约 (index.uvue)', () => { it('页面含 list-view 与互换码输入,并避让 TabBar', () => { const pageSource = fs.readFileSync(HALL_PAGE, 'utf8'); const logicSource = fs.readFileSync(HALL_UTS, 'utf8'); expect(pageSource.includes(' { const pageSource = fs.readFileSync(HALL_PAGE, 'utf8'); const logicSource = fs.readFileSync(HALL_UTS, 'utf8'); const template = pageSource.split('')[0] : ''; const emptyBlockMatch = template.match( /v-else-if="state\.empty"[\s\S]*?(?=)/ ); const emptyBlock = emptyBlockMatch != null ? emptyBlockMatch[0] : ''; expect(emptyBlock.length).toBeGreaterThan(0); expect(emptyBlock.includes("t('empty')") || emptyBlock.includes('t("empty")')).toBe( true ); expect(emptyBlock.includes('emptyDesc')).toBe(true); expect(emptyBlock.includes('primary-cta-btn')).toBe(false); expect(emptyBlock.includes('