mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
release: v0.1.0 — one-click install, keyless boot, in-app Provider Settings (#142)
The first formal release. - One-click install via Pinokio; keyless boot lands on a live Esri World Imagery satellite globe with keyless terrain, with automatic OSM fallback and graceful degradation when terrain is unavailable. - Provider Settings (the POWER UP panel): add, replace, or remove API keys inside the app; credential files made owner-only before any secret is written; external keys shown read-only; the panel refuses shared or proxied servers. - Keyless capability responses for the optional HUD summary and place search. - Aircraft-identity voice answers cover operator, type, and route, and say so plainly when enrichment is unavailable. - README rewritten keyless-first; concise 0.1.0 changelog section; CI workflow included. Gates: 2,672 unit tests pass / 0 fail, build clean, tracking regression 108/108, map-source tray QA pass, setup doctor ready.
This commit is contained in:
1 parent
6d83bb6008
commit
b6da93b8ac
170 files changed
+5800
-853
No files matched your search
+56
-12
@@ -1,8 +1,8 @@
|
||||
// MAP STACK chip row — the dropdown's replacement control surface.
|
||||
//
|
||||
// The product issue was two clicks (open panel → open dropdown) to change
|
||||
// The owner's complaint was two clicks (open panel → open dropdown) to change
|
||||
// basemap. These tests pin the three things that make the row a faithful swap:
|
||||
// it projects the accepted four-source allowlist from the controller's
|
||||
// it projects the owner-approved four-source allowlist from the controller's
|
||||
// stack data, a click dispatches the same selection the `change` handler used
|
||||
// to, and the lit chip tracks controller state rather than the click. Run with:
|
||||
// npm test
|
||||
@@ -66,20 +66,21 @@ const CONTROLLER_STACKS = [
|
||||
{ id: 'photoreal', label: 'Google 3D', requiresIon: false, available: true, unavailableReason: null },
|
||||
{ id: 'bing-aerial', label: 'Bing Aerial', requiresIon: true, available: true, unavailableReason: null },
|
||||
{ id: 'bing-labels', label: 'Bing Labels', requiresIon: true, available: true, unavailableReason: null },
|
||||
{ id: 'esri-imagery', label: 'Esri Satellite', requiresIon: false, available: true, unavailableReason: null },
|
||||
{ id: 'osm', label: 'OSM', requiresIon: false, available: true, unavailableReason: null },
|
||||
];
|
||||
|
||||
test('the row renders exactly the four accepted sources', () => {
|
||||
test('the row renders exactly the five owner-approved sources', () => {
|
||||
const container = makeElement();
|
||||
renderMapStackChips(container, CONTROLLER_STACKS, { activeId: 'photoreal', doc });
|
||||
|
||||
assert.deepEqual(container.children.map((chip) => chip.dataset.stackId), [
|
||||
'photoreal', 'bing-aerial', 'bing-labels', 'osm',
|
||||
'photoreal', 'bing-aerial', 'bing-labels', 'esri-imagery', 'osm',
|
||||
]);
|
||||
assert.deepEqual(container.children.map(chipText), [
|
||||
'Google 3D', 'Bing Aerial', 'Bing Labels', 'OSM',
|
||||
'Google 3D', 'Bing Aerial', 'Bing Labels', 'Esri Satellite', 'OSM',
|
||||
]);
|
||||
assert.deepEqual(PRESENTED_MAP_STACK_IDS, ['photoreal', 'bing-aerial', 'bing-labels', 'osm']);
|
||||
assert.deepEqual(PRESENTED_MAP_STACK_IDS, ['photoreal', 'bing-aerial', 'bing-labels', 'esri-imagery', 'osm']);
|
||||
assert.ok(container.children.every((chip) => chip.tagName === 'button' && chip.type === 'button'));
|
||||
assert.ok(container.children.every((chip) => chip.classList.contains(MAP_STACK_CHIP_CLASS)));
|
||||
});
|
||||
@@ -87,11 +88,11 @@ test('the row renders exactly the four accepted sources', () => {
|
||||
test('internal and future stacks stay outside the approved presentation set', () => {
|
||||
const container = makeElement();
|
||||
// A future Hybrid stack may land in the controller, but it must not appear
|
||||
// until the accepted presentation allowlist explicitly includes it.
|
||||
// until the owner-approved presentation allowlist explicitly includes it.
|
||||
const withHybrid = [...CONTROLLER_STACKS, { id: 'hybrid', label: 'Hybrid', available: true }];
|
||||
renderMapStackChips(container, withHybrid, { activeId: 'photoreal', doc });
|
||||
|
||||
assert.equal(container.children.length, 4);
|
||||
assert.equal(container.children.length, 5);
|
||||
assert.doesNotMatch(container.children.map(chipText).join(' '), /Hybrid/);
|
||||
});
|
||||
|
||||
@@ -112,9 +113,10 @@ test('clicking a chip dispatches that stack id — the same selection the dropdo
|
||||
doc,
|
||||
});
|
||||
|
||||
container.children[4].click();
|
||||
container.children[3].click();
|
||||
container.children[1].click();
|
||||
assert.deepEqual(selected, ['osm', 'bing-aerial']);
|
||||
assert.deepEqual(selected, ['osm', 'esri-imagery', 'bing-aerial']);
|
||||
});
|
||||
|
||||
test('the active chip is the pressed chip, and exactly one is pressed', () => {
|
||||
@@ -136,12 +138,12 @@ test('the lit chip tracks controller state, not the click', () => {
|
||||
// A rejected/superseded switch reports the stack that is genuinely active.
|
||||
syncMapStackChips(container, 'photoreal');
|
||||
assert.ok(container.children[0].classList.contains('active'));
|
||||
assert.equal(container.children[3].getAttribute('aria-pressed'), 'false');
|
||||
assert.equal(container.children[4].getAttribute('aria-pressed'), 'false');
|
||||
|
||||
// A landed switch moves both the class and the pressed state.
|
||||
syncMapStackChips(container, 'osm');
|
||||
assert.ok(container.children[3].classList.contains('active'));
|
||||
assert.equal(container.children[3].getAttribute('aria-pressed'), 'true');
|
||||
assert.ok(container.children[4].classList.contains('active'));
|
||||
assert.equal(container.children[4].getAttribute('aria-pressed'), 'true');
|
||||
assert.ok(!container.children[0].classList.contains('active'));
|
||||
assert.equal(container.children[0].getAttribute('aria-pressed'), 'false');
|
||||
});
|
||||
@@ -354,4 +356,46 @@ test('the Visual Presets tray owns Map Source and the retired left panel is abse
|
||||
/_renderMapStackState\(state\) \{[\s\S]*?syncMapStackChips\(this\._mapStackChips, state\.activeId\)/,
|
||||
'the active chip must be re-synced from controller state',
|
||||
);
|
||||
assert.match(
|
||||
ui,
|
||||
/window\.addEventListener\('gev:map-stack-changed', this\._mapStackChangeHandler\)/,
|
||||
'provider-driven fallback must re-sync the UI without a user click',
|
||||
);
|
||||
assert.match(
|
||||
ui,
|
||||
/window\.removeEventListener\('gev:map-stack-changed', this\._mapStackChangeHandler\)/,
|
||||
'the provider-driven state listener must be released with StyleManager',
|
||||
);
|
||||
});
|
||||
|
||||
test('Esri fallbacks report and attribute the imagery source actually rendered', () => {
|
||||
const controller = readFileSync(new URL('./mapStackController.js', import.meta.url), 'utf8');
|
||||
assert.match(
|
||||
controller,
|
||||
/effectiveStackId = 'osm';[\s\S]*?fallbackMessage = 'Esri Satellite is unavailable; using OSM'/,
|
||||
'construction failure must resolve truthfully to OSM',
|
||||
);
|
||||
assert.match(
|
||||
controller,
|
||||
/this\._activeId = activation\?\.effectiveStackId \|\| stack\.id/,
|
||||
'the active chip must follow the effective provider, not the requested stack',
|
||||
);
|
||||
assert.match(
|
||||
controller,
|
||||
/this\._syncEsriAttribution\(resolution\.effectiveStackId\)/,
|
||||
'Esri credit must follow the effective provider',
|
||||
);
|
||||
});
|
||||
|
||||
test('repeated active Esri tile failures fall back to OSM and one transient does not', () => {
|
||||
const controller = readFileSync(new URL('./mapStackController.js', import.meta.url), 'utf8');
|
||||
assert.match(controller, /let failures = 0/);
|
||||
assert.match(controller, /if \(failures < 2 \|\| this\._esriFallbackPending\) return/);
|
||||
assert.match(controller, /this\.setStack\('osm', \{ silent: true \}\)/);
|
||||
assert.match(controller, /state\?\.activeId === 'osm'[\s\S]*?this\._emitChange\('error'\)/);
|
||||
assert.match(
|
||||
controller,
|
||||
/gen !== this\._switchGen \|\| this\._activeImageryProvider !== resolution\.provider/,
|
||||
'a stale provider error must not replace a newer user selection',
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user