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

44 lines
1.9 KiB
TypeScript

import AsyncStorage from '@react-native-async-storage/async-storage'
import {
clearAllGenerationIdempotencyKeys,
clearGenerationIdempotencyKey,
getOrCreateGenerationIdempotencyKey,
} from '../src/features/templates/generation-idempotency'
import { uuidV4FromBytes } from '../src/lib/random-id'
const USER_ID = '11111111-1111-4111-8111-111111111111'
const OTHER_USER_ID = '22222222-2222-4222-8222-222222222222'
const MEETING_ID = '33333333-3333-4333-8333-333333333333'
const TEMPLATE_ID = '44444444-4444-4444-8444-444444444444'
describe('meeting document generation idempotency', () => {
beforeEach(async () => {
await AsyncStorage.clear()
})
it('formats random bytes as an RFC 4122 version 4 UUID', () => {
expect(uuidV4FromBytes(Uint8Array.from({ length: 16 }, (_, index) => index)))
.toBe('00010203-0405-4607-8809-0a0b0c0d0e0f')
})
it('reuses a pending key across retries and clears it only after commit', async () => {
const first = await getOrCreateGenerationIdempotencyKey(USER_ID, MEETING_ID, TEMPLATE_ID)
const retry = await getOrCreateGenerationIdempotencyKey(USER_ID, MEETING_ID, TEMPLATE_ID)
expect(retry).toBe(first)
await clearGenerationIdempotencyKey(USER_ID, MEETING_ID, TEMPLATE_ID)
const nextOperation = await getOrCreateGenerationIdempotencyKey(USER_ID, MEETING_ID, TEMPLATE_ID)
expect(nextOperation).not.toBe(first)
})
it('purges only the requested account pending keys', async () => {
const own = await getOrCreateGenerationIdempotencyKey(USER_ID, MEETING_ID, TEMPLATE_ID)
const other = await getOrCreateGenerationIdempotencyKey(OTHER_USER_ID, MEETING_ID, TEMPLATE_ID)
await clearAllGenerationIdempotencyKeys(USER_ID)
const recreated = await getOrCreateGenerationIdempotencyKey(USER_ID, MEETING_ID, TEMPLATE_ID)
const otherRetry = await getOrCreateGenerationIdempotencyKey(OTHER_USER_ID, MEETING_ID, TEMPLATE_ID)
expect(recreated).not.toBe(own)
expect(otherRetry).toBe(other)
})
})