fuzzyworld

when-am-i / files / src / utils / yearScale.test.ts

yearScale.test.ts

2.8 KB · history · blame

1import { describe, it, expect } from 'vitest';
2import { buildYearScale } from './yearScale';
3
4describe('buildYearScale', () => {
5 it('places the endpoints at 0 and 1', () => {
6 const s = buildYearScale(-243, 2026, [1954]);
7 expect(s.toFraction(-243)).toBe(0);
8 expect(s.toFraction(2026)).toBe(1);
9 });
10
11 it('clamps years outside the range (including ±Infinity for open-ended eras)', () => {
12 const s = buildYearScale(-243, 2026, [1954]);
13 expect(s.toFraction(-Infinity)).toBe(0);
14 expect(s.toFraction(-5000)).toBe(0);
15 expect(s.toFraction(Infinity)).toBe(1);
16 expect(s.toFraction(9999)).toBe(1);
17 });
18
19 it('anchors on the region key years (a single boundary lands dead-centre)', () => {
20 const s = buildYearScale(-243, 2026, [1954]);
21 expect(s.anchors).toEqual([-243, 1954, 2026]);
22 expect(s.toFraction(1954)).toBeCloseTo(0.5, 6);
23 });
24
25 it('sorts and de-dupes key years and drops any outside the range', () => {
26 const s = buildYearScale(-243, 2026, [1910, 1896, 1896, 9999, -500, 1907, 1897]);
27 expect(s.anchors).toEqual([-243, 1896, 1897, 1907, 1910, 2026]);
28 });
29
30 it('spreads clustered key dates evenly so each is readable (Korea 1896–1910)', () => {
31 const s = buildYearScale(-243, 2026, [1896, 1897, 1907, 1910]);
32 const fracs = s.anchors.map((y) => s.toFraction(y));
33 const step = 1 / (s.anchors.length - 1);
34 for (let i = 1; i < fracs.length; i++) {
35 // Equal-width segments → even spacing, even though 1896→1897 is one
36 // year and 1910→2026 is 116 (proportional spacing would collide them).
37 expect(fracs[i] - fracs[i - 1]).toBeCloseTo(step, 6);
38 }
39 });
40
41 it('falls back to round epoch anchors when the region has no key years', () => {
42 const s = buildYearScale(-243, 2026, []);
43 expect(s.anchors).toEqual([-243, 1500, 1800, 1900, 2026]);
44 });
45
46 it('is monotonic increasing in year', () => {
47 const s = buildYearScale(-243, 2026, [1896, 1897, 1907, 1910]);
48 let prev = -Infinity;
49 for (let y = -243; y <= 2026; y += 7) {
50 const f = s.toFraction(y);
51 expect(f).toBeGreaterThanOrEqual(prev);
52 prev = f;
53 }
54 });
55
56 it('round-trips year → fraction → year', () => {
57 const s = buildYearScale(-243, 2026, [1792, 1806, 1871]);
58 for (const y of [-243, 500, 1792, 1806, 1850, 1871, 1945, 2026]) {
59 expect(s.toYear(s.toFraction(y))).toBeCloseTo(y, 6);
60 }
61 });
62
63 it('degrades to a single linear segment when there are no usable anchors', () => {
64 const s = buildYearScale(1980, 2026, []); // no epoch anchors in range either
65 expect(s.anchors).toEqual([1980, 2026]);
66 expect(s.toFraction(2003)).toBeCloseTo((2003 - 1980) / (2026 - 1980), 6);
67 });
68});