32 lines
1.8 KiB
TypeScript
32 lines
1.8 KiB
TypeScript
// Source-order contract for realtime-token: provider availability and minting
|
|
// must precede the quota spend, and raw errors must never reach the response.
|
|
const index = await Deno.readTextFile(new URL('./index.ts', import.meta.url))
|
|
const handler = await Deno.readTextFile(new URL('./handler.ts', import.meta.url))
|
|
const provider = await Deno.readTextFile(new URL('./openai-provider.ts', import.meta.url))
|
|
|
|
function assert(condition: boolean, message: string): asserts condition {
|
|
if (!condition) throw new Error(message)
|
|
}
|
|
|
|
Deno.test('index is only a composition root over the tested handler', () => {
|
|
assert(index.includes('createRealtimeTokenHandler('), 'index must wire the tested handler')
|
|
assert(index.includes('Deno.serve(handler)'), 'index must serve the composed handler')
|
|
assert(!index.includes('api.openai.com'), 'provider IO must live in openai-provider.ts')
|
|
})
|
|
|
|
Deno.test('provider checks and minting precede the quota spend', () => {
|
|
const configuredIndex = handler.indexOf('provider.isConfigured()')
|
|
const mintIndex = handler.indexOf('provider.mintClientSecret(', configuredIndex)
|
|
const consumeIndex = handler.indexOf('quota.consume(', mintIndex)
|
|
assert(configuredIndex >= 0, 'provider availability check missing')
|
|
assert(mintIndex > configuredIndex, 'minting must follow the availability check')
|
|
assert(consumeIndex > mintIndex, 'quota must be consumed only after a successful mint')
|
|
})
|
|
|
|
Deno.test('raw provider and exception text are never returned', () => {
|
|
for (const source of [index, handler, provider]) {
|
|
assert(!source.includes('JSON.stringify({ error: message })'), 'raw exception message returned')
|
|
assert(!source.includes('errText'), 'provider error body is read into the response path')
|
|
}
|
|
assert(handler.includes("json(500, { error: 'internal_error' })"), 'generic internal error missing')
|
|
})
|