Merge main into feat/shipwrecks

Main added the News layer at the same places: both layers are kept in the
layer names, panel order (News stays last of Events), standalone sources,
voice manifest, credits, DATA_SOURCES and the CURRENT-STATE table. News took
share-link token 00 first, so Shipwrecks moves to 01 (ledger, registry,
CURRENT-STATE and the token tests). The catalog now has 40 layers and the
share-link registry 38. Shipwreck strings are added to the new Hebrew
catalog; the other catalogs keep both sides' strings.
This commit is contained in:
Sameh Khamis committed 2026-11-10 14:03:39 -08:00
commit 8ff22f1a12
466 files changed
+57748 -1865

No files matched your search

+30 -1
View File
@@ -37,7 +37,7 @@ test('every acquisition source can be omitted without losing catalog membership'
test('all acquisition sources may be absent, and enable fails before initializing or fetching', async (t) => {
const actual = catalog({}, t);
assert.equal(actual.layers.length, 39);
assert.equal(actual.layers.length, 40);
const manager = new LayerLifecycle(
{},
{ getSourceAvailability: actual.getSourceAvailability },
@@ -150,6 +150,35 @@ test('GhostMaps obeys source omission, replacement and explicit removal', async
assert.equal(fetches, 0);
});
test('News is unavailable without a source and the standalone default reads only same-origin /api/news', async (t) => {
const missing = catalog({}, t);
assert.equal(missing.getSourceAvailability('news')?.available, false);
const manager = new LayerLifecycle(
{},
{ getSourceAvailability: missing.getSourceAvailability },
);
manager.register(missing.get('news'));
assert.equal(await manager.setEnabled('news', true), false);
assert.equal(manager.layers.get('news').initialized, false);
assert.equal(createStandaloneLayerSources({ news: null }).news, null);
const urls = [];
t.mock.method(globalThis, 'fetch', async (url) => {
urls.push(url);
return new Response(
JSON.stringify({
error: 'news_not_configured',
unavailable: true,
retryable: false,
}),
{ status: 503 },
);
});
const standalone = createStandaloneLayerSources().news;
await assert.rejects(standalone.getHotspots(), { unavailable: true });
assert.deepEqual(urls, ['/api/news/hotspots']);
});
test('empty Street Level uses the shared unavailable lifecycle without initialization', async (t) => {
const actual = catalog({}, t);
const manager = new LayerLifecycle(