Files
waoowaoo/tests/unit/billing/cost-error-branches.test.ts

66 lines
2.1 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
const lookupMock = vi.hoisted(() => ({
resolveBuiltinPricing: vi.fn(),
}))
vi.mock('@/lib/model-pricing/lookup', () => ({
resolveBuiltinPricing: lookupMock.resolveBuiltinPricing,
}))
import { calcImage, calcText, calcVideo, calcVoice } from '@/lib/billing/cost'
describe('billing/cost error branches', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it('throws ambiguous pricing error when catalog has multiple candidates', () => {
lookupMock.resolveBuiltinPricing.mockReturnValue({
status: 'ambiguous_model',
apiType: 'image',
modelId: 'shared-model',
candidates: [
{
apiType: 'image',
provider: 'p1',
modelId: 'shared-model',
pricing: { mode: 'flat', flatAmount: 1 },
},
{
apiType: 'image',
provider: 'p2',
modelId: 'shared-model',
pricing: { mode: 'flat', flatAmount: 1 },
},
],
})
expect(() => calcImage('shared-model', 1)).toThrow('Ambiguous image pricing modelId')
})
it('throws unknown model when catalog returns not_configured', () => {
lookupMock.resolveBuiltinPricing.mockReturnValue({
status: 'not_configured',
})
expect(() => calcImage('provider::missing-image-model', 1)).toThrow('Unknown image model pricing')
})
it('normalizes invalid numeric inputs to zero before pricing', () => {
lookupMock.resolveBuiltinPricing.mockImplementation(
(input: { selections?: { tokenType?: 'input' | 'output' } }) => {
if (input.selections?.tokenType === 'input') return { status: 'resolved', amount: 2 }
if (input.selections?.tokenType === 'output') return { status: 'resolved', amount: 4 }
return { status: 'resolved', amount: 3 }
},
)
expect(calcText('text-model', Number.NaN, 1_000_000)).toBeCloseTo(4, 8)
expect(calcText('text-model', 1_000_000, Number.NaN)).toBeCloseTo(2, 8)
expect(calcImage('image-model', Number.NaN)).toBe(0)
expect(calcVideo('video-model', '720p', Number.NaN)).toBe(0)
expect(calcVoice(Number.NaN)).toBe(0)
})
})