| 1 |
import { test } from 'node:test'; |
| 2 |
import assert from 'node:assert/strict'; |
| 3 |
import { |
| 4 |
type Segment, |
| 5 |
formatTime, |
| 6 |
buildTimeline, |
| 7 |
mainOffsetMs, |
| 8 |
segmentIndexAtVirtualMs, |
| 9 |
chapterToVirtualMs, |
| 10 |
} from './media-player.logic.ts'; |
| 11 |
|
| 12 |
// A main file A split around an insertion, then a second main file B: |
| 13 |
// [ main A 10s ][ ad 5s ][ main A 8s ][ main B 6s ] |
| 14 |
const segs: Segment[] = [ |
| 15 |
{ url: 'A', duration_ms: 10_000, segment_type: 'main' }, |
| 16 |
{ url: 'X', duration_ms: 5_000, segment_type: 'ad' }, |
| 17 |
{ url: 'A', duration_ms: 8_000, segment_type: 'main' }, |
| 18 |
{ url: 'B', duration_ms: 6_000, segment_type: 'main' }, |
| 19 |
]; |
| 20 |
|
| 21 |
test('formatTime formats m:ss and h:mm:ss', () => { |
| 22 |
assert.equal(formatTime(0), '0:00'); |
| 23 |
assert.equal(formatTime(65), '1:05'); |
| 24 |
assert.equal(formatTime(3661), '1:01:01'); |
| 25 |
assert.equal(formatTime(NaN), '0:00'); |
| 26 |
}); |
| 27 |
|
| 28 |
test('buildTimeline gives cumulative starts + total', () => { |
| 29 |
const { segStarts, totalMs } = buildTimeline(segs); |
| 30 |
assert.deepEqual(segStarts, [0, 10_000, 15_000, 23_000]); |
| 31 |
assert.equal(totalMs, 29_000); |
| 32 |
}); |
| 33 |
|
| 34 |
test('mainOffsetMs is the offset within a split main URL', () => { |
| 35 |
assert.equal(mainOffsetMs(segs, 0), 0); // A's first appearance |
| 36 |
assert.equal(mainOffsetMs(segs, 1), 0); // insertion → 0 |
| 37 |
assert.equal(mainOffsetMs(segs, 2), 10_000); // A's second slice sits 10s into A |
| 38 |
assert.equal(mainOffsetMs(segs, 3), 0); // B's first appearance |
| 39 |
}); |
| 40 |
|
| 41 |
test('segmentIndexAtVirtualMs finds the containing segment and clamps past end', () => { |
| 42 |
const { segStarts, totalMs } = buildTimeline(segs); |
| 43 |
assert.equal(segmentIndexAtVirtualMs(segStarts, segs, 0), 0); |
| 44 |
assert.equal(segmentIndexAtVirtualMs(segStarts, segs, 12_000), 1); |
| 45 |
assert.equal(segmentIndexAtVirtualMs(segStarts, segs, 15_000), 2); |
| 46 |
assert.equal(segmentIndexAtVirtualMs(segStarts, segs, totalMs + 1), 3); |
| 47 |
}); |
| 48 |
|
| 49 |
test('chapterToVirtualMs maps main-only time across insertions', () => { |
| 50 |
// 5s into main lands at 5s virtual (nothing precedes it). |
| 51 |
assert.equal(chapterToVirtualMs(segs, 5_000), 5_000); |
| 52 |
// 12s of main = all of A1 (10s) + 2s of A2; virtual = 10s A1 + 5s ad + 2s = 17s. |
| 53 |
assert.equal(chapterToVirtualMs(segs, 12_000), 17_000); |
| 54 |
}); |
| 55 |
|