Files
AetherForge/server/web/src/components/Lotl/LotlTierTimeline.test.tsx
AetherForge 4204dd6b6d Add fleet phenotype cloning for sibling machines.
Publish winning tier paths per host fingerprint on hashrate success, inherit on auth before adaptive strategy, and surface clone badges in LOTL Timeline and Access Depth.
2026-06-07 02:28:00 -07:00

73 lines
2.8 KiB
TypeScript

/**
* @vitest-environment happy-dom
*/
import { afterEach, describe, expect, it } from 'vitest';
import { cleanup, render, screen, fireEvent } from '@testing-library/react';
import LotlTierTimeline from './LotlTierTimeline';
import { buildLotlTimelineModel, resolveLotlTierOrder } from '../../help/lotlTimeline';
import { mockAgent } from '../../test/fixtures';
describe('LotlTierTimeline', () => {
afterEach(() => cleanup());
it('renders 14 tiers from fixture attempts', () => {
const order = resolveLotlTierOrder();
expect(order).toHaveLength(14);
const agent = mockAgent({
status: 'online',
lotl_tier: 'wsl',
lotl_attempts: [
{ tier: 'vuln_recon', ok: true, duration_ms: 800, phase: 'recon' },
{ tier: 'docker', ok: false, error: 'no daemon', duration_ms: 1200, phase: 'deploy' },
{ tier: 'wsl', ok: false, error: 'distro missing', duration_ms: 900, phase: 'deploy' },
],
});
const model = buildLotlTimelineModel(agent, order, agent.lotl_attempts ?? []);
expect(model.tiers).toHaveLength(14);
expect(model.succeeded).toBe(1);
expect(model.tiers[0].state).toBe('success');
expect(model.tiers[1].state).toBe('failed');
expect(model.tiers[2].state).toBe('trying');
render(<LotlTierTimeline model={model} agentName="Test Miner" />);
expect(screen.getByText('ONION TIER CHAIN')).toBeInTheDocument();
expect(screen.getByText('1/14 tiers succeeded')).toBeInTheDocument();
expect(screen.getAllByRole('listitem')).toHaveLength(14);
expect(screen.getByText('Vuln Recon')).toBeInTheDocument();
expect(screen.getByText('GPO')).toBeInTheDocument();
});
it('shows cloned-from badge when inherited phenotype present', () => {
const order = resolveLotlTierOrder();
const agent = mockAgent({
inherited_phenotype: {
source_agent_name: 'worker-07',
tier_order: ['container', 'wsl'],
spread_lane: 'winrm',
},
});
const model = buildLotlTimelineModel(agent, order, []);
render(<LotlTierTimeline model={model} agentName="Node B" clonedFrom="worker-07" />);
expect(screen.getByText('Cloned from worker-07')).toBeInTheDocument();
});
it('expands attempt detail on tier click', () => {
const order = resolveLotlTierOrder();
const agent = mockAgent({
lotl_attempts: [
{ tier: 'docker', ok: false, error: 'AV blocked', duration_ms: 500, phase: 'deploy' },
],
});
const model = buildLotlTimelineModel(agent, order, agent.lotl_attempts ?? []);
render(<LotlTierTimeline model={model} agentName="Node A" />);
fireEvent.click(screen.getByText('Docker'));
expect(screen.getByText('AV blocked')).toBeInTheDocument();
expect(screen.getByText('deploy')).toBeInTheDocument();
expect(screen.getByText('500ms')).toBeInTheDocument();
});
});