worldmap-viewer

git clone https://git.godosa.eu/worldmap-viewer

master

raw ยท 3152 bytes

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));
});