mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-10-26 16:58:28 +00:00
Measured design audit fixes, one type ladder and header, zero clipping at 900 to 1680, light-theme contrast, Lucide icons, shared Escape, plurals and provider names, motion tokens with zero refresh shift, black frame with rounded content card, grouped monochrome sidebar with collapse, two-layer card system on every screen, Overview gauge, sparkline cards and chart grid, wallpaper onboarding, Windows fixes. Every number diffed identical to main on a fixed range; 1,032 app tests passing.
83 lines
3.2 KiB
TypeScript
83 lines
3.2 KiB
TypeScript
import { afterEach, describe, expect, it } from 'vitest'
|
||
|
||
import { formatCompact, formatConverted, formatCount, formatDayLong, formatDayShort, formatDuration, formatUsd, setActiveCurrency } from './format'
|
||
|
||
describe('currency-aware formatting', () => {
|
||
afterEach(() => setActiveCurrency({ code: 'USD', symbol: '$', rate: 1 }))
|
||
|
||
it('formats raw USD with the default USD currency', () => {
|
||
expect(formatUsd(12.34)).toBe('$12.34')
|
||
expect(formatUsd(1_234.5)).toBe('$1,234.50')
|
||
})
|
||
|
||
it('applies the active FX rate and symbol to raw-USD values exactly once', () => {
|
||
setActiveCurrency({ code: 'EUR', symbol: '€', rate: 0.9 })
|
||
// 100 USD × 0.9 = 90.00 EUR
|
||
expect(formatUsd(100)).toBe('€90.00')
|
||
expect(formatUsd(1_000)).toBe('€900.00')
|
||
})
|
||
|
||
it('formatConverted swaps the symbol without re-applying the rate (CLI-converted values)', () => {
|
||
setActiveCurrency({ code: 'EUR', symbol: '€', rate: 0.9 })
|
||
// Already-EUR input renders as-is, never multiplied by the rate again.
|
||
expect(formatConverted(90)).toBe('€90.00')
|
||
expect(formatConverted(20)).toBe('€20.00')
|
||
})
|
||
})
|
||
|
||
describe('formatCompact', () => {
|
||
it('formats zero, plain counts, thousands, and millions compactly', () => {
|
||
expect(formatCompact(0)).toBe('0')
|
||
expect(formatCompact(842)).toBe('842')
|
||
expect(formatCompact(1_842)).toBe('1.8K')
|
||
expect(formatCompact(184_000)).toBe('184K')
|
||
expect(formatCompact(1_200_000)).toBe('1.2M')
|
||
})
|
||
|
||
it('trims trailing decimals and rejects non-finite values', () => {
|
||
expect(formatCompact(2_000_000)).toBe('2M')
|
||
expect(formatCompact(Number.NaN)).toBe('—')
|
||
})
|
||
})
|
||
|
||
describe('date and duration formatters', () => {
|
||
it('formats short and long calendar dates and handles invalid input', () => {
|
||
const date = '2026-07-10T12:00:00'
|
||
expect(formatDayShort(date)).toBe('Jul 10')
|
||
expect(formatDayLong(date)).toBe('Jul 10, 2026')
|
||
expect(formatDayShort('not-a-date')).toBe('—')
|
||
expect(formatDayLong('not-a-date')).toBe('—')
|
||
})
|
||
|
||
it('formats seconds, minutes, hours, and invalid durations', () => {
|
||
expect(formatDuration(29_000)).toBe('29s')
|
||
expect(formatDuration(30_000)).toBe('30s')
|
||
expect(formatDuration(47 * 60_000)).toBe('47m')
|
||
expect(formatDuration(134 * 60_000)).toBe('2h 14m')
|
||
expect(formatDuration(286 * 3_600_000 + 39 * 60_000)).toBe('12 days')
|
||
expect(formatDuration(0)).toBe('—')
|
||
})
|
||
})
|
||
|
||
describe('formatCount', () => {
|
||
it('uses the singular noun for exactly one', () => {
|
||
expect(formatCount(1, 'session')).toBe('1 session')
|
||
expect(formatCount(1, 'finding')).toBe('1 finding')
|
||
expect(formatCount(1, 'distinct session')).toBe('1 distinct session')
|
||
})
|
||
|
||
it('uses the plural noun for zero and for more than one', () => {
|
||
expect(formatCount(0, 'session')).toBe('0 sessions')
|
||
expect(formatCount(2, 'session')).toBe('2 sessions')
|
||
})
|
||
|
||
it('groups thousands with the same separator everywhere', () => {
|
||
expect(formatCount(5084, 'session')).toBe('5,084 sessions')
|
||
expect(formatCount(6205, 'session')).toBe('6,205 sessions')
|
||
})
|
||
|
||
it('takes an irregular plural when the noun needs one', () => {
|
||
expect(formatCount(1, 'entry', 'entries')).toBe('1 entry')
|
||
expect(formatCount(3, 'entry', 'entries')).toBe('3 entries')
|
||
})
|
||
})
|