Files
electric-cherry/tests/unit/system-status.test.ts
T
josh e5c0fda1ed Add native host management and role-based operator authentication
Introduce an outbound Python host agent, Debian installer, durable remote
operations, immutable game-file libraries, host-aware deployments and ports,
and occupancy-safe campaigns and draining. Native hosts do not require Komodo.

Add administrator, operator and viewer accounts, protected management routes,
secure sessions, password recovery, audit history and separate telemetry tokens.
Document first-admin setup, reporter migration and live-host acceptance checks.

Validation: 1,343 TypeScript tests and 39 agent tests passed, along with type
checking, the production build, compiled SSR/API smoke tests and administrator
recovery. Real Debian/Docker T5/T6 acceptance remains unrun.
2026-10-03 11:42:36 -04:00

51 lines
3.2 KiB
TypeScript

import { afterEach, beforeEach, expect, it, vi } from 'vitest';
import { newFixture, type Fixture } from '../helpers/fixture.js';
let fixture: Fixture;
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture([]);
vi.stubEnv('KOMODO_ADDRESS', '');
vi.stubEnv('KOMODO_API_KEY', '');
vi.stubEnv('KOMODO_API_SECRET', '');
vi.stubEnv('KOMODO_TARGET_SERVER', '');
vi.stubEnv('RCON_PASSWORD', '');
});
afterEach(async () => { await fixture.cleanup(); vi.unstubAllEnvs(); vi.restoreAllMocks(); });
it('directs a fresh controller to native hosts and verified libraries without probing Komodo', async () => {
const probe = vi.spyOn(await import('../../src/lib/server/integrations/netProbe.js'), 'tcpProbe');
const { GET } = await import('../../src/routes/api/system-status/+server.js');
const response = await GET({ url: new URL('http://localhost/api/system-status') });
const body = await response.json();
expect(response.headers.get('cache-control')).toBe('no-store');
expect(body.checks.find((check: { id: string }) => check.id === 'hosts').state).toBe('unconfigured');
expect(body.checks.find((check: { id: string }) => check.id === 'game-files').state).toBe('attention');
expect(body.checks.some((check: { id: string }) => check.id === 'komodo')).toBe(false);
expect(body.readyServers).toBe(0);
expect(probe).not.toHaveBeenCalled();
});
it('never exposes credentials or claims that network reachability validates them', async () => {
vi.stubEnv('KOMODO_ADDRESS', 'https://komodo.example.test');
vi.stubEnv('KOMODO_API_KEY', 'fixture-private-key');
vi.stubEnv('KOMODO_API_SECRET', 'fixture-private-secret');
vi.stubEnv('RCON_PASSWORD', 'fixture-rcon-secret');
vi.spyOn(await import('../../src/lib/server/integrations/netProbe.js'), 'tcpProbe').mockResolvedValue({ label: 'Komodo', host: 'komodo.example.test', port: 443, resolvedIp: '192.0.2.1', outcome: 'connected', elapsedMs: 1 });
const { GET } = await import('../../src/routes/api/system-status/+server.js');
const text = await (await GET({ url: new URL('http://localhost/api/system-status?probe=1') })).text();
for (const secret of ['fixture-private-key', 'fixture-private-secret', 'fixture-rcon-secret']) expect(text).not.toContain(secret);
const connection = JSON.parse(text).checks.find((check: { id: string }) => check.id === 'komodo');
expect(connection.state).toBe('ready');
expect(connection.detail).toContain('does not validate API credentials');
});
it('reports a configured unreachable host as needing attention', async () => {
vi.stubEnv('KOMODO_ADDRESS', 'http://komodo.example.test:9120');
vi.stubEnv('KOMODO_API_KEY', 'key'); vi.stubEnv('KOMODO_API_SECRET', 'secret');
vi.spyOn(await import('../../src/lib/server/integrations/netProbe.js'), 'tcpProbe').mockResolvedValue({ label: 'Komodo', host: 'komodo.example.test', port: 9120, resolvedIp: null, outcome: 'dns-fail', elapsedMs: 1 });
const { GET } = await import('../../src/routes/api/system-status/+server.js');
const body = await (await GET({ url: new URL('http://localhost/api/system-status?probe=1') })).json();
expect(body.checks.find((check: { id: string }) => check.id === 'komodo').state).toBe('attention');
});