import { describe, expect, it } from 'vitest'; import { compareMetricValues, metricDuration, metricNumber, metricPercent, metricPeriodLabels } from '../../src/lib/ui/metrics.js'; describe('metric presentation', () => { it('distinguishes unavailable evidence, zero, and tiny nonzero values', () => { expect(metricPercent(0, 0)).toBe('—'); expect(metricPercent(0, 1)).toBe('0.0%'); expect(metricPercent(0.0001, 1)).toBe('<0.1%'); expect(metricDuration(0)).toBe('0 h'); expect(metricDuration(0.1 / 3600)).toBe('<1 s'); expect(metricDuration(45 / 3600)).toBe('45 s'); expect(metricDuration(90 / 3600)).toBe('1.5 min'); expect(metricNumber(0.0125)).toBe('<0.1'); }); it('sorts numerically while putting unavailable observations last in both directions', () => { const values = [2, null, 100, 0, 10]; expect([...values].sort((a, b) => compareMetricValues(a, b, 'desc'))).toEqual([ 100, 10, 2, 0, null ]); expect([...values].sort((a, b) => compareMetricValues(a, b, 'asc'))).toEqual([ 0, 2, 10, 100, null ]); }); it('labels daily buckets by their actual starting weekday in the report timezone', () => { const points = Array.from({ length: 8 }, (_, day) => ({ startAt: Date.parse('2026-10-01T00:00:00Z') + day * 86_400_000 })); expect(metricPeriodLabels(points, 7, 'America/New_York').map((item) => item.label)).toEqual( ['Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Mon', 'Tue', 'Wed'] ); expect(metricPeriodLabels(points, 7, 'UTC')[0].label).toBe('Thu'); expect(metricPeriodLabels(points, 7, 'UTC')[0].position).toBe(6.25); expect(metricPeriodLabels([], 7, 'UTC')).toEqual([]); }); it('keeps hourly and long-range labels sparse without relabelling UTC buckets as local days', () => { const points = Array.from({ length: 31 }, (_, day) => ({ startAt: Date.parse('2026-10-01T00:00:00Z') + day * 86_400_000 })); const labels = metricPeriodLabels(points, 30, 'UTC'); expect(labels.length).toBeLessThanOrEqual(6); expect(labels[0]).toMatchObject({ label: 'Thu', date: '1' }); const hourly = metricPeriodLabels( Array.from({ length: 25 }, (_, hour) => ({ startAt: Date.parse('2026-11-01T04:00:00Z') + hour * 3_600_000 })), 1, 'America/New_York' ); expect(hourly[0].label).toBe('12 AM'); expect(hourly[1].label).toBe('4 AM'); expect(hourly).toHaveLength(5); }); });