-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrange-math.test.mjs
More file actions
152 lines (126 loc) · 5.66 KB
/
Copy pathrange-math.test.mjs
File metadata and controls
152 lines (126 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
clamp,
isInRange,
progressAt,
resolveBoundary,
resolveNamedRange,
resolveRange,
resolveScrollRange,
viewProgress
} from '../src/range-math.js';
/** A 200px subject 1000px down a 800px-tall scrollport. */
const geometry = { subjectOffset: 1000, subjectSize: 200, scrollportSize: 800 };
/** A subject taller than the scrollport. */
const tall = { subjectOffset: 1000, subjectSize: 1200, scrollportSize: 800 };
describe('clamp', () => {
it('clamps to the default 0–1 interval', () => {
assert.equal(clamp(-3), 0);
assert.equal(clamp(0.25), 0.25);
assert.equal(clamp(9), 1);
});
it('honours explicit bounds', () => {
assert.equal(clamp(15, 0, 10), 10);
});
});
describe('resolveNamedRange', () => {
it('resolves cover as first-touch to fully-left', () => {
assert.deepEqual(resolveNamedRange('cover', geometry), { start: 200, end: 1200 });
});
it('resolves contain for a subject smaller than the scrollport', () => {
// subject fully visible from scroll 400 (subject bottom at scrollport bottom)
// through scroll 1000 (subject top at scrollport top).
assert.deepEqual(resolveNamedRange('contain', geometry), { start: 400, end: 1000 });
});
it('resolves contain for a subject larger than the scrollport', () => {
// The subject covers the scrollport from scroll 1000 to scroll 1400.
assert.deepEqual(resolveNamedRange('contain', tall), { start: 1000, end: 1400 });
});
it('makes entry span cover-start to contain-start', () => {
const cover = resolveNamedRange('cover', geometry);
const contain = resolveNamedRange('contain', geometry);
assert.deepEqual(resolveNamedRange('entry', geometry), { start: cover.start, end: contain.start });
});
it('makes exit span contain-end to cover-end', () => {
const cover = resolveNamedRange('cover', geometry);
const contain = resolveNamedRange('contain', geometry);
assert.deepEqual(resolveNamedRange('exit', geometry), { start: contain.end, end: cover.end });
});
it('resolves entry-crossing as the subject crossing the end edge', () => {
assert.deepEqual(resolveNamedRange('entry-crossing', geometry), { start: 200, end: 400 });
});
it('resolves exit-crossing as the subject crossing the start edge', () => {
assert.deepEqual(resolveNamedRange('exit-crossing', geometry), { start: 1000, end: 1200 });
});
it('equals cover when composing entry-crossing start with exit-crossing end', () => {
const cover = resolveNamedRange('cover', geometry);
assert.equal(resolveNamedRange('entry-crossing', geometry).start, cover.start);
assert.equal(resolveNamedRange('exit-crossing', geometry).end, cover.end);
});
it('falls back to cover for unknown range names', () => {
assert.deepEqual(resolveNamedRange('nonsense', geometry), resolveNamedRange('cover', geometry));
});
it('shrinks the scrollport by view-timeline insets', () => {
const inset = { ...geometry, insetStart: 100, insetEnd: 100 };
// Effective scrollport is 600px, and the start edge moves down by 100px.
assert.deepEqual(resolveNamedRange('cover', inset), { start: 300, end: 1100 });
});
});
describe('resolveBoundary', () => {
it('resolves a plain named boundary to the range start', () => {
assert.equal(resolveBoundary({ name: 'entry', percent: 0 }, geometry), 200);
});
it('interpolates a percentage inside the named range', () => {
// entry spans 200 → 400, so 50% is 300.
assert.equal(resolveBoundary({ name: 'entry', percent: 50 }, geometry), 300);
});
it('permits percentages outside 0–100', () => {
assert.equal(resolveBoundary({ name: 'entry', percent: 150 }, geometry), 500);
});
});
describe('resolveRange', () => {
it('mixes different named ranges on each side', () => {
const spec = { start: { name: 'entry', percent: 0 }, end: { name: 'exit', percent: 100 } };
assert.deepEqual(resolveRange(spec, geometry), { start: 200, end: 1200 });
});
});
describe('resolveScrollRange', () => {
it('spans the scrollable distance', () => {
assert.deepEqual(resolveScrollRange({ scrollSize: 3000, clientSize: 800 }), { start: 0, end: 2200 });
});
it('never reports a negative range for unscrollable content', () => {
assert.deepEqual(resolveScrollRange({ scrollSize: 500, clientSize: 800 }), { start: 0, end: 0 });
});
});
describe('progressAt', () => {
it('maps the range onto 0–1', () => {
assert.equal(progressAt(200, { start: 200, end: 1200 }), 0);
assert.equal(progressAt(700, { start: 200, end: 1200 }), 0.5);
assert.equal(progressAt(1200, { start: 200, end: 1200 }), 1);
});
it('clamps outside the range', () => {
assert.equal(progressAt(0, { start: 200, end: 1200 }), 0);
assert.equal(progressAt(5000, { start: 200, end: 1200 }), 1);
});
it('treats a zero-length range as a step', () => {
assert.equal(progressAt(99, { start: 100, end: 100 }), 0);
assert.equal(progressAt(100, { start: 100, end: 100 }), 1);
});
});
describe('viewProgress', () => {
it('reports 0.5 halfway through the entry range', () => {
const spec = { start: { name: 'entry', percent: 0 }, end: { name: 'entry', percent: 100 } };
assert.equal(viewProgress(300, spec, geometry), 0.5);
});
it('stays pinned at 0 before the subject appears', () => {
const spec = { start: { name: 'cover', percent: 0 }, end: { name: 'cover', percent: 100 } };
assert.equal(viewProgress(0, spec, geometry), 0);
});
});
describe('isInRange', () => {
it('is direction agnostic', () => {
assert.equal(isInRange(500, { start: 1000, end: 200 }), true);
assert.equal(isInRange(1500, { start: 200, end: 1000 }), false);
});
});