tighten the remaining voice outline review items

- One place-name key for server and tiles, so "St. Paul" and "Saint Paul"
  agree in Nominatim name checks.
- Tile street names: a lone letter is a direction only beside another name
  word ("E Street" is not "East Street"), and a trailing quadrant ("E St NW")
  may go unsaid in the ask.
- A building cut at the tile edge that is nearer the point than any whole
  one leaves the point instead of a farther neighbour standing in; an edge
  without a tile buffer counts as a cut, so a cut area never answers grounds.
- A batch building install re-judges only results that installed; a late
  timeout during caption conversion keeps the pending point drawn; a failed
  plain recaption keeps the old mark addressable.
- An interrupted Nominatim dispatch is reclaimed by the next lock owner ten
  minutes after the start its marker names; node:sqlite loads on first use
  without its experimental warning.
- PHOTON_URL accepts only https, which the page's connect-src allows.
- Shared OpenFreeMap tiles decode each layer when a consumer first selects
  it; outline selection reuses the shared ring area and simplification, and
  ground probes the shared ring centroid; the grounds word list lives once.
This commit is contained in:
Sameh Khamis committed 2026-11-02 08:50:05 -08:00
1 parent a38a065c5c
commit a61d0f4c2a
24 files changed
+422 -128

No files matched your search

@@ -407,6 +407,38 @@ test('a persistence failure after fetch invocation aborts it and blocks restarts
assert.equal(calls.length, 1);
assert.deepEqual(markers(), orphan);
assert.equal(createGateStateStore({ file }).count('2026-09-29'), 1);
// Long past any request's timeout, the next lock owner reclaims it.
clock += 10 * 60_000;
const resumed = make(async (url) => {
calls.push(url);
return json([]);
});
assert.deepEqual(
await resumed.requestJson((endpoint) => `${endpoint}?q=z`),
[],
);
assert.equal(calls.length, 2);
assert.deepEqual(markers(), []);
assert.equal(createGateStateStore({ file }).count('2026-09-29'), 2);
});
test('a dispatch marker that names no start keeps refusing', async (t) => {
const file = path.join(tempDir(t), 'state.json');
fs.writeFileSync(`${file}.dispatch.123.456`, '');
const gate = createNominatimGate({
settings: PUBLIC,
usage: createGateStateStore({ file, onError: () => {} }),
now: () => Date.UTC(2026, 8, 29, 12),
sleep: async () => {},
fetchImpl: async () =>
assert.fail('no request while a dispatch is unfinished'),
});
await assert.rejects(
gate.requestJson((endpoint) => `${endpoint}?q=x`),
{
code: 'NOMINATIM_STATE_UNAVAILABLE',
},
);
});
test('parseable but invalid public usage state fails closed', async (t) => {
@@ -719,6 +719,11 @@ test('names are normalized Unicode-aware so small differences share an entry', (
'non-Latin names survive',
);
assert.equal(normalizePlaceName('Central Park'), 'central park');
// One key with the bundled place packs and tile street matching.
assert.equal(
normalizePlaceName('Saint Paul'),
normalizePlaceName('St. Paul'),
);
});
test('small view changes reuse one cached outline', async (t) => {
+7
View File
@@ -89,6 +89,13 @@ test('explicit build inputs preserve browser-only defines, plugin order and loop
'null',
'credentials are never serialized into browser assets',
);
assert.equal(
createBrowserViteConfig({ photonUrl: 'http://localhost:2322/api/' }).define[
'import.meta.env.PHOTON_URL'
],
'null',
'plain http would be blocked by connect-src, so it is refused here',
);
assert.equal(
createBrowserViteConfig({ mapillaryToken: 'MLY|1|abc' }).define[
'import.meta.env.MAPILLARY_CLIENT_TOKEN'