// @vitest-environment node /** * 平台会话代次的语义。 * * 渲染层只持有这一个派生计数,用来识别换号/登出后到达的迟到结果。它必须在 * 「同一账号续期」和「同一身份重复采纳(StrictMode 双次 hydrate)」时保持不变——否则 * 在途生成会被自己的续期判成旧账号请求;而换账号、换 origin、登出又必须立刻推进。 */ import { beforeEach, expect, test, vi } from 'vitest'; const refreshClientAuthSession = vi.hoisted(() => vi.fn()); vi.mock('../src/services/clientAuth', () => ({ refreshClientAuthSession, subscribeClientAuthState: () => () => {}, })); import { beginPlatformSessionTransition, commitAuthenticatedPlatformSession, currentPlatformSessionGeneration, requestPlatformSessionRefresh, resetPlatformSessionForTests, subscribePlatformSessionGeneration, } from '../src/services/platformSession'; const userA = { id: 'user-a', publicUserCode: 'tn-a', displayName: '账号 A', avatarUrl: null, phoneNumber: null, phoneNumberMasked: null, loginMethod: 'password', bindingStatus: 'active', wechatBound: false, wechatDisplayName: null, wechatAccount: null, }; const userB = { ...userA, id: 'user-b', publicUserCode: 'tn-b', displayName: '账号 B', }; beforeEach(() => { refreshClientAuthSession.mockReset(); resetPlatformSessionForTests(); }); test('同一身份重复采纳不推进代次,换 origin 或换账号才推进', async () => { const observed: number[] = []; const unsubscribe = subscribePlatformSessionGeneration((generation) => { observed.push(generation); }); const first = await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); expect(first).toBe(1); // StrictMode 双次 hydrate 或同一账号重新登录:代次必须原地不动。 const again = await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); expect(again).toBe(first); const otherOrigin = await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://b.example.com', ); expect(otherOrigin).toBe(2); const otherUser = await commitAuthenticatedPlatformSession( userB, currentPlatformSessionGeneration(), 'https://b.example.com', ); expect(otherUser).toBe(3); expect(observed).toEqual([1, 2, 3]); unsubscribe(); }); test('期望代次已过期时不采纳身份', async () => { await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); await expect( commitAuthenticatedPlatformSession(userB, 0, 'https://a.example.com'), ).resolves.toBeNull(); expect(currentPlatformSessionGeneration()).toBe(1); }); test('登录切换与登出立刻推进代次', () => { const before = currentPlatformSessionGeneration(); const next = beginPlatformSessionTransition(); expect(next).toBe(before + 1); expect(currentPlatformSessionGeneration()).toBe(next); }); test('同一账号续期不推进代次,并发续期只发一次请求', async () => { await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); const generationBefore = currentPlatformSessionGeneration(); refreshClientAuthSession.mockResolvedValue({ status: 'refreshed', user: userA, }); const [first, second] = await Promise.all([ requestPlatformSessionRefresh(), requestPlatformSessionRefresh(), ]); expect(refreshClientAuthSession).toHaveBeenCalledTimes(1); expect(first).toEqual({ status: 'refreshed', user: userA, generation: generationBefore, }); expect(second).toEqual(first); expect(currentPlatformSessionGeneration()).toBe(generationBefore); }); test('续期发现未登录时采纳空身份并给出权威失败', async () => { await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); const generationBefore = currentPlatformSessionGeneration(); refreshClientAuthSession.mockResolvedValue({ status: 'unauthenticated' }); const result = await requestPlatformSessionRefresh(); expect(result.status).toBe('failed'); if (result.status === 'failed') { expect(result.authoritative).toBe(true); expect(String(result.error)).toContain('登录已失效'); } expect(currentPlatformSessionGeneration()).toBe(generationBefore + 1); }); test('续期期间换号时返回 stale,不覆盖新身份', async () => { await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); refreshClientAuthSession.mockImplementation(async () => { beginPlatformSessionTransition(); return { status: 'refreshed', user: userA }; }); await expect(requestPlatformSessionRefresh()).resolves.toEqual({ status: 'stale', }); }); test('网络类续期失败保持会话且不标记为权威失败', async () => { await commitAuthenticatedPlatformSession( userA, currentPlatformSessionGeneration(), 'https://a.example.com', ); const generationBefore = currentPlatformSessionGeneration(); refreshClientAuthSession.mockRejectedValue(new Error('网络不可达')); const result = await requestPlatformSessionRefresh(); expect(result.status).toBe('failed'); if (result.status === 'failed') { expect(result.authoritative).toBe(false); } expect(currentPlatformSessionGeneration()).toBe(generationBefore); });