Files
eden/tests/money-formatting.test.ts
T

68 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from 'bun:test';
import {
decimalIskToCents,
validateQuantity,
} from '../src/lib/domain/money';
import { formatIskAmount, formatQuantity } from '../src/lib/domain/formatting';
describe('exact decimal ISK conversion', () => {
test('preserves the existing unsigned ESI syntax and positive half-up rounding', () => {
expect(decimalIskToCents('0')).toBe('0');
expect(decimalIskToCents('12.34')).toBe('1234');
expect(decimalIskToCents('12.345')).toBe('1235');
expect(decimalIskToCents('12.344')).toBe('1234');
expect(decimalIskToCents('1e2')).toBe('10000');
expect(decimalIskToCents('1.2e-1')).toBe('12');
expect(decimalIskToCents('0.000e1000')).toBe('0');
});
test('rounds signed values half away from zero and normalizes negative zero', () => {
expect(decimalIskToCents('1.005')).toBe('101');
expect(decimalIskToCents('-1.005')).toBe('-101');
expect(decimalIskToCents('1.004')).toBe('100');
expect(decimalIskToCents('-1.004')).toBe('-100');
expect(decimalIskToCents('-0')).toBe('0');
expect(decimalIskToCents('-0.004')).toBe('0');
expect(decimalIskToCents('-0.005')).toBe('-1');
});
test('rejects malformed syntax, strict trailing-newline bypasses, and plus signs', () => {
for (const value of ['+1', '01', '1.', '.1', 'NaN', 'Infinity', '1_000', ' 1', '1 ', '١', '1\n', '1\r', '1e2\n']) {
expect(() => decimalIskToCents(value)).toThrow();
}
});
test('enforces exponent, shift, coefficient, and raw-input limits without truncation', () => {
expect(decimalIskToCents(`1e${'0'.repeat(8190)}`)).toBe('100');
expect(() => decimalIskToCents(`1e${'0'.repeat(8191)}`)).toThrow('input exceeds resource bounds');
expect(() => decimalIskToCents('1e1001')).toThrow('exponent is outside bounds');
expect(() => decimalIskToCents('1e-1001')).toThrow('exponent is outside bounds');
expect(decimalIskToCents('1e1000')).toBe(`1${'0'.repeat(1002)}`);
expect(decimalIskToCents(`0.${'0'.repeat(999)}1`)).toBe('0');
expect(() => decimalIskToCents(`0.${'0'.repeat(1000)}1`)).toThrow('shift exceeds resource bounds');
expect(decimalIskToCents('1'.repeat(4096))).toBe(`${BigInt('1'.repeat(4096)) * 100n}`);
expect(() => decimalIskToCents('1'.repeat(4097))).toThrow('coefficient exceeds resource bounds');
});
});
describe('shared exact money formatting', () => {
test('formats signed cents with correct fractional sign and grouping', () => {
expect(formatIskAmount('0')).toBe('0.00');
expect(formatIskAmount('123456789')).toBe('1,234,567.89');
expect(formatIskAmount('-1')).toBe('-0.01');
expect(formatIskAmount('-99')).toBe('-0.99');
expect(formatIskAmount('-100')).toBe('-1.00');
expect(formatIskAmount('-101')).toBe('-1.01');
expect(formatIskAmount('-123456789')).toBe('-1,234,567.89');
expect(formatIskAmount(-1n)).toBe('-0.01');
});
test('formats quantities without coercing bigint or changing quantity policy', () => {
const large = 2n ** 100n;
expect(validateQuantity(Number.MAX_SAFE_INTEGER)).toBe(BigInt(Number.MAX_SAFE_INTEGER));
expect(validateQuantity(large)).toBe(large);
expect(formatQuantity(large)).toBe('1,267,650,600,228,229,401,496,703,205,376');
expect(() => formatQuantity(-1)).toThrow();
});
});