-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse.test.mjs
More file actions
146 lines (122 loc) · 5.13 KB
/
Copy pathparse.test.mjs
File metadata and controls
146 lines (122 loc) · 5.13 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
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
animationNameFromShorthand,
durationFromShorthand,
parseRange,
parseRangeBoundary,
parseTimeline,
splitTopLevel
} from '../lib/parse.js';
import { offsetFromSelector } from '../lib/keyframes.js';
import { resolveMode } from '../lib/manifest.js';
describe('splitTopLevel', () => {
it('keeps function arguments together', () => {
assert.deepEqual(splitTopLevel('scroll(root block) 1s'), ['scroll(root block)', '1s']);
});
it('collapses runs of whitespace', () => {
assert.deepEqual(splitTopLevel(' a b '), ['a', 'b']);
});
});
describe('parseTimeline', () => {
it('parses view() with no arguments', () => {
assert.deepEqual(parseTimeline('view()'), { kind: 'view', name: null, axis: 'block', scroller: 'nearest' });
});
it('parses scroll() with scroller and axis in either order', () => {
assert.deepEqual(parseTimeline('scroll(inline root)').axis, 'inline');
assert.deepEqual(parseTimeline('scroll(inline root)').scroller, 'root');
assert.deepEqual(parseTimeline('scroll(root inline)').scroller, 'root');
});
it('tolerates comma-separated arguments', () => {
assert.equal(parseTimeline('view(block, 10%)').kind, 'view');
});
it('recognises none and auto', () => {
assert.equal(parseTimeline('none').kind, 'none');
assert.equal(parseTimeline('auto').kind, 'auto');
});
it('treats anything else as a named timeline', () => {
assert.deepEqual(parseTimeline('--hero').name, '--hero');
});
});
describe('parseRangeBoundary', () => {
it('defaults to cover with the supplied percentage', () => {
assert.deepEqual(parseRangeBoundary('normal', 0), { name: 'cover', percent: 0 });
assert.deepEqual(parseRangeBoundary('normal', 100), { name: 'cover', percent: 100 });
});
it('reads a name and percentage', () => {
assert.deepEqual(parseRangeBoundary('entry 25%', 0), { name: 'entry', percent: 25 });
});
it('accepts negative percentages', () => {
assert.deepEqual(parseRangeBoundary('exit -10%', 0), { name: 'exit', percent: -10 });
});
});
describe('parseRange', () => {
it('splits a two-sided shorthand', () => {
assert.deepEqual(parseRange({ range: 'entry 0% exit 100%' }), {
start: { name: 'entry', percent: 0 },
end: { name: 'exit', percent: 100 }
});
});
it('mirrors a one-sided shorthand across both boundaries', () => {
assert.deepEqual(parseRange({ range: 'entry' }), {
start: { name: 'entry', percent: 0 },
end: { name: 'entry', percent: 100 }
});
});
it('handles a bare name plus a bare percentage', () => {
assert.deepEqual(parseRange({ range: 'contain 10% contain 90%' }), {
start: { name: 'contain', percent: 10 },
end: { name: 'contain', percent: 90 }
});
});
it('uses longhands when no shorthand is present', () => {
assert.deepEqual(parseRange({ start: 'cover 20%', end: 'cover 80%' }), {
start: { name: 'cover', percent: 20 },
end: { name: 'cover', percent: 80 }
});
});
});
describe('animationNameFromShorthand', () => {
it('skips durations, easings and keywords', () => {
assert.equal(animationNameFromShorthand('1s linear both fade-up'), 'fade-up');
assert.equal(animationNameFromShorthand('fade-up 300ms ease-in-out infinite'), 'fade-up');
assert.equal(animationNameFromShorthand('cubic-bezier(0.4, 0, 0.2, 1) 2s reveal'), 'reveal');
});
it('returns null when only keywords are present', () => {
assert.equal(animationNameFromShorthand('1s linear both'), null);
});
});
describe('durationFromShorthand', () => {
it('reads seconds and milliseconds', () => {
assert.equal(durationFromShorthand('fade 1.5s linear'), 1500);
assert.equal(durationFromShorthand('fade 250ms linear'), 250);
});
it('returns null when no time is present', () => {
assert.equal(durationFromShorthand('fade linear'), null);
});
});
describe('offsetFromSelector', () => {
it('maps from/to and percentages', () => {
assert.equal(offsetFromSelector('from'), 0);
assert.equal(offsetFromSelector('TO'), 1);
assert.equal(offsetFromSelector(' 62.5% '), 0.625);
assert.equal(offsetFromSelector('bogus'), null);
});
});
describe('resolveMode', () => {
const view = { kind: 'view', name: null, axis: 'block', scroller: 'nearest' };
const scroll = { kind: 'scroll', name: null, axis: 'block', scroller: 'nearest' };
const entryRange = { start: { name: 'entry', percent: 0 }, end: { name: 'entry', percent: 100 } };
const coverRange = { start: { name: 'cover', percent: 0 }, end: { name: 'cover', percent: 100 } };
it('uses the observer for a single-named entry/exit range', () => {
assert.equal(resolveMode(view, entryRange, 'observer'), 'observer');
});
it('uses progress for cover and for scroll() timelines', () => {
assert.equal(resolveMode(view, coverRange, 'observer'), 'progress');
assert.equal(resolveMode(scroll, entryRange, 'observer'), 'progress');
});
it('passes explicit modes straight through', () => {
assert.equal(resolveMode(view, entryRange, 'progress'), 'progress');
assert.equal(resolveMode(view, entryRange, 'none'), 'none');
});
});