import { beforeEach, describe, expect, it, vi } from 'vitest' const api = vi.hoisted (() => ({ apiGet: vi.fn (), apiPost: vi.fn () })) vi.mock ('@/lib/api', () => ({ ...api, isApiError: (error: { isAxiosError?: boolean }) => error.isAxiosError === true })) const user = { id: 1, name: 'Cookie user', role: 'guest', inheritanceCode: 'current-code' } const noSession = { isAxiosError: true, response: { status: 401 } } describe ('Cookie session initialisation', () => { beforeEach (() => { vi.resetModules () vi.clearAllMocks () api.apiGet.mockReset () api.apiPost.mockReset () localStorage.clear () }) it ('keeps Cookie identity and updates an older recovery code', async () => { localStorage.setItem ('user_code', 'old-code') api.apiGet.mockResolvedValueOnce (user) const { initialiseUserSession } = await import ('@/lib/users') await expect (initialiseUserSession ()).resolves.toEqual (user) expect (api.apiGet).toHaveBeenCalledWith ('/users/me') expect (api.apiPost).not.toHaveBeenCalled () expect (localStorage.getItem ('user_code')).toBe ('current-code') }) it ('restores from storage only after Cookie authentication returns 401', async () => { localStorage.setItem ('user_code', 'backup-code') api.apiGet.mockRejectedValueOnce (noSession) api.apiPost.mockResolvedValueOnce ({ valid: true, user }) const { initialiseUserSession } = await import ('@/lib/users') await expect (initialiseUserSession ()).resolves.toEqual (user) expect (api.apiPost).toHaveBeenCalledExactlyOnceWith ( '/users/verify', { code: 'backup-code', restore: true }) }) it ('creates an account after a recovery code is rejected', async () => { localStorage.setItem ('user_code', 'expired-code') api.apiGet.mockRejectedValueOnce (noSession) api.apiPost.mockResolvedValueOnce ({ valid: false }) api.apiPost.mockResolvedValueOnce ({ code: user.inheritanceCode, user }) const { initialiseUserSession } = await import ('@/lib/users') await expect (initialiseUserSession ()).resolves.toEqual (user) expect (api.apiPost).toHaveBeenLastCalledWith ('/users') }) it.each ([403, 503]) ('does not replace a session when the API returns %s', async status => { localStorage.setItem ('user_code', 'backup-code') const error = { isAxiosError: true, response: { status } } api.apiGet.mockRejectedValueOnce (error) const { initialiseUserSession } = await import ('@/lib/users') await expect (initialiseUserSession ()).rejects.toBe (error) expect (api.apiPost).not.toHaveBeenCalled () expect (localStorage.getItem ('user_code')).toBe ('backup-code') }) it ('shares concurrent initialisation to avoid duplicate account creation', async () => { api.apiGet.mockRejectedValueOnce (noSession) api.apiPost.mockResolvedValueOnce ({ code: user.inheritanceCode, user }) const { initialiseUserSession } = await import ('@/lib/users') await Promise.all ([initialiseUserSession (), initialiseUserSession ()]) expect (api.apiGet).toHaveBeenCalledTimes (1) expect (api.apiPost).toHaveBeenCalledExactlyOnceWith ('/users') }) })