when-am-i / files / src / utils / lanes.test.ts
lanes.test.ts
ba77fd91 2026-06-19 Pavel Safronov | 1 | import { describe, it, expect } from 'vitest'; |
| 2 | import { assignLanes } from './lanes'; | |
| 3 | ||
| 4 | interface Span { start: number; end: number; } | |
| 5 | const lane = (spans: Span[]) => | |
| 6 | assignLanes(spans, (s) => s.start, (s) => s.end); | |
| 7 | ||
| 8 | describe('assignLanes', () => { | |
| 9 | it('puts non-overlapping, adjacent intervals in the same lane', () => { | |
| 10 | const { lanes, count } = lane([ | |
| 11 | { start: 1630, end: 1752 }, | |
| 12 | { start: 1752, end: Infinity }, // half-open: shares the lane | |
| 13 | ]); | |
| 14 | expect(count).toBe(1); | |
| 15 | expect(lanes.map((l) => l.lane)).toEqual([0, 0]); | |
| 16 | }); | |
| 17 | ||
| 18 | it('puts overlapping intervals in separate lanes', () => { | |
| 19 | const { lanes, count } = lane([ | |
| 20 | { start: -Infinity, end: Infinity }, // spans everything | |
| 21 | { start: 1630, end: 1752 }, | |
| 22 | { start: 1752, end: Infinity }, | |
| 23 | ]); | |
| 24 | expect(count).toBe(2); | |
| 25 | // The all-spanning interval gets its own lane; the two adjacent ones share the other. | |
| 26 | const byOrder = lanes.sort((a, b) => a.item.start - b.item.start).map((l) => l.lane); | |
| 27 | expect(byOrder[0]).not.toBe(byOrder[1]); // spanning vs 1630 | |
| 28 | expect(byOrder[1]).toBe(byOrder[2]); // 1630 and 1752 share | |
| 29 | }); | |
| 30 | ||
| 31 | it('opens a third lane when three intervals overlap at once', () => { | |
| 32 | const { count } = lane([ | |
| 33 | { start: 0, end: 10 }, | |
| 34 | { start: 5, end: 15 }, | |
| 35 | { start: 8, end: 20 }, | |
| 36 | ]); | |
| 37 | expect(count).toBe(3); | |
| 38 | }); | |
| 39 | }); |