Merge branch 'main' into feat/bikeshare-norway

This commit is contained in:
Said Turksever authored and GitHub committed 2026-10-15 20:04:57 +01:00
commit 09bdc105a6
21 files changed
+755 -45

No files matched your search

+28
View File
@@ -26,6 +26,7 @@ import {
validMilitaryInstallationBox,
writeMilitaryInstallationDisk,
} from '../../vite.config.js';
import { resolveOverpassUpstreamTag } from '../../server/providers/overpass/constants.js';
const DAY_MS = 86_400_000;
test('installation failure reasons disclose no raw upstream error and do not guess overload', () => {
@@ -274,3 +275,30 @@ test('an unwritable cache directory degrades to a miss instead of throwing', asy
await fsp.rm(dir, { recursive: true, force: true });
}
});
test('an installation entry is not served after OVERPASS_UPSTREAMS is repointed', async (t) => {
const prior = process.env.OVERPASS_UPSTREAMS;
t.after(() => {
if (prior === undefined) delete process.env.OVERPASS_UPSTREAMS;
else process.env.OVERPASS_UPSTREAMS = prior;
});
const dir = tempCacheDir();
const key = '30.250,-97.750,30.300,-97.700';
try {
process.env.OVERPASS_UPSTREAMS = 'https://a.example/api/interpreter,https://b.example/api/interpreter';
const tag = resolveOverpassUpstreamTag();
await writeMilitaryInstallationDisk(key, { ...entry(Date.now()), upstreams: tag }, dir);
assert.ok(await readMilitaryInstallationDisk(key, TTL_MS, dir), 'its own entry is a hit');
process.env.OVERPASS_UPSTREAMS = 'https://b.example/api/interpreter,https://a.example/api/interpreter';
assert.equal(resolveOverpassUpstreamTag(), tag, 'reordering the same instances keeps the tag');
process.env.OVERPASS_UPSTREAMS = 'https://c.example/api/interpreter';
assert.equal(await readMilitaryInstallationDisk(key, TTL_MS, dir), null, 'fresh read refused');
assert.equal(await readMilitaryInstallationDisk(key, Infinity, dir), null, 'stale read refused');
await writeMilitaryInstallationDisk('legacy', entry(Date.now()), dir);
assert.equal(await readMilitaryInstallationDisk('legacy', Infinity, dir), null, 'untagged entry refused');
delete process.env.OVERPASS_UPSTREAMS;
assert.ok(await readMilitaryInstallationDisk(key, Infinity, dir), 'nothing configured accepts any entry');
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
+19 -4
View File
@@ -296,6 +296,24 @@ function imageryPinOption(key, token) {
});
}
function satelliteFilterOption() {
const percentage = boundedIntegerOption('infrared', 'i', 100, {
min: 0,
max: 100,
});
return Object.freeze({
...percentage,
normalize: (value) =>
value === 'filtered'
? 100
: value === 'full'
? 0
: percentage.normalize(value),
decode: (value) =>
value === 'f' ? 100 : value === 'a' ? 0 : percentage.decode(value),
});
}
const OPTION_GROUPS = Object.freeze({
traffic: Object.freeze([
enumOption('roadMode', 'r', null, ['tomtom', 'osm', 'hybrid'], {
@@ -317,10 +335,7 @@ const OPTION_GROUPS = Object.freeze({
}),
]),
'weather-satellite': Object.freeze([
enumOption('infrared', 'i', 'filtered', ['filtered', 'full'], {
filtered: 'f',
full: 'a',
}),
satelliteFilterOption(),
enumOption('opacity', 'o', 'strong', ['light', 'strong'], {
light: 'l',
strong: 's',
+56 -8
View File
@@ -2422,23 +2422,74 @@ test('wind appearance shares round trip while old links retain weather defaults'
assert.deepEqual(invalid.options.wind, defaults);
});
test('observed weather round trips product and opacity without persisting historical playback', () => {
test('observed weather round trips product and presets without persisting historical playback', () => {
const state = normalizeLayerState({
enabledLayerIds: ['weather-radar', 'weather-satellite'],
options: {
'weather-radar': { opacity: 'light', play: true },
'weather-satellite': { product: 'clouds', opacity: 'light', step: -1 },
'weather-satellite': {
product: 'clouds',
opacity: 'light',
infrared: 'filtered',
step: -1,
},
},
});
const params = new URLSearchParams(encode(state));
const decoded = decodeLayerStateParams(params);
assert.deepEqual(decoded, state);
assert.equal(state.options['weather-satellite'].product, 'clouds');
assert.equal(state.options['weather-satellite'].opacity, 'light');
assert.equal(state.options['weather-satellite'].infrared, 100);
assert.equal(Object.hasOwn(state.options['weather-radar'], 'play'), false);
});
test('satellite infrared display mode round trips and invalid or absent values use filtered', () => {
for (const infrared of ['full', 'filtered', undefined, 'invalid']) {
test('satellite filter strength percentages round-trip and legacy mode codes remain readable', () => {
const state = normalizeLayerState({
enabledLayerIds: ['weather-satellite'],
options: { 'weather-satellite': { infrared: 53, opacity: 'light' } },
});
const params = encodeLayerStateParams(
new URLSearchParams([['v', '2']]),
state,
);
assert.deepEqual(decodeLayerStateParams(params), state);
assert.equal(state.options['weather-satellite'].infrared, 53);
assert.equal(state.options['weather-satellite'].opacity, 'light');
for (const [legacy, expected] of [
['f', 100],
['a', 0],
]) {
const decoded = decodeLayerStateParams(
new URLSearchParams(`v=2&l=o&lo=o.i.${legacy}`),
);
assert.equal(decoded.options['weather-satellite'].infrared, expected);
}
for (const [legacy, expected] of [
['filtered', 100],
['full', 0],
]) {
const normalized = normalizeLayerState({
enabledLayerIds: ['weather-satellite'],
options: { 'weather-satellite': { infrared: legacy } },
});
assert.equal(normalized.options['weather-satellite'].infrared, expected);
}
const invalid = normalizeLayerState({
enabledLayerIds: ['weather-satellite'],
options: { 'weather-satellite': { infrared: 101 } },
});
assert.equal(invalid.options['weather-satellite'].infrared, 100);
});
test('satellite cloud filter round trips and invalid or absent values default to Clouds only', () => {
for (const [infrared, expected] of [
['full', 0],
['filtered', 100],
[53, 53],
[undefined, 100],
['invalid', 100],
]) {
const state = normalizeLayerState({
enabledLayerIds: ['weather-satellite'],
options: {
@@ -2454,10 +2505,7 @@ test('satellite infrared display mode round trips and invalid or absent values u
decodeLayerStateParams(new URLSearchParams(encode(state))),
state,
);
assert.equal(
state.options['weather-satellite'].infrared,
infrared === 'full' ? 'full' : 'filtered',
);
assert.equal(state.options['weather-satellite'].infrared, expected);
assert.equal(
Object.hasOwn(state.options['weather-satellite'], 'step'),
false,