aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/viewer/tools/smoke/search.mjs
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
committergodosa <godosa@godosa.eu>2026-10-07 00:14:38 +0200
commit3443c1c65e9f1753e1e656b35d08416c1fa298f2 (patch)
tree4e43236f460145a4d75d1b4616dcb7aa6ef08f51 /viewer/tools/smoke/search.mjs
downloadworldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.tar.gz
worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.zip
worldmap-viewer: initial public history
Diffstat (limited to 'viewer/tools/smoke/search.mjs')
-rw-r--r--viewer/tools/smoke/search.mjs29
1 files changed, 29 insertions, 0 deletions
diff --git a/viewer/tools/smoke/search.mjs b/viewer/tools/smoke/search.mjs
new file mode 100644
index 0000000..bdc159c
--- /dev/null
+++ b/viewer/tools/smoke/search.mjs
@@ -0,0 +1,29 @@
+// search.mjs — search by coordinates, H3 cell id and pin name
+const type = s => [{ type: 'key', id: 'kb', actions: [...s].flatMap(c => [{ type: 'keyDown', value: c }, { type: 'keyUp', value: c }]) }];
+const ENTER = '', ESC = '';
+const items = `return [...document.querySelectorAll('#suggest .item')].map(e => e.textContent);`;
+export const steps = [
+ { name: '/ focuses search', wait: 4000, actions: type('/'), js: `return document.activeElement.id;`, expect: v => v === 'search' },
+ { name: 'coordinates suggest', actions: type('40N 10W'), js: items, expect: v => v.length === 1 && v[0].startsWith('40.000° N') },
+ { name: 'Enter flies there with a marker', actions: type(ENTER), settle: 700,
+ js: `const s = window.mapViewer.view.getState(); return { s, n: document.querySelectorAll('.marker.search').length };`,
+ expect: v => Math.abs(v.s.lat - 40) < 0.01 && Math.abs(v.s.lon + 10) < 0.01 && v.s.alt <= 0.6 + 1e-9 && v.n === 1 },
+ { name: 'Esc clears the marker', actions: type(ESC), js: `return document.querySelectorAll('.marker.search').length;`, expect: v => v === 0 },
+ { name: 'cell id suggests', js: `const c = await (await fetch('/api/cell?lat=-20&lon=100')).json(); const i = document.getElementById('search');
+ i.focus(); i.value = c.cell; i.dispatchEvent(new Event('input')); return document.querySelectorAll('#suggest .item').length;`, expect: v => v === 1 },
+ { name: 'Enter resolves the cell', actions: type(ENTER), settle: 900,
+ js: `const s = window.mapViewer.view.getState(); return Math.abs(s.lat + 20) < 0.6 && Math.abs(s.lon - 100) < 0.6;`, expect: v => v === true },
+ { name: 'pins are searchable', js: `await fetch('/api/pins', { method: 'POST', headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ name: 'Searchable Ford', lat: 12, lon: 34 }) }); await window.mapViewer.pins.load();
+ const i = document.getElementById('search'); i.focus(); i.value = 'ford'; i.dispatchEvent(new Event('input'));` + items,
+ expect: v => v.some(t => t.startsWith('Searchable Ford')) },
+ { name: 'Enter on a pin flies without a marker', actions: type(ENTER), settle: 700,
+ js: `const s = window.mapViewer.view.getState(); return [s.lat, s.lon, document.querySelectorAll('.marker.search').length];`,
+ expect: ([la, lo, n]) => Math.abs(la - 12) < 0.01 && Math.abs(lo - 34) < 0.01 && n === 0 },
+ { name: 'measure two points, focus search', js: `const a = window.mapViewer; a.showTab('measure'); a.measure.add({ lat: 1, lon: 2 });
+ a.measure.add({ lat: 3, lon: 4 }); a.measureChanged(); document.getElementById('search').focus(); return a.measure.points.length;`, expect: v => v === 2 },
+ { name: 'Esc in the search box keeps the measure path', actions: type(ESC), expect: v => v === 2,
+ js: `return window.mapViewer.measure.points.length;` },
+ { name: 'junk suggests nothing', js: `const i = document.getElementById('search'); i.value = '95 10'; i.dispatchEvent(new Event('input')); return document.getElementById('suggest').hidden;`,
+ expect: v => v === true },
+];