50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
creditsForUsage,
|
|
findPack,
|
|
parseCreditPriceBook,
|
|
readCreditPriceBook,
|
|
} from '../../src/document-workbench/price-book';
|
|
|
|
const valid = {
|
|
version: '2026-11-01',
|
|
currency: 'SEK',
|
|
packs: [
|
|
{ id: 'starter', credits: 100, amountMinor: 9900 },
|
|
{ id: 'pro', credits: 2000, amountMinor: 129900 },
|
|
],
|
|
metering: { pagesPerCredit: 5, inputTokensPerCredit: 20000, outputTokensPerCredit: 4000 },
|
|
};
|
|
|
|
describe('credit price book', () => {
|
|
it('parses a valid server-owned price book', () => {
|
|
const book = parseCreditPriceBook(valid);
|
|
expect(book.packs).toHaveLength(2);
|
|
expect(findPack(book, 'pro')?.credits).toBe(2000);
|
|
});
|
|
|
|
it('fails closed when the env price book is absent or invalid', () => {
|
|
expect(readCreditPriceBook({} as unknown as NodeJS.ProcessEnv)).toBeUndefined();
|
|
expect(readCreditPriceBook({ OPT_CREDIT_PRICE_BOOK: '{not json' } as unknown as NodeJS.ProcessEnv)).toBeUndefined();
|
|
expect(
|
|
readCreditPriceBook({
|
|
OPT_CREDIT_PRICE_BOOK: JSON.stringify({ ...valid, currency: 'sek' }),
|
|
} as unknown as NodeJS.ProcessEnv),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it('rejects duplicate pack ids, unknown currencies and non-integer money', () => {
|
|
expect(() => parseCreditPriceBook({ ...valid, packs: [valid.packs[0], valid.packs[0]] })).toThrow();
|
|
expect(() =>
|
|
parseCreditPriceBook({ ...valid, packs: [{ id: 'x', credits: 1, amountMinor: 1.5 }] }),
|
|
).toThrow();
|
|
});
|
|
|
|
it('rounds every metered component up to its billing block', () => {
|
|
const book = parseCreditPriceBook(valid);
|
|
expect(creditsForUsage(book, { pages: 0, inputTokens: 0, outputTokens: 0 })).toBe(0);
|
|
expect(creditsForUsage(book, { pages: 1, inputTokens: 1, outputTokens: 1 })).toBe(3);
|
|
expect(creditsForUsage(book, { pages: 6, inputTokens: 40001, outputTokens: 8001 })).toBe(8);
|
|
});
|
|
});
|