import './_planet.mjs'; import { test } from 'node:test'; import assert from 'node:assert/strict'; import { MeasurePath } from '../js/measure.js'; import { R_KM } from '../js/geo.js'; import { FakeEl, installFakeDom } from './fakedom.mjs'; const A = { lat: 0, lon: 0 }, B = { lat: 0, lon: 90 }, C = { lat: 90, lon: 0 }; const near = (a, b, eps) => assert.ok(Math.abs(a - b) <= eps, `${a} vs ${b}`); test('open path: segments and total', () => { const m = new MeasurePath(); [A, B, C].forEach(p => m.add(p)); assert.equal(m.segmentsKm().length, 2); near(m.totalKm(), R_KM * Math.PI, 1e-6); // two quarter circles assert.equal(m.areaKm2(), null); assert.equal(m.lines()[0].length, 3); }); test('closing needs three points; a closed path adds the return leg and an area', () => { const m = new MeasurePath(); m.add(A); m.add(B); assert.equal(m.close(), false); m.add(C); assert.equal(m.close(), true); assert.equal(m.segmentsKm().length, 3); near(m.areaKm2(), (4 * Math.PI * R_KM ** 2) / 8, 1); assert.deepEqual(m.lines()[0].at(-1), A); }); test('undo reopens then removes; repeats ignored; adding after a close starts over', () => { const m = new MeasurePath(); [A, B, C].forEach(p => m.add(p)); m.close(); m.undo(); assert.equal(m.closed, false); assert.equal(m.points.length, 3); m.undo(); assert.equal(m.points.length, 2); m.add(B); // a double-click lands twice on the same spot assert.equal(m.points.length, 2); m.add(C); m.close(); m.add(A); assert.deepEqual(m.points, [A]); }); test('panel never renders null/undefined children (DOM would print "null")', async () => { installFakeDom(); const { renderMeasure } = await import('../js/measure.js'); const box = new FakeEl('section'), noop = () => {}; const m = new MeasurePath(); for (const pts of [[], [A], [A, B]]) { m.clear(); pts.forEach(p => m.add(p)); renderMeasure(box, m, { undo: noop, close: noop, clear: noop }); assert.ok(box.kids.every(k => k !== null && k !== undefined), `${pts.length} points: ${box.kids.map(String)}`); } }); test('elevation chart: an svg profile; hovering reports the nearest sample', async () => { installFakeDom(); const { renderProfile, renderMeasure } = await import('../js/measure.js'); const box = new FakeEl('div'), seen = []; const prof = { samples: [{ d_km: 0, lat: 0, lon: 0, z_m: -100, water: true }, { d_km: 10, lat: 0, lon: 0.1, z_m: 500, water: false }], stats: { min_m: -100, max_m: 500, ascent_m: 600, descent_m: 0, water_km: 5, length_km: 10 } }; renderProfile(box, prof, p => seen.push(p)); const chart = box.kids[0]; assert.equal(chart.tag, 'svg'); assert.ok(chart.find(e => e.tag === 'path')); chart.fire('pointermove', { clientX: 300 }); assert.equal(seen.at(-1).d_km, 10); assert.match(box.textContent, /Highest 500 m/); chart.fire('pointerleave'); assert.equal(seen.at(-1), null); const mbox = new FakeEl('section'), m = new MeasurePath(); m.add(A); m.add(B); const pbox = renderMeasure(mbox, m, { undo() {}, close() {}, clear() {} }); assert.ok(mbox.kids.includes(pbox)); });