Files
AetherForge/server/web/src/components/Fleet/AccessDepthPanel.test.tsx
AetherForge 72d0e6ac19
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add Vitest coverage for erasure lanes, fleet evolution UI, and spread routes.
Cover Path Tracer RS lane hints, Calibrate erasure toggle, fleet role chips, atlas skips panel, and erasure_lanes help copy.
2026-06-07 06:21:11 -07:00

253 lines
8.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @vitest-environment happy-dom
*/
import { afterEach, describe, expect, it, vi } from 'vitest';
import { cleanup, render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import AccessDepthPanel from './AccessDepthPanel';
import type { Agent } from '../../types';
import {
buildAccessDepthModel,
parseAccessDepthDiagnostics,
parseAccessDepthServerPolicy,
} from '../../help/accessDepth';
vi.mock('../../hooks/useWebSocket', () => ({
useWebSocket: () => ({ latestMessage: null }),
}));
vi.mock('../../api/client', () => ({
api: {
getConfig: vi.fn().mockResolvedValue({
server: {
lotl_onion_tiers: ['vuln_recon', 'docker', 'winrm'],
triple_onion_policy: {
recon_tiers: ['vuln_recon'],
deploy_lanes: ['docker', 'winrm'],
},
},
}),
},
}));
function mockAgent(overrides: Partial<Agent>): Agent {
return {
id: 'a1',
name: 'Node',
wallet: '',
ip: '10.0.0.5',
version: '1',
status: 'online',
cpu_cores: 8,
memory_gb: 16,
last_seen: '',
created_at: '',
hashrate_15s: 0,
hashrate_1m: 0,
hashrate_15m: 0,
shares_total: 0,
shares_good: 0,
shares_bad: 0,
cpu_usage_pct: 0,
memory_usage_pct: 0,
uptime_seconds: 0,
...overrides,
};
}
function renderPanel(agent: Agent, diagnostics?: ReturnType<typeof parseAccessDepthDiagnostics>) {
return render(
<MemoryRouter>
<AccessDepthPanel agent={agent} diagnostics={diagnostics} />
</MemoryRouter>,
);
}
describe('accessDepth helpers', () => {
it('parses mining diagnostics payload with probes and tier chain', () => {
const diag = parseAccessDepthDiagnostics({
lotl_tier: 'wsl',
tier_chain_order: ['container', 'wsl', 'cpu_inprocess'],
tier_chain_skipped: ['exe_subprocess'],
environment_probes: { docker: true, wsl: true, pwsh: true, gpu: false },
lotl_attempts: [
{ tier: 'container', ok: false, error: 'no runtime', phase: 'mining' },
{ tier: 'wsl', ok: true, duration_ms: 900, phase: 'mining' },
],
});
expect(diag.lotl_tier).toBe('wsl');
expect(diag.tier_chain_skipped).toEqual(['exe_subprocess']);
expect(diag.environment_probes?.docker).toBe(true);
expect(diag.lotl_attempts).toHaveLength(2);
expect(diag.lotl_attempts?.[1].phase).toBe('mining');
});
it('buildAccessDepthModel for Windows agent with diagnostics', () => {
const agent = mockAgent({
platform: 'windows',
os_version: '10.0.26200',
arch: 'amd64',
lotl_tier: 'wsl',
join_lane: 'winrm',
agent_elevated: true,
capabilities: { auto_spread: true, hole_punch: false, mesh_p2p: true, remote_aggressive: true, process_hollowing: false, ai_enabled: false },
});
const model = buildAccessDepthModel(
agent,
parseAccessDepthDiagnostics({
tier_chain_order: ['container', 'wsl', 'cpu_inprocess'],
tier_chain_skipped: ['exe_subprocess'],
lotl_attempts: [
{ tier: 'container', ok: false, error: 'blocked', phase: 'mining' },
{ tier: 'wsl', ok: true, phase: 'mining' },
],
environment_probes: { docker: false, wsl: true, pwsh: true },
}),
parseAccessDepthServerPolicy({ server: { lotl_onion_tiers: ['vuln_recon', 'docker'] } }),
);
expect(model.platformLabel).toBe('Windows');
expect(model.joinLane).toBe('winrm');
expect(model.succeeded).toHaveLength(1);
expect(model.failed).toHaveLength(1);
expect(model.miningOnion.find((r) => r.tier === 'wsl')?.status).toBe('active');
expect(model.spreadOnion).toHaveLength(2);
});
it('buildAccessDepthModel for Linux agent without diagnostics', () => {
const agent = mockAgent({
platform: 'linux',
join_lane: 'linux-lotl',
lotl_attempts: [{ tier: 'cpu_inprocess', ok: true, phase: 'mining' }],
});
const model = buildAccessDepthModel(agent);
expect(model.platformLabel).toBe('Linux');
expect(model.succeeded[0].tier).toBe('cpu_inprocess');
expect(model.miningOnion.length).toBeGreaterThan(0);
});
it('buildAccessDepthModel for macOS agent', () => {
const agent = mockAgent({ platform: 'darwin', os_version: '14.2' });
const model = buildAccessDepthModel(agent);
expect(model.platformLabel).toBe('macOS');
expect(model.osLine).toContain('macOS');
});
});
describe('AccessDepthPanel', () => {
afterEach(() => cleanup());
it('renders sections for Windows fixture', async () => {
renderPanel(
mockAgent({
platform: 'windows',
lotl_tier: 'wsl',
join_lane: 'winrm',
lotl_attempts: [{ tier: 'wsl', ok: true, phase: 'mining' }],
}),
parseAccessDepthDiagnostics({
environment_probes: { wsl: true, pwsh: true },
tier_chain_order: ['container', 'wsl'],
lotl_attempts: [{ tier: 'wsl', ok: true, phase: 'mining' }],
}),
);
expect(screen.getByText('ACCESS DEPTH')).toBeInTheDocument();
expect(screen.getByText('OS & posture')).toBeInTheDocument();
expect(screen.getByText('Active')).toBeInTheDocument();
expect(screen.getByText('Succeeded')).toBeInTheDocument();
expect(screen.getByText('Failed / in progress')).toBeInTheDocument();
expect(screen.getByText('Effective onion order')).toBeInTheDocument();
expect(await screen.findByText('WinRM')).toBeInTheDocument();
});
it('shows phenotype source when inherited phenotype present', async () => {
renderPanel(
mockAgent({
platform: 'windows',
inherited_phenotype: {
source_agent_name: 'worker-07',
spread_lane: 'winrm',
tier_order: ['container', 'wsl', 'cpu_inprocess'],
},
}),
);
expect(await screen.findByText(/phenotype cloned from/i)).toBeInTheDocument();
expect(screen.getByText('worker-07')).toBeInTheDocument();
expect(await screen.findByText('WinRM')).toBeInTheDocument();
});
it('renders adaptive strategy reasoning fixtures', () => {
renderPanel(
mockAgent({ platform: 'windows', status: 'online' }),
parseAccessDepthDiagnostics({
adaptive_strategy: {
tier_order: ['container', 'docker_load', 'wsl', 'cpu_inprocess'],
skip_tiers: ['exe_subprocess'],
confidence: 0.72,
reasoning: [
{
fact: 'Docker runtime available on Windows host',
inference: 'Container tier isolates miner from AV friction',
action: 'Prefer container before raw subprocess',
},
],
},
}),
);
expect(screen.getByText('Strategy')).toBeInTheDocument();
expect(screen.getByText('Adaptive')).toBeInTheDocument();
expect(screen.getByText('AI path')).toBeInTheDocument();
expect(screen.getByText(/Docker runtime available/i)).toBeInTheDocument();
expect(screen.getByText(/confidence 72%/i)).toBeInTheDocument();
});
it('renders atlas skips block when failure atlas hard-skips tiers', async () => {
renderPanel(
mockAgent({ platform: 'windows', status: 'online' }),
parseAccessDepthDiagnostics({
tier_chain_order: ['exe_subprocess', 'ps_inmemory', 'cpu_inprocess'],
atlas_skips: [
{ tier: 'ps_inmemory', condition: 'defender_on', reason: '5 failures with Defender on' },
],
}),
);
expect(await screen.findByText('Atlas skips')).toBeInTheDocument();
expect(screen.getByText(/ps inmemory \(Defender on\)/i)).toBeInTheDocument();
});
it('shows spread genealogy lineage when watermark present', async () => {
renderPanel(
mockAgent({
platform: 'windows',
parent_agent_id: '11112222-3333-4444-aaaa-bbbbbbbbbbbb',
spread_generation: 2,
spread_strain: '#a1b2c3',
join_lane: 'winrm',
}),
);
expect(await screen.findByText(/lineage gen 2/i)).toBeInTheDocument();
expect(screen.getByText(/parent 11112222/i)).toBeInTheDocument();
});
it('renders clearance badge L0L4 with tooltip permissions', () => {
renderPanel(mockAgent({ clearance_level: 2 }));
const badge = screen.getByLabelText(/Clearance L2/i);
expect(badge).toHaveTextContent('L2');
expect(badge.getAttribute('title')).toMatch(/spread/i);
});
it('shows pending chain when tiers not yet attempted', () => {
renderPanel(
mockAgent({
platform: 'linux',
status: 'online',
lotl_attempts: [{ tier: 'container', ok: false, error: 'missing' }],
}),
parseAccessDepthDiagnostics({
tier_chain_order: ['container', 'wsl', 'cpu_inprocess'],
lotl_attempts: [{ tier: 'container', ok: false, error: 'missing' }],
}),
);
expect(screen.getByText(/pending:/i)).toBeInTheDocument();
});
});