d3ro-voice/apps/mobile-rn/__tests__/logout.test.ts
2026-08-29 18:33:45 +09:00

55 lines
1.7 KiB
TypeScript

const mockSignOut = jest.fn()
jest.mock('../src/lib/supabase', () => ({
supabase: {
auth: {
signOut: (...args: unknown[]) => mockSignOut(...args),
},
},
}))
import { signOutWithLocalFallback } from '../src/lib/logout'
describe('offline-safe logout boundary', () => {
beforeEach(() => jest.clearAllMocks())
test('confirms remote revocation and still performs the secure local purge', async () => {
mockSignOut.mockResolvedValue({ error: null })
const purge = jest.fn(async () => undefined)
await expect(signOutWithLocalFallback(purge)).resolves.toEqual({
remoteRevocationConfirmed: true,
})
expect(purge).toHaveBeenCalledTimes(1)
})
test('logs this device out when the revocation endpoint is offline', async () => {
mockSignOut.mockResolvedValue({ error: new Error('offline') })
const purge = jest.fn(async () => undefined)
await expect(signOutWithLocalFallback(purge)).resolves.toEqual({
remoteRevocationConfirmed: false,
})
expect(purge).toHaveBeenCalledTimes(1)
})
test('also purges locally when the auth client throws a transport error', async () => {
mockSignOut.mockRejectedValue(new Error('network down'))
const purge = jest.fn(async () => undefined)
await expect(signOutWithLocalFallback(purge)).resolves.toEqual({
remoteRevocationConfirmed: false,
})
expect(purge).toHaveBeenCalledTimes(1)
})
test('never reports logout success if secure local deletion fails', async () => {
mockSignOut.mockResolvedValue({ error: new Error('offline') })
const purge = jest.fn(async () => {
throw new Error('keychain deletion failed')
})
await expect(signOutWithLocalFallback(purge))
.rejects.toThrow('keychain deletion failed')
})
})