42 lines
2.7 KiB
JavaScript
42 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* check-map-fly-reduced-motion — useMapFly honours prefers-reduced-motion for EVERY camera move, headless.
|
|
*
|
|
* A reader who asks the OS for reduced motion must not get flying/easing maps (a photosensitivity issue).
|
|
* useMapFly decides it itself (cam()), so a caller cannot forget it; flyToCoords also honours caller
|
|
* options (it used to take none, silently dropping a caller's { duration: 0 }).
|
|
* Runs the real composable against a recording fake map, with matchMedia reporting reduce / no-preference.
|
|
* USAGE node internal/check-map-fly-reduced-motion.mjs EXIT 0 pass · 1 fail
|
|
*/
|
|
let reduce = false
|
|
globalThis.window = { matchMedia: (q) => ({ matches: reduce && /prefers-reduced-motion:\s*reduce/.test(q) }), devicePixelRatio: 1 }
|
|
const { useMapFly } = await import('../library/composables/useMapFly.js')
|
|
const calls = []
|
|
const map = new Proxy({}, { get: (_, k) => (k === 'getZoom' ? () => 3 : (...a) => { calls.push({ fn: String(k), a }) }) })
|
|
const fly = useMapFly({ getMap: () => map })
|
|
let bad = 0
|
|
const check = (name, ok, got) => { if (!ok) bad++; console.log(` ${ok ? 'ok ' : 'FAIL'} ${name}${ok ? '' : ' — got ' + JSON.stringify(got)}`) }
|
|
const run = (fn) => { calls.length = 0; fn(); return calls.slice() }
|
|
const B = [[0, 0], [10, 10]]
|
|
|
|
console.log('MAP-FLY-REDUCED-MOTION: the real useMapFly against a recording map (no browser)')
|
|
reduce = false
|
|
let c = run(() => fly.flyTo([1, 2], { zoom: 4 }))
|
|
check('motion allowed: flyTo animates', c[0]?.fn === 'flyTo', c)
|
|
c = run(() => fly.fitBounds(B))
|
|
check('motion allowed: fitBounds eases (duration > 0)', c[0]?.fn === 'fitBounds' && c[0].a[1].duration > 0, c)
|
|
c = run(() => fly.flyToCoords({ longitude: 1, latitude: 2 }, 5, { duration: 0 }))
|
|
check('flyToCoords passes caller options through ({ duration: 0 })', c[0]?.fn === 'flyTo' && c[0].a[0].duration === 0 && c[0].a[0].zoom === 5, c)
|
|
|
|
reduce = true
|
|
c = run(() => fly.flyTo([1, 2], { zoom: 4 }))
|
|
check('reduced motion: flyTo becomes jumpTo', c.length === 1 && c[0].fn === 'jumpTo' && c[0].a[0].zoom === 4, c)
|
|
c = run(() => fly.flyToCoords({ longitude: 1, latitude: 2 }))
|
|
check('reduced motion: flyToCoords becomes jumpTo', c.length === 1 && c[0].fn === 'jumpTo', c)
|
|
c = run(() => fly.fitBounds(B))
|
|
check('reduced motion: fitBounds is instant (animate:false, duration 0)', c[0]?.fn === 'fitBounds' && c[0].a[1].animate === false && c[0].a[1].duration === 0, c)
|
|
c = run(() => fly.resetView())
|
|
check('reduced motion: resetView makes no flyTo/easeTo', !c.some((x) => x.fn === 'flyTo' || x.fn === 'easeTo'), c)
|
|
|
|
if (bad) { console.log(`MAP-FLY-REDUCED-MOTION: FAIL — ${bad} case(s).`); process.exit(1) }
|
|
console.log('MAP-FLY-REDUCED-MOTION: PASS — every camera move in useMapFly is instant under reduced motion; caller options reach flyToCoords.')
|