108 lines
3.0 KiB
TypeScript
108 lines
3.0 KiB
TypeScript
import { describe, expect, it } from 'bun:test';
|
|
import {
|
|
formatCurrencyByScale,
|
|
formatFinancialStatementValue,
|
|
formatScaledNumber
|
|
} from './format';
|
|
|
|
describe('formatScaledNumber', () => {
|
|
it('keeps values below one thousand unscaled', () => {
|
|
expect(formatScaledNumber(950)).toBe('950');
|
|
expect(formatScaledNumber(950.44, { maximumFractionDigits: 2 })).toBe('950.44');
|
|
});
|
|
|
|
it('scales thousands with K suffix', () => {
|
|
expect(formatScaledNumber(12_345)).toBe('12.3K');
|
|
});
|
|
|
|
it('scales millions with M suffix', () => {
|
|
expect(formatScaledNumber(3_250_000)).toBe('3.3M');
|
|
});
|
|
|
|
it('scales billions with B suffix', () => {
|
|
expect(formatScaledNumber(7_500_000_000)).toBe('7.5B');
|
|
});
|
|
|
|
it('preserves negative sign when scaled', () => {
|
|
expect(formatScaledNumber(-2_750_000)).toBe('-2.8M');
|
|
});
|
|
|
|
it('promotes rounded values to the next scale when needed', () => {
|
|
expect(formatScaledNumber(999_950)).toBe('1M');
|
|
});
|
|
});
|
|
|
|
describe('formatCurrencyByScale', () => {
|
|
it('formats values in thousands', () => {
|
|
expect(formatCurrencyByScale(12_345, 'thousands')).toBe('$12.3K');
|
|
});
|
|
|
|
it('formats values in millions', () => {
|
|
expect(formatCurrencyByScale(12_345_678, 'millions')).toBe('$12.3M');
|
|
});
|
|
|
|
it('formats values in billions', () => {
|
|
expect(formatCurrencyByScale(12_345_678_901, 'billions')).toBe('$12.3B');
|
|
});
|
|
|
|
it('keeps sign for negative values', () => {
|
|
expect(formatCurrencyByScale(-2_500_000, 'millions')).toBe('-$2.5M');
|
|
});
|
|
});
|
|
|
|
describe('formatFinancialStatementValue', () => {
|
|
it('renders null statement values as em dashes', () => {
|
|
expect(formatFinancialStatementValue({
|
|
value: null,
|
|
unit: 'currency',
|
|
scale: 'millions',
|
|
rowKey: 'revenue',
|
|
surfaceKind: 'income_statement'
|
|
})).toBe('—');
|
|
});
|
|
|
|
it('formats scaled currency values without a currency symbol', () => {
|
|
expect(formatFinancialStatementValue({
|
|
value: 15_940_899_000,
|
|
unit: 'currency',
|
|
scale: 'millions',
|
|
rowKey: 'revenue',
|
|
surfaceKind: 'income_statement'
|
|
})).toBe('15,940.9');
|
|
expect(formatFinancialStatementValue({
|
|
value: 1_100_000_000,
|
|
unit: 'currency',
|
|
scale: 'millions',
|
|
rowKey: 'long_term_debt_issued',
|
|
surfaceKind: 'cash_flow_statement'
|
|
})).toBe('1,100');
|
|
});
|
|
|
|
it('keeps extra precision for per-share rows', () => {
|
|
expect(formatFinancialStatementValue({
|
|
value: 14.64,
|
|
unit: 'currency',
|
|
scale: 'millions',
|
|
rowKey: 'diluted_eps',
|
|
surfaceKind: 'income_statement'
|
|
})).toBe('14.64');
|
|
});
|
|
|
|
it('formats statement percents and ratios with trimmed precision', () => {
|
|
expect(formatFinancialStatementValue({
|
|
value: 0.233,
|
|
unit: 'percent',
|
|
scale: 'millions',
|
|
rowKey: 'effective_tax_rate',
|
|
surfaceKind: 'income_statement'
|
|
})).toBe('23.3%');
|
|
expect(formatFinancialStatementValue({
|
|
value: 1.5,
|
|
unit: 'ratio',
|
|
scale: 'millions',
|
|
rowKey: 'debt_to_equity',
|
|
surfaceKind: 'ratios'
|
|
})).toBe('1.5x');
|
|
});
|
|
});
|