Amélioration avec des fonctions d'un vrai dashboard automotive et containerisation du projet pour faciliter le déploiement
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createServices } from './services.mjs';
|
||||
import { distance, validateZones, nearbyZones, routeProgress, instruction } from '../ui/geo.js';
|
||||
import { palette } from '../ui/theme.js';
|
||||
|
||||
test('geographic distances, segment projection and French instructions', () => {
|
||||
assert.equal(distance({lat:48,lon:2},{lat:48,lon:2}), 0);
|
||||
assert.ok(Math.abs(distance({lat:0,lon:0},{lat:0,lon:1}) - 111195) < 1);
|
||||
const p = routeProgress([[2,48],[2.1,48]], {lon:2.05,lat:48});
|
||||
assert.ok(p.away < 1 && Math.abs(p.fraction - .5) < .001);
|
||||
assert.match(instruction({maneuver:{type:'turn',modifier:'left'},name:'Rue A'}), /gauche.*Rue A/);
|
||||
});
|
||||
const now = Date.UTC(2026,8,12);
|
||||
const collection = {type:'FeatureCollection',features:[{type:'Feature',geometry:{type:'Point',coordinates:[2,48]},properties:{id:'a',country:'FR',radiusM:1000,source:'Test',updatedAt:'2026-09-01',expiresAt:'2026-10-01'}}]};
|
||||
test('zone validation and alerts exclude expired, foreign, stale and inaccurate positions', () => {
|
||||
const zones = validateZones(collection);
|
||||
const gps = {lat:48,lon:2,source:'gps',accuracy:10,timestamp:now};
|
||||
assert.equal(nearbyZones(zones,gps,'FR',now).length,1);
|
||||
for (const change of [{source:'manual'},{accuracy:200},{timestamp:now-16000}]) assert.equal(nearbyZones(zones,{...gps,...change},'FR',now).length,0);
|
||||
assert.equal(nearbyZones(zones,gps,'BE',now).length,0);
|
||||
assert.equal(nearbyZones(zones,{...gps,timestamp:now+40*86400000},'FR',now+40*86400000).length,0);
|
||||
assert.throws(()=>validateZones({type:'FeatureCollection',features:[{}]}));
|
||||
const invalid = structuredClone(collection); invalid.features[0].properties.radiusM = 0;
|
||||
assert.throws(()=>validateZones(invalid));
|
||||
});
|
||||
test('custom extreme colors are adjusted for light and dark contrast', () => {
|
||||
assert.notEqual(palette('#ffffff',true).accent,'#ffffff');
|
||||
assert.notEqual(palette('#000000',false).accent,'#000000');
|
||||
assert.equal(palette('invalid').accent,palette('#d2ef92').accent);
|
||||
});
|
||||
test('weather cache, coordinate validation, upstream errors, search normalization', async () => {
|
||||
let calls = 0, time = 100000;
|
||||
const service = createServices({now:()=>time,env:{},fetcher:async url=>{
|
||||
calls++;
|
||||
if (url.hostname.includes('photon')) return {ok:true,json:async()=>({features:[{geometry:{type:'Point',coordinates:[2,48]},properties:{name:'Paris',city:'Paris',country:'France'}}]})};
|
||||
return {ok:true,json:async()=>({current:{temperature_2m:20,wind_speed_10m:5,weather_code:0,time:'2026-09-12T12:00'},daily:{temperature_2m_min:[12],temperature_2m_max:[22]}})};
|
||||
}});
|
||||
const params = new URLSearchParams({lat:'48',lon:'2'});
|
||||
const responses = await Promise.all([service('/api/weather',params),service('/api/weather',params)]);
|
||||
assert.equal(responses[0].temperature,20); assert.equal(calls,1);
|
||||
await service('/api/weather',params); assert.equal(calls,1);
|
||||
await assert.rejects(service('/api/weather',new URLSearchParams({lat:'',lon:'2'})),{status:400});
|
||||
await assert.rejects(service('/api/weather',new URLSearchParams({lat:'91',lon:'2'})),{status:400});
|
||||
await assert.rejects(service('/api/weather',new URLSearchParams({lat:'49',lon:'2'})),{status:429});
|
||||
time += 2000;
|
||||
const places = await service('/api/search',new URLSearchParams({q:'Paris'}));
|
||||
assert.equal(places[0].label,'Paris, France');
|
||||
const broken = createServices({env:{},fetcher:async()=>{throw new Error('Offline');}});
|
||||
await assert.rejects(broken('/api/weather',params),{status:502});
|
||||
});
|
||||
test('routing coordinates and NoRoute response are handled', async () => {
|
||||
let target;
|
||||
const service = createServices({env:{},fetcher:async url=>{target=url;return {ok:true,json:async()=>({code:'NoRoute'})};}});
|
||||
await assert.rejects(service('/api/route',new URLSearchParams({fromLat:'48',fromLon:'2',toLat:'49',toLon:'3'})),{status:422});
|
||||
assert.match(target.pathname,/2,48;3,49$/);
|
||||
});
|
||||
Reference in New Issue
Block a user