Files
gods-eye-view/src/ui/railTimeline.test.mjs
T
0251c74109 feat(weather): add globe wind, observed weather and cyclone context (#617)
Wind (NOAA GFS and ECMWF IFS: animated particles, colour field, a reading at map centre), observed weather (NOAA MRMS radar, GOES and NESDIS infrared clouds, lightning density) on one shared history timeline, NHC and CPHC cyclone advisories with tracks and cones, and a WEATHER panel in the right rail. On 3D Tiles the observed products render as raised shells with a sharper window around the view.

Co-authored-by: Gustavo Beneduzi <[email protected]>
Co-authored-by: Daniel Slay <[email protected]>
Co-authored-by: Rehaan Delmotra <[email protected]>
Co-authored-by: Cursor Agent <[email protected]>
2026-09-22 17:45:39 -05:00

119 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test';
import assert from 'node:assert/strict';
import { createRailTimeline } from './railTimeline.js';
import { railFixture } from './railTestFixture.mjs';
const ticks = [
'2026-09-22T01:00:00Z',
'2026-09-22T01:05:00Z',
'2026-09-22T01:10:00Z',
];
const props = {
ticks,
index: 2,
mode: 'latest',
playing: false,
readout: 'Latest',
disabled: false,
};
test('preview is immediate, commits are coalesced and the drag DOM and tick mapping stay stable', (t) => {
t.mock.timers.enable({ apis: ['setTimeout'] });
const f = railFixture();
const previews = [];
const commits = [];
const view = createRailTimeline({
...f,
onPreview: (tick) => {
previews.push(tick);
return tick;
},
onCommit: (tick) => commits.push(tick),
});
view.update(props);
const slider = f.find((n) => n.tagName === 'INPUT');
const row = slider.parent;
assert.equal(slider.getAttribute('aria-label'), 'Observed history');
slider.value = '0';
slider.dispatchEvent(new Event('input'));
assert.deepEqual(commits, []);
assert.deepEqual(previews, [ticks[0]]);
assert.equal(slider.getAttribute('aria-valuetext'), '09-22 01:00 UTC');
view.update({
...props,
ticks: ticks.slice(1),
index: 1,
readout: 'Refresh',
});
assert.equal(slider.parent, row);
assert.equal(row.children[1], slider);
assert.equal(slider.value, '0');
assert.equal(slider.max, '2');
assert.equal(
f.find((n) => n.className === 'rail-timeline-readout').textContent,
ticks[0],
);
t.mock.timers.tick(149);
assert.equal(commits.length, 0);
slider.value = '1';
slider.dispatchEvent(new Event('input'));
t.mock.timers.tick(1);
assert.deepEqual(commits, [ticks[1]]);
slider.value = '2';
slider.dispatchEvent(new Event('input'));
slider.dispatchEvent(new Event('change'));
assert.deepEqual(commits, [ticks[1], ticks[2]]);
t.mock.timers.tick(150);
assert.equal(commits.length, 2);
assert.equal(slider.max, '1');
view.destroy();
});
test('identical updates write nothing; controls call actions and destruction cancels commits', (t) => {
t.mock.timers.enable({ apis: ['setTimeout'] });
let writes = 0;
const f = railFixture(() => writes++);
const calls = [];
const view = createRailTimeline({
...f,
onCommit: () => calls.push('commit'),
onStep: (n) => calls.push(n),
onLatest: () => calls.push('latest'),
onPlay: () => calls.push('play'),
});
view.update({ ...props, index: 1 });
writes = 0;
view.update({ ...props, index: 1 });
assert.equal(writes, 0);
for (const label of ['‹', '›', 'Latest', 'Play'])
f.find((n) => n.textContent === label).click();
assert.deepEqual(calls, [-1, 1, 'latest', 'play']);
view.update({ ...props, playing: true });
assert.ok(f.find((n) => n.textContent === 'Pause'));
const slider = f.find((n) => n.tagName === 'INPUT');
slider.value = '0';
slider.dispatchEvent(new Event('change'));
assert.equal(calls.at(-1), 'commit');
slider.dispatchEvent(new Event('input'));
view.destroy();
t.mock.timers.tick(150);
assert.equal(calls.length, 5);
assert.equal(f.container.children.length, 0);
});
test('observed history label and endpoint times track the advertised tick range', () => {
const f = railFixture();
const view = createRailTimeline(f);
view.update(props);
assert.equal(
f.find((n) => n.className === 'panel-title').textContent,
'Observed history',
);
const endpoints = f.find((n) => n.className === 'rail-timeline-endpoints');
assert.equal(endpoints.parent.className, 'rail-timeline-track');
assert.deepEqual(
endpoints.children.map((n) => n.textContent),
['01:00 UTC', '01:10 UTC'],
);
view.update({ ...props, ticks: ticks.slice(1) });
assert.equal(endpoints.children[0].textContent, '01:05 UTC');
view.destroy();
});