88 lines
3.3 KiB
JavaScript
88 lines
3.3 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { formatUSD, formatUSDWhole, formatCentsUSD, validateNonNegativeMoney } from './money';
|
|
|
|
describe('validateNonNegativeMoney', () => {
|
|
it('allows blank and zero (non-negative, not strictly positive)', () => {
|
|
expect(validateNonNegativeMoney('')).toBe('');
|
|
expect(validateNonNegativeMoney(null)).toBe('');
|
|
expect(validateNonNegativeMoney(undefined)).toBe('');
|
|
expect(validateNonNegativeMoney('0')).toBe('');
|
|
expect(validateNonNegativeMoney('12.50')).toBe('');
|
|
});
|
|
|
|
it('rejects negatives and non-numeric with a labelled message', () => {
|
|
expect(validateNonNegativeMoney('-1', 'Amount')).toBe('Amount must be a non-negative number');
|
|
expect(validateNonNegativeMoney('abc', 'Balance')).toBe('Balance must be a non-negative number');
|
|
expect(validateNonNegativeMoney('-0.01', 'Min payment')).toBe('Min payment must be a non-negative number');
|
|
});
|
|
});
|
|
|
|
describe('formatUSD (dollars in)', () => {
|
|
it('formats to two decimals with grouping', () => {
|
|
expect(formatUSD(1234.5)).toBe('$1,234.50');
|
|
expect(formatUSD(0)).toBe('$0.00');
|
|
expect(formatUSD(8.99)).toBe('$8.99');
|
|
});
|
|
|
|
it('formats negatives', () => {
|
|
expect(formatUSD(-12.34)).toBe('-$12.34');
|
|
});
|
|
|
|
it('normalizes negative zero to "$0.00" (not "-$0.00")', () => {
|
|
expect(formatUSD(-0)).toBe('$0.00');
|
|
expect(formatUSD(Math.round(-0.2))).toBe('$0.00'); // Math.round(-0.2) === -0
|
|
});
|
|
|
|
it('coerces blank / non-numeric to $0.00 (never NaN)', () => {
|
|
expect(formatUSD(null)).toBe('$0.00');
|
|
expect(formatUSD(undefined)).toBe('$0.00');
|
|
expect(formatUSD('')).toBe('$0.00');
|
|
expect(formatUSD('not a number')).toBe('$0.00');
|
|
});
|
|
|
|
it('accepts numeric strings', () => {
|
|
expect(formatUSD('1234.5')).toBe('$1,234.50');
|
|
});
|
|
|
|
it('whole:true drops the cents', () => {
|
|
expect(formatUSD(1234.56, { whole: true })).toBe('$1,235');
|
|
expect(formatUSDWhole(1234.4)).toBe('$1,234');
|
|
});
|
|
|
|
it('dash:true renders blank input as an em dash, but 0 as $0.00', () => {
|
|
expect(formatUSD(null, { dash: true })).toBe('—');
|
|
expect(formatUSD(undefined, { dash: true })).toBe('—');
|
|
expect(formatUSD('', { dash: true })).toBe('—');
|
|
expect(formatUSD(0, { dash: true })).toBe('$0.00');
|
|
});
|
|
});
|
|
|
|
describe('formatCentsUSD (integer cents in)', () => {
|
|
it('converts cents to dollars', () => {
|
|
expect(formatCentsUSD(1234)).toBe('$12.34');
|
|
expect(formatCentsUSD(0)).toBe('$0.00');
|
|
expect(formatCentsUSD(99)).toBe('$0.99');
|
|
});
|
|
|
|
it('unsigned negatives get a leading minus only', () => {
|
|
expect(formatCentsUSD(-1234)).toBe('-$12.34');
|
|
});
|
|
|
|
it('signed:true adds +/- for income vs expense', () => {
|
|
expect(formatCentsUSD(1234, { signed: true })).toBe('+$12.34');
|
|
expect(formatCentsUSD(-1234, { signed: true })).toBe('-$12.34');
|
|
expect(formatCentsUSD(0, { signed: true })).toBe('+$0.00');
|
|
});
|
|
|
|
it('dash:true renders blank input as an em dash', () => {
|
|
expect(formatCentsUSD(null, { dash: true })).toBe('—');
|
|
expect(formatCentsUSD(undefined, { dash: true })).toBe('—');
|
|
expect(formatCentsUSD(0, { dash: true })).toBe('$0.00');
|
|
});
|
|
|
|
it('coerces non-numeric to $0.00 (never NaN)', () => {
|
|
expect(formatCentsUSD('abc')).toBe('$0.00');
|
|
expect(formatCentsUSD(null)).toBe('$0.00');
|
|
});
|
|
});
|