Files
electric-cherry/tests/unit/ui-fleet-attention.test.ts
T
2026-10-19 20:22:58 -04:00

91 lines
3.1 KiB
TypeScript

import { expect, it, vi } from 'vitest';
import { render } from 'svelte/server';
import { writable } from 'svelte/store';
import type { ComponentProps } from 'svelte';
import Page from '../../src/routes/+page.svelte';
import { syncServerTime } from '../../src/lib/ui/stores/servers.js';
import type { FleetServer } from '../../src/lib/fleet-overview.js';
vi.mock('$app/navigation', () => ({
afterNavigate: vi.fn(),
replaceState: vi.fn(),
goto: vi.fn(),
beforeNavigate: vi.fn()
}));
vi.mock('$app/stores', () => ({
page: writable({ url: new URL('http://localhost/'), data: { user: { role: 'viewer' } } })
}));
const now = Date.parse('2026-10-19T22:46:00.000Z');
const healthAt = new Date(now - 8000).toISOString();
const failedAt = '2026-10-19T18:48:42.000Z';
const server: FleetServer = {
name: 't5_zombie_sumpf_1',
game: 't5',
map: 'zombie_sumpf',
last_map: 'zombie_sumpf',
last_players: 0,
last_gametype: 'zom',
last_seen_at: healthAt,
last_checked_at: healthAt,
container_state: 'running',
container_checked_at: healthAt,
last_error: null,
roster: [],
health: 'online',
held: [],
active_since: null,
inactive_since: null,
game_started_at: null,
game_ended_at: null
};
it.each([true, false])(
'dates the displayed attention reason when the server is healthy=%s',
(healthy) => {
syncServerTime(now);
const data = {
user: null,
setupRequired: false,
fleetSnapshot: {
serverNow: now,
hostAttention: 0,
reservedNames: [],
servers: [
healthy ? server : { ...server, health: 'offline', container_state: 'stopped' }
],
integrations: {
native: true,
hostsReady: 1,
hostsTotal: 1,
rcon: true,
rconTimeoutMs: 2000,
defaultRconHost: 'localhost'
},
operations: [
{
key: 'campaign:one',
group: 'campaign:one',
kind: 'campaign',
server: server.name,
label: 'Update needs attention',
detail: 'Download timed out',
href: '/campaigns/one',
state: 'attention',
startedAt: '2026-10-19T18:38:00.000Z',
evidenceAt: failedAt
}
]
}
// Rendering needs the public Fleet fields, without the registry's storage metadata.
} as unknown as ComponentProps<typeof Page>['data'];
const body = render(Page, { props: { data } }).body;
const evidence = body.match(/class="evidence-time[^"]*" title="([^"]+)"/)?.[1];
expect(evidence).toBe(healthy ? failedAt : healthAt);
if (healthy) {
expect(body).toContain('Update needs attention');
expect(body).toContain('Evidence 3h 57m ago');
}
}
);