mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
311 lines
12 KiB
JavaScript
311 lines
12 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import path from 'node:path';
|
|
import {
|
|
buildCapabilitySummary,
|
|
CREDENTIALS,
|
|
classifyNodeVersion,
|
|
formatSetupReport,
|
|
hasRequiredDependencies,
|
|
isConfiguredValue,
|
|
npmProcessSpec,
|
|
readDoctorDotenvValue,
|
|
resolveOpenSkyAuthMode,
|
|
resolveCredential,
|
|
} from '../scripts/setup-doctor.mjs';
|
|
|
|
const credential = (name) => CREDENTIALS.find((spec) => spec.name === name);
|
|
|
|
test('doctor distinguishes supported, usable EOL, and unsupported Node versions', () => {
|
|
assert.equal(classifyNodeVersion('24.14.0').level, 'ok');
|
|
assert.equal(classifyNodeVersion('26.1.0').level, 'ok');
|
|
assert.equal(classifyNodeVersion('25.6.1').level, 'warn');
|
|
assert.match(classifyNodeVersion('25.6.1').summary, /usable but EOL/);
|
|
assert.equal(classifyNodeVersion('22.0.0').level, 'error');
|
|
// A FUTURE Node is a warning, never an install-bricking refusal: the
|
|
// no-terminal user it would stop cannot act on "install Node 24".
|
|
assert.equal(classifyNodeVersion('27.0.0').level, 'warn');
|
|
assert.match(classifyNodeVersion('27.0.0').summary, /newer than this release has verified/);
|
|
});
|
|
|
|
test('doctor rejects an empty node_modules and requires every direct package', () => {
|
|
const root = mkdtempSync(path.join(tmpdir(), 'gev-doctor-deps-'));
|
|
try {
|
|
writeFileSync(path.join(root, 'package.json'), JSON.stringify({
|
|
dependencies: { vite: '1.0.0' },
|
|
devDependencies: { '@scope/tool': '1.0.0' },
|
|
}));
|
|
mkdirSync(path.join(root, 'node_modules'));
|
|
assert.equal(hasRequiredDependencies(root), false);
|
|
|
|
for (const packagePath of ['vite', '@scope/tool']) {
|
|
const directory = path.join(root, 'node_modules', ...packagePath.split('/'));
|
|
mkdirSync(directory, { recursive: true });
|
|
writeFileSync(path.join(directory, 'package.json'), '{}');
|
|
}
|
|
assert.equal(hasRequiredDependencies(root), true);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('placeholder values are never counted as configured credentials', () => {
|
|
assert.equal(isConfiguredValue(''), false);
|
|
assert.equal(isConfiguredValue('your_google_maps_api_key_here'), false);
|
|
assert.equal(isConfiguredValue('replace_me'), false);
|
|
assert.equal(isConfiguredValue('configured-value'), true);
|
|
});
|
|
|
|
test('doctor selects a Windows-safe npm process without changing Unix behavior', () => {
|
|
assert.deepEqual(npmProcessSpec('win32'), { command: 'npm.cmd', shell: true });
|
|
assert.deepEqual(npmProcessSpec('darwin'), { command: 'npm', shell: false });
|
|
assert.deepEqual(npmProcessSpec('linux'), { command: 'npm', shell: false });
|
|
});
|
|
|
|
test('doctor recognizes every OpenSky OAuth keychain alias used by dev-fresh', () => {
|
|
assert.deepEqual(
|
|
credential('OPENSKY_CLIENT_ID').keychain,
|
|
[
|
|
['opensky-network', 'client_id'],
|
|
['opensky-network', 'client-id'],
|
|
['opensky-network', 'client'],
|
|
['opensky-network', 'api-key'],
|
|
['opensky', 'client_id'],
|
|
['opensky', 'client-id'],
|
|
['opensky', 'client'],
|
|
['opensky', 'api-key'],
|
|
],
|
|
);
|
|
assert.deepEqual(
|
|
credential('OPENSKY_CLIENT_SECRET').keychain,
|
|
[
|
|
['opensky-network', 'client_secret'],
|
|
['opensky-network', 'client-secret'],
|
|
['opensky-network', 'secret'],
|
|
['opensky', 'client_secret'],
|
|
['opensky', 'client-secret'],
|
|
['opensky', 'secret'],
|
|
],
|
|
);
|
|
});
|
|
|
|
test('Pinokio-scoped diagnosis ignores Keychain items its start path does not import', () => {
|
|
const root = mkdtempSync(path.join(tmpdir(), 'gev-pinokio-doctor-'));
|
|
try {
|
|
const spec = credential('OPENAI_API_KEY');
|
|
const keychainLookup = () => true;
|
|
assert.deepEqual(resolveCredential(spec, {
|
|
environment: {},
|
|
rootDir: root,
|
|
keychainLookup,
|
|
}), { configured: true, source: 'macOS Keychain' });
|
|
assert.deepEqual(resolveCredential(spec, {
|
|
includeKeychain: false,
|
|
environment: {},
|
|
rootDir: root,
|
|
keychainLookup,
|
|
}), { configured: false, source: null });
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('Pinokio-scoped diagnosis does not count dotenv values shadowed by blank app fields', () => {
|
|
const root = mkdtempSync(path.join(tmpdir(), 'gev-pinokio-doctor-env-'));
|
|
try {
|
|
const spec = credential('GOOGLE_MAPS_API_KEY');
|
|
writeFileSync(path.join(root, '.env.local'), 'GOOGLE_MAPS_API_KEY=dotenv-only\n');
|
|
assert.deepEqual(resolveCredential(spec, {
|
|
environment: { GOOGLE_MAPS_API_KEY: '' },
|
|
rootDir: root,
|
|
keychainLookup: () => false,
|
|
}), { configured: true, source: 'dotenv files' });
|
|
assert.deepEqual(resolveCredential(spec, {
|
|
authoritativeEnvironment: true,
|
|
environment: { GOOGLE_MAPS_API_KEY: '' },
|
|
rootDir: root,
|
|
keychainLookup: () => false,
|
|
}), { configured: false, source: null });
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('doctor reads the dotenv ladder without requiring Vite to be installed', () => {
|
|
const root = mkdtempSync(path.join(tmpdir(), 'gev-doctor-'));
|
|
try {
|
|
writeFileSync(path.join(root, '.env'), 'GEV_TEST_KEY=base\n');
|
|
writeFileSync(path.join(root, '.env.local'), 'GEV_TEST_KEY=local\n');
|
|
writeFileSync(path.join(root, '.env.development.local'), 'GEV_TEST_KEY=mode-local\n');
|
|
assert.equal(readDoctorDotenvValue('GEV_TEST_KEY', root), 'mode-local');
|
|
assert.equal(readDoctorDotenvValue('not valid', root), '');
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('doctor resolves OpenSky auth mode with launcher-compatible precedence', () => {
|
|
const root = mkdtempSync(path.join(tmpdir(), 'gev-doctor-opensky-mode-'));
|
|
try {
|
|
writeFileSync(path.join(root, '.env'), 'OPENSKY_AUTH_MODE=anon\n');
|
|
assert.equal(resolveOpenSkyAuthMode({ environment: {}, rootDir: root }), 'anon');
|
|
assert.equal(resolveOpenSkyAuthMode({ environment: { OPENSKY_AUTH_MODE: 'oauth' }, rootDir: root }), 'oauth');
|
|
assert.equal(resolveOpenSkyAuthMode({ environment: { OPENSKY_AUTH_MODE: '' }, rootDir: root }), 'anon');
|
|
assert.equal(resolveOpenSkyAuthMode({ environment: { OPENSKY_AUTH_MODE: 'invalid' }, rootDir: root }), 'oauth');
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('doctor reports keyless anonymous OpenSky access for explicit anon mode', () => {
|
|
const credentials = {
|
|
OPENSKY_CLIENT_ID: { configured: true },
|
|
OPENSKY_CLIENT_SECRET: { configured: true },
|
|
};
|
|
assert.equal(
|
|
buildCapabilitySummary(credentials, { openSkyAuthMode: 'anon' }).flights,
|
|
'OpenSky keyless anonymous access (rate-limited)',
|
|
);
|
|
});
|
|
|
|
test('doctor retains OAuth capability wording for a complete client pair', () => {
|
|
const credentials = {
|
|
OPENSKY_CLIENT_ID: { configured: true },
|
|
OPENSKY_CLIENT_SECRET: { configured: true },
|
|
};
|
|
assert.equal(
|
|
buildCapabilitySummary(credentials, { openSkyAuthMode: 'oauth' }).flights,
|
|
'OpenSky OAuth credentials present (runtime mode and validity not verified)',
|
|
);
|
|
});
|
|
|
|
test('doctor reports Basic mode without inferring runtime auth from OAuth credentials', () => {
|
|
const oauthCredentials = {
|
|
OPENSKY_CLIENT_ID: { configured: true },
|
|
OPENSKY_CLIENT_SECRET: { configured: true },
|
|
};
|
|
for (const credentials of [{}, oauthCredentials]) {
|
|
assert.equal(
|
|
buildCapabilitySummary(credentials, { openSkyAuthMode: 'basic' }).flights,
|
|
'OpenSky Basic mode selected (credential presence and validity not verified)',
|
|
);
|
|
}
|
|
});
|
|
|
|
test('doctor reports auto mode without assuming its eventual credential choice', () => {
|
|
const oauthCredentials = {
|
|
OPENSKY_CLIENT_ID: { configured: true },
|
|
OPENSKY_CLIENT_SECRET: { configured: true },
|
|
};
|
|
for (const credentials of [{}, oauthCredentials]) {
|
|
assert.equal(
|
|
buildCapabilitySummary(credentials, { openSkyAuthMode: 'auto' }).flights,
|
|
'OpenSky auto mode selected (runtime credential choice and validity not verified)',
|
|
);
|
|
}
|
|
});
|
|
|
|
test('doctor describes the credential ladder without exposing values', () => {
|
|
const credentials = {
|
|
GOOGLE_MAPS_API_KEY: { configured: false },
|
|
GOOGLE_MAPS_SERVER_API_KEY: { configured: false },
|
|
CESIUM_ION_TOKEN: { configured: true, source: 'environment' },
|
|
OPENAI_API_KEY: { configured: true, source: 'dotenv files' },
|
|
AISSTREAM_API_KEY: { configured: false },
|
|
FIRMS_MAP_KEY: { configured: false },
|
|
TOMTOM_API_KEY: { configured: false },
|
|
OPENSKY_CLIENT_ID: { configured: false },
|
|
OPENSKY_CLIENT_SECRET: { configured: false },
|
|
LL2_API_TOKEN: { configured: true, source: 'environment' },
|
|
};
|
|
const capabilities = buildCapabilitySummary(credentials);
|
|
assert.match(capabilities.map, /Google Photorealistic 3D Tiles through Cesium ion/);
|
|
assert.match(capabilities.map, /Bing and world-terrain stacks/);
|
|
assert.equal(capabilities.voice, 'available');
|
|
assert.match(capabilities.missions, /token allowance/);
|
|
assert.equal(capabilities.flights, 'OpenSky keyless anonymous access (rate-limited)');
|
|
|
|
const report = formatSetupReport({
|
|
ready: true,
|
|
node: { version: '25.6.1', level: 'warn', summary: 'usable but EOL' },
|
|
npm: { available: true, version: '11.0.0' },
|
|
dependenciesInstalled: true,
|
|
credentials,
|
|
capabilities,
|
|
});
|
|
assert.doesNotMatch(report, /configured-value/);
|
|
assert.match(report, /Cesium ion \(environment\)/);
|
|
assert.match(report, /Launch Library 2 \(environment\)/);
|
|
|
|
const pinokioReport = formatSetupReport({
|
|
ready: true,
|
|
node: { version: '24.14.0', level: 'ok', summary: 'supported' },
|
|
npm: { available: true, version: '11.0.0' },
|
|
dependenciesInstalled: true,
|
|
credentials,
|
|
capabilities,
|
|
}, { readyMessage: 'Ready. Return to Pinokio and choose Start.' });
|
|
assert.match(pinokioReport, /Return to Pinokio and choose Start/);
|
|
assert.doesNotMatch(pinokioReport, /npm run dev/);
|
|
});
|
|
|
|
test('doctor sends Keychain-backed reports to dev-fresh and describes OpenSky as presence only', () => {
|
|
const credentials = Object.fromEntries([
|
|
'GOOGLE_MAPS_API_KEY',
|
|
'GOOGLE_MAPS_SERVER_API_KEY',
|
|
'CESIUM_ION_TOKEN',
|
|
'OPENAI_API_KEY',
|
|
'AISSTREAM_API_KEY',
|
|
'FIRMS_MAP_KEY',
|
|
'TOMTOM_API_KEY',
|
|
'OPENSKY_CLIENT_ID',
|
|
'OPENSKY_CLIENT_SECRET',
|
|
'LL2_API_TOKEN',
|
|
].map((name) => [name, { configured: false }]));
|
|
credentials.GOOGLE_MAPS_API_KEY = { configured: true, source: 'macOS Keychain' };
|
|
credentials.OPENSKY_CLIENT_ID = { configured: true, source: 'environment' };
|
|
credentials.OPENSKY_CLIENT_SECRET = { configured: true, source: 'environment' };
|
|
const capabilities = buildCapabilitySummary(credentials);
|
|
const output = formatSetupReport({
|
|
ready: true,
|
|
node: { level: 'ok', version: '24.14.0', summary: 'supported' },
|
|
npm: { available: true, version: '11.0.0' },
|
|
dependenciesInstalled: true,
|
|
capabilities,
|
|
credentials,
|
|
});
|
|
assert.match(output, /Run \.\/scripts\/dev-fresh\.sh/);
|
|
assert.doesNotMatch(output, /Run npm run dev/);
|
|
assert.match(capabilities.flights, /credentials present/);
|
|
assert.match(capabilities.flights, /runtime mode and validity not verified/);
|
|
assert.doesNotMatch(capabilities.flights, /polling/);
|
|
});
|
|
|
|
test('doctor never calls a dependency-missing setup ready', () => {
|
|
const credentials = Object.fromEntries([
|
|
'GOOGLE_MAPS_API_KEY',
|
|
'GOOGLE_MAPS_SERVER_API_KEY',
|
|
'CESIUM_ION_TOKEN',
|
|
'OPENAI_API_KEY',
|
|
'AISSTREAM_API_KEY',
|
|
'FIRMS_MAP_KEY',
|
|
'TOMTOM_API_KEY',
|
|
'OPENSKY_CLIENT_ID',
|
|
'OPENSKY_CLIENT_SECRET',
|
|
'LL2_API_TOKEN',
|
|
].map((name) => [name, { configured: false }]));
|
|
const output = formatSetupReport({
|
|
ready: false,
|
|
node: { level: 'ok', version: '24.14.0', summary: 'supported' },
|
|
npm: { available: true, version: '11.0.0' },
|
|
dependenciesInstalled: false,
|
|
capabilities: buildCapabilitySummary(credentials),
|
|
credentials,
|
|
});
|
|
assert.match(output, /dependencies missing; run npm install/);
|
|
assert.match(output, /Setup needs attention/);
|
|
assert.doesNotMatch(output, /Ready\. Run/);
|
|
});
|