mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
Bins airborne ADS-B v1/v2 aircraft that report degraded navigation integrity (NIC < 7, NACp < 8, or readsb's GPS-loss flag) into 0.5 degree cells over a rolling 30-minute window, coloured with the gpsjam.org bands. Keyless: reads the capped adsb.lol point snapshot around the view through /api/gnss-integrity, which returns integrity fields only, caches 60 s per whole-degree anchor, backs off on upstream 429 and serves the last snapshot on failure. Adds scripts/qa-gnss.mjs. Built by the Hex project (Crew Leo Agile dev team). Co-Authored-By: Claude <[email protected]>
173 lines
6.2 KiB
JavaScript
173 lines
6.2 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { writeFile, rm } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { build, createServer, preview } from 'vite';
|
|
import { localProviderPlugins } from '../../server/providers/local.js';
|
|
import { apiNotFoundPlugin } from '../../server/standalone/api-not-found.js';
|
|
import { makeFixtureRoot } from './fixtureRoot.mjs';
|
|
|
|
test('data providers have both hooks; credential editing stays development-only', () => {
|
|
const plugins = localProviderPlugins();
|
|
assert.ok(plugins.some(({ name }) => name === 'fire-perimeters'));
|
|
assert.ok(plugins.some(({ name }) => name === 'gnss-integrity'));
|
|
for (const plugin of plugins) {
|
|
if (plugin.name === 'gev-key-setup') {
|
|
assert.equal(plugin.configurePreviewServer, undefined);
|
|
assert.equal(
|
|
plugin.apply({}, { command: 'serve', isPreview: true }),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
plugin.apply({}, { command: 'serve', isPreview: false }),
|
|
true,
|
|
);
|
|
continue;
|
|
}
|
|
assert.equal(typeof plugin.configureServer, 'function', plugin.name);
|
|
assert.equal(typeof plugin.configurePreviewServer, 'function', plugin.name);
|
|
}
|
|
});
|
|
|
|
test('real dev and built-preview servers serve provider JSON and terminate unknown APIs', async (t) => {
|
|
// Physical path: Vite's root and the files written under it must agree on one
|
|
// spelling, and macOS reaches the temp directory through a symlink.
|
|
const root = await makeFixtureRoot('gev-preview-');
|
|
t.after(() => rm(root, { recursive: true, force: true }));
|
|
await writeFile(
|
|
path.join(root, 'index.html'),
|
|
'<!doctype html><title>Preview fixture</title><p>Built application</p>',
|
|
);
|
|
for (const [name, value] of Object.entries({
|
|
AISSTREAM_API_KEY: '',
|
|
FIRMS_MAP_KEY: '',
|
|
FIRMS_API_KEY: '',
|
|
TOMTOM_API_KEY: '',
|
|
GOOGLE_MAPS_API_KEY: '',
|
|
GOOGLE_MAPS_SERVER_API_KEY: '',
|
|
MAPILLARY_CLIENT_TOKEN: '',
|
|
OPENAI_API_KEY: '',
|
|
OPENSKY_AUTH_MODE: 'anon',
|
|
OPENSKY_CLIENT_ID: '',
|
|
OPENSKY_CLIENT_SECRET: '',
|
|
CCTV_FORCE_AUSTIN: '0',
|
|
CCTV_SOURCES_FILE: path.join(root, 'absent.json'),
|
|
CCTV_SOURCES_JSON: JSON.stringify([
|
|
{ id: 'fixture', lat: 30.27, lon: -97.74 },
|
|
]),
|
|
})) {
|
|
const before = process.env[name];
|
|
process.env[name] = value;
|
|
t.after(() => {
|
|
if (before === undefined) delete process.env[name];
|
|
else process.env[name] = before;
|
|
});
|
|
}
|
|
const nativeFetch = globalThis.fetch;
|
|
t.mock.method(globalThis, 'fetch', async (raw, options) => {
|
|
const url = new URL(raw);
|
|
if (url.hostname === '127.0.0.1') return nativeFetch(raw, options);
|
|
assert.ok(
|
|
['opensky-network.org', 'api.adsb.lol'].includes(url.hostname),
|
|
url.origin,
|
|
);
|
|
return Response.json({
|
|
time: Math.floor(Date.now() / 1000),
|
|
states: [],
|
|
ac: [],
|
|
});
|
|
});
|
|
const base = {
|
|
root,
|
|
configFile: false,
|
|
envFile: false,
|
|
publicDir: false,
|
|
logLevel: 'silent',
|
|
};
|
|
await build(base);
|
|
for (const isPreview of [false, true]) {
|
|
const config = {
|
|
...base,
|
|
plugins: [...localProviderPlugins(), apiNotFoundPlugin()],
|
|
server: { host: '127.0.0.1', port: 0, hmr: false },
|
|
preview: { host: '127.0.0.1', port: 0 },
|
|
};
|
|
const server = isPreview
|
|
? await preview(config)
|
|
: await createServer(config);
|
|
if (!isPreview) await server.listen();
|
|
const origin = `http://127.0.0.1:${server.httpServer.address().port}`;
|
|
try {
|
|
for (const [route, status] of [
|
|
['/api/flights', 200],
|
|
['/api/military', 200],
|
|
['/api/adsbdb/type/invalid', 400],
|
|
['/api/firms/status', 200],
|
|
['/api/fire-perimeters/inciweb/publication/invalid', 400],
|
|
['/api/gnss-integrity?lat=invalid', 400],
|
|
['/api/terrain/heights?points=invalid', 400],
|
|
['/api/overpass', 405],
|
|
['/api/overpass/status', 200],
|
|
['/api/cctv/sources', 200],
|
|
['/api/gbfs/', 400],
|
|
['/api/tomtom/status', 200],
|
|
// The Street Level QA gate intercepts these in the browser; this is
|
|
// the check that the real servers register them.
|
|
['/api/mapillary/status', 200],
|
|
['/api/mapillary/tiles/coverage/14/1/2', 503],
|
|
['/api/radio/unknown', 404],
|
|
['/api/setup/status', isPreview ? 404 : 200],
|
|
['/api/setup/update', 404],
|
|
['/api/does-not-exist', 404],
|
|
['/api', 404],
|
|
]) {
|
|
const response = await fetch(origin + route);
|
|
assert.equal(
|
|
response.status,
|
|
status,
|
|
`${isPreview ? 'preview' : 'dev'} ${route}`,
|
|
);
|
|
assert.match(
|
|
response.headers.get('content-type'),
|
|
/application\/json/,
|
|
route,
|
|
);
|
|
const body = await response.json();
|
|
if (route === '/api/cctv/sources')
|
|
assert.equal(body.sources[0].id, 'fixture');
|
|
if (route === '/api/mapillary/status')
|
|
assert.deepEqual(body, { configured: false }, route);
|
|
if (route.startsWith('/api/mapillary/tiles'))
|
|
assert.deepEqual(body, { error: 'no_key', keyRequired: true }, route);
|
|
if (
|
|
route === '/api/does-not-exist' ||
|
|
(isPreview && route.startsWith('/api/setup'))
|
|
) {
|
|
assert.deepEqual(body, { error: 'Unknown API route' });
|
|
assert.equal(response.headers.get('cache-control'), 'no-store');
|
|
}
|
|
}
|
|
const tle = await fetch(origin + '/api/celestrak/invalid!');
|
|
assert.equal(tle.status, 400);
|
|
assert.equal(await tle.text(), 'invalid group');
|
|
if (isPreview) {
|
|
const write = await fetch(origin + '/api/setup/keys', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ GOOGLE_MAPS_API_KEY: 'must-not-save' }),
|
|
});
|
|
assert.equal(write.status, 404);
|
|
assert.deepEqual(await write.json(), { error: 'Unknown API route' });
|
|
}
|
|
for (const route of ['/', '/application-route', '/apiary']) {
|
|
const response = await fetch(origin + route);
|
|
assert.equal(response.status, 200);
|
|
assert.match(response.headers.get('content-type'), /text\/html/);
|
|
assert.match(await response.text(), /Built application/);
|
|
}
|
|
} finally {
|
|
await server.close();
|
|
}
|
|
}
|
|
});
|