agent-ecosystem/test/shared/utils/costFormatting.test.ts
2026-02-22 15:44:04 +05:30

228 lines
7.9 KiB
TypeScript

/**
* Tests for cost formatting utilities
*/
import { describe, it, expect } from 'vitest';
import { formatCostUsd, formatCostCompact } from '@shared/utils/costFormatting';
describe('Cost Formatting', () => {
describe('formatCostUsd', () => {
describe('Zero values', () => {
it('should format zero as $0.00', () => {
expect(formatCostUsd(0)).toBe('$0.00');
});
it('should format negative zero as $0.00', () => {
expect(formatCostUsd(-0)).toBe('$0.00');
});
});
describe('Standard amounts (>= $0.01)', () => {
it('should format 1 cent with 2 decimal places', () => {
expect(formatCostUsd(0.01)).toBe('$0.01');
});
it('should format 1 dollar with 2 decimal places', () => {
expect(formatCostUsd(1.0)).toBe('$1.00');
});
it('should format dollars and cents', () => {
expect(formatCostUsd(1.23)).toBe('$1.23');
});
it('should format large amounts', () => {
expect(formatCostUsd(999.99)).toBe('$999.99');
expect(formatCostUsd(1234.56)).toBe('$1234.56');
});
it('should round to 2 decimal places for amounts >= 1 cent', () => {
expect(formatCostUsd(1.234)).toBe('$1.23');
expect(formatCostUsd(1.235)).toBe('$1.24'); // Rounds up
expect(formatCostUsd(1.999)).toBe('$2.00');
});
});
describe('Sub-cent amounts ($0.001 - $0.01)', () => {
it('should format 1 tenth of a cent with 3 decimal places', () => {
expect(formatCostUsd(0.001)).toBe('$0.001');
});
it('should format sub-cent amounts with 3 decimal places', () => {
expect(formatCostUsd(0.005)).toBe('$0.005');
expect(formatCostUsd(0.009)).toBe('$0.009');
});
it('should round to 3 decimal places for sub-cent amounts', () => {
expect(formatCostUsd(0.0012)).toBe('$0.001');
expect(formatCostUsd(0.0015)).toBe('$0.002'); // Rounds up
expect(formatCostUsd(0.0099)).toBe('$0.010');
});
});
describe('Very small amounts (< $0.001)', () => {
it('should format tiny amounts with 4 decimal places', () => {
expect(formatCostUsd(0.0001)).toBe('$0.0001');
expect(formatCostUsd(0.0005)).toBe('$0.0005');
expect(formatCostUsd(0.0009)).toBe('$0.0009');
});
it('should round to 4 decimal places for tiny amounts', () => {
expect(formatCostUsd(0.00012)).toBe('$0.0001');
expect(formatCostUsd(0.00016)).toBe('$0.0002'); // Rounds up
expect(formatCostUsd(0.00099)).toBe('$0.0010');
});
it('should handle very tiny amounts', () => {
expect(formatCostUsd(0.000001)).toBe('$0.0000');
});
});
describe('Edge cases', () => {
it('should handle negative amounts with 4 decimal places', () => {
// Negative numbers don't match >= comparisons, so they use 4 decimals
expect(formatCostUsd(-1.23)).toBe('$-1.2300');
expect(formatCostUsd(-0.001)).toBe('$-0.0010');
expect(formatCostUsd(-0.0001)).toBe('$-0.0001');
});
it('should handle very large amounts', () => {
expect(formatCostUsd(1000000)).toBe('$1000000.00');
});
it('should handle precision boundaries', () => {
// Boundary between 2 and 3 decimal places
expect(formatCostUsd(0.01)).toBe('$0.01');
expect(formatCostUsd(0.00999)).toBe('$0.010'); // Just below threshold, uses 3 decimals
// Boundary between 3 and 4 decimal places
expect(formatCostUsd(0.001)).toBe('$0.001');
expect(formatCostUsd(0.00099)).toBe('$0.0010'); // Just below threshold, uses 4 decimals
});
});
describe('Real-world API cost examples', () => {
it('should format typical Claude API costs', () => {
// 1M input tokens at $3.00/M
expect(formatCostUsd(3.0)).toBe('$3.00');
// 100k input tokens at $3.00/M
expect(formatCostUsd(0.3)).toBe('$0.30');
// 10k cache read tokens at $0.30/M
expect(formatCostUsd(0.003)).toBe('$0.003');
// 1k cache read tokens at $0.30/M
expect(formatCostUsd(0.0003)).toBe('$0.0003');
});
it('should format session totals', () => {
// Small session
expect(formatCostUsd(0.15)).toBe('$0.15');
// Medium session
expect(formatCostUsd(5.67)).toBe('$5.67');
// Large session
expect(formatCostUsd(29.57)).toBe('$29.57');
});
});
});
describe('formatCostCompact', () => {
describe('Zero values', () => {
it('should format zero as 0.00', () => {
expect(formatCostCompact(0)).toBe('0.00');
});
it('should format negative zero as 0.00', () => {
expect(formatCostCompact(-0)).toBe('0.00');
});
});
describe('Standard amounts (>= $0.01)', () => {
it('should format amounts without $ prefix', () => {
expect(formatCostCompact(0.01)).toBe('0.01');
expect(formatCostCompact(1.0)).toBe('1.00');
expect(formatCostCompact(1.23)).toBe('1.23');
});
it('should format large amounts', () => {
expect(formatCostCompact(999.99)).toBe('999.99');
expect(formatCostCompact(1234.56)).toBe('1234.56');
});
it('should round to 2 decimal places', () => {
expect(formatCostCompact(1.234)).toBe('1.23');
expect(formatCostCompact(1.235)).toBe('1.24'); // Rounds up
expect(formatCostCompact(1.999)).toBe('2.00');
});
});
describe('Sub-cent amounts ($0.001 - $0.01)', () => {
it('should format sub-cent amounts with 3 decimal places', () => {
expect(formatCostCompact(0.001)).toBe('0.001');
expect(formatCostCompact(0.005)).toBe('0.005');
expect(formatCostCompact(0.009)).toBe('0.009');
});
it('should round to 3 decimal places', () => {
expect(formatCostCompact(0.0012)).toBe('0.001');
expect(formatCostCompact(0.0015)).toBe('0.002'); // Rounds up
expect(formatCostCompact(0.0099)).toBe('0.010');
});
});
describe('Very small amounts (< $0.001)', () => {
it('should format tiny amounts with 4 decimal places', () => {
expect(formatCostCompact(0.0001)).toBe('0.0001');
expect(formatCostCompact(0.0005)).toBe('0.0005');
expect(formatCostCompact(0.0009)).toBe('0.0009');
});
it('should round to 4 decimal places', () => {
expect(formatCostCompact(0.00012)).toBe('0.0001');
expect(formatCostCompact(0.00016)).toBe('0.0002'); // Rounds up
expect(formatCostCompact(0.00099)).toBe('0.0010');
});
});
describe('Edge cases', () => {
it('should handle negative amounts with 4 decimal places', () => {
// Negative numbers don't match >= comparisons, so they use 4 decimals
expect(formatCostCompact(-1.23)).toBe('-1.2300');
expect(formatCostCompact(-0.001)).toBe('-0.0010');
expect(formatCostCompact(-0.0001)).toBe('-0.0001');
});
it('should handle very large amounts', () => {
expect(formatCostCompact(1000000)).toBe('1000000.00');
});
});
describe('Comparison with formatCostUsd', () => {
it('should match formatCostUsd except for $ prefix', () => {
const testCases = [0, 0.0001, 0.001, 0.01, 1.23, 999.99];
testCases.forEach((cost) => {
const withPrefix = formatCostUsd(cost);
const compact = formatCostCompact(cost);
// Compact should equal the USD format without the $
expect(compact).toBe(withPrefix.substring(1));
});
});
});
describe('Badge display use cases', () => {
it('should format for badge display', () => {
// Small per-message costs
expect(formatCostCompact(0.0015)).toBe('0.002');
expect(formatCostCompact(0.01)).toBe('0.01');
// Session totals in badges
expect(formatCostCompact(2.5)).toBe('2.50');
expect(formatCostCompact(15.0)).toBe('15.00');
});
});
});
});