Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+125 -24
View File
@@ -6,34 +6,105 @@ import CapacityPage from '../../src/routes/capacity/+page.svelte';
import CapacityHosts from '../../src/lib/ui/components/capacity/CapacityHosts.svelte';
import CapacityChart from '../../src/lib/ui/components/capacity/CapacityChart.svelte';
vi.mock('$app/state', () => ({ page: { url: new URL('http://localhost/capacity?host=ec-1&game=t5') } }));
vi.mock('$app/state', () => ({
page: { url: new URL('http://localhost/capacity?host=ec-1&game=t5') }
}));
vi.mock('$app/stores', () => ({ page: writable({ url: new URL('http://localhost/capacity') }) }));
vi.mock('$app/navigation', () => ({ beforeNavigate: vi.fn(), afterNavigate: vi.fn(), goto: vi.fn() }));
vi.mock('$app/navigation', () => ({
beforeNavigate: vi.fn(),
afterNavigate: vi.fn(),
goto: vi.fn()
}));
const allowance = { cpuCores: 0.5, memoryBytes: 1024 ** 3, source: 'host' as const, samples: 20, observedAt: '2026-10-06T12:00:00Z' };
const allowance = {
cpuCores: 0.5,
memoryBytes: 1024 ** 3,
source: 'host' as const,
samples: 20,
observedAt: '2026-10-06T12:00:00Z'
};
const host = (changes: Partial<CapacityHost> = {}): CapacityHost => ({
id: 'ec-1', name: 'ec-1', connected: true, readiness: 'ready', updatedAt: '2026-10-06T12:00:00Z', eligible: true,
games: ['t5', 't6'], reasons: [], cpuCoresAvailable: 2, memoryBytesAvailable: 4 * 1024 ** 3,
portsAvailable: 1, totalPorts: 10, estimatedServers: 1, limits: { cpu: 4, memory: 4, ports: 1 }, limitingResource: 'Ports',
calibration: { running: allowance, startup: allowance }, ...changes
id: 'ec-1',
name: 'ec-1',
connected: true,
readiness: 'ready',
updatedAt: '2026-10-06T12:00:00Z',
eligible: true,
games: ['t5', 't6'],
reasons: [],
cpuCoresAvailable: 2,
memoryBytesAvailable: 4 * 1024 ** 3,
portsAvailable: 1,
totalPorts: 10,
estimatedServers: 1,
limits: { cpu: 4, memory: 4, ports: 1 },
limitingResource: 'Ports',
calibration: { running: allowance, startup: allowance },
...changes
});
const history: CapacityHistory = { range: '24h', startAt: 1000, endAt: 5000, bucketMs: 1000, points: [
{ at: 1000, cpuCoresAvailable: 2, memoryBytesAvailable: 1024 ** 3, reportingHosts: 1, expectedHosts: 1 },
{ at: 2000, cpuCoresAvailable: null, memoryBytesAvailable: null, reportingHosts: 0, expectedHosts: 1 },
{ at: 3000, cpuCoresAvailable: 3, memoryBytesAvailable: 2 * 1024 ** 3, reportingHosts: 1, expectedHosts: 1 }
] };
const data = (): CapacityData => ({ query: { range: '24h', game: 't5', hostId: 'ec-1' }, history,
current: { updatedAt: '2026-10-06T12:00:00Z', hosts: [host()], hostOptions: [{ id: 'ec-1', name: 'ec-1' }], warnings: [], summary: {
estimatedServers: 1, cpuCoresAvailable: 2, memoryBytesAvailable: 4 * 1024 ** 3, portsAvailable: 1,
eligibleHosts: 1, totalHosts: 1, startupSlots: 3, startupLimit: 3, activeStartups: 0, queued: 0
} }
const history: CapacityHistory = {
range: '24h',
startAt: 1000,
endAt: 5000,
bucketMs: 1000,
points: [
{
at: 1000,
cpuCoresAvailable: 2,
memoryBytesAvailable: 1024 ** 3,
reportingHosts: 1,
expectedHosts: 1
},
{
at: 2000,
cpuCoresAvailable: null,
memoryBytesAvailable: null,
reportingHosts: 0,
expectedHosts: 1
},
{
at: 3000,
cpuCoresAvailable: 3,
memoryBytesAvailable: 2 * 1024 ** 3,
reportingHosts: 1,
expectedHosts: 1
}
]
};
const data = (): CapacityData => ({
query: { range: '24h', game: 't5', hostId: 'ec-1' },
history,
current: {
updatedAt: '2026-10-06T12:00:00Z',
hosts: [host()],
hostOptions: [{ id: 'ec-1', name: 'ec-1' }],
warnings: [],
summary: {
estimatedServers: 1,
cpuCoresAvailable: 2,
memoryBytesAvailable: 4 * 1024 ** 3,
portsAvailable: 1,
eligibleHosts: 1,
totalHosts: 1,
startupSlots: 3,
startupLimit: 3,
activeStartups: 0,
queued: 0
}
}
});
it('keeps current estimates and host comparison before history with scoped history controls', () => {
const body = render(CapacityPage, { props: { data: data() } }).body;
expect(body.indexOf('id="capacity-now-title"')).toBeLessThan(body.indexOf('id="host-capacity-title"'));
expect(body.indexOf('id="host-capacity-title"')).toBeLessThan(body.indexOf('id="capacity-history-title"'));
expect(body.indexOf('aria-label="History range"')).toBeGreaterThan(body.indexOf('id="capacity-history-title"'));
expect(body.indexOf('id="capacity-now-title"')).toBeLessThan(
body.indexOf('id="host-capacity-title"')
);
expect(body.indexOf('id="host-capacity-title"')).toBeLessThan(
body.indexOf('id="capacity-history-title"')
);
expect(body.indexOf('aria-label="History range"')).toBeGreaterThan(
body.indexOf('id="capacity-history-title"')
);
expect(body).toContain('range=7d&amp;game=t5&amp;host=ec-1');
expect(body).toContain('3 of 3 available');
expect(body).toContain('No queued servers');
@@ -44,16 +115,44 @@ it('keeps current estimates and host comparison before history with scoped histo
});
it('keeps fleet-wide queue scope explicit and preserves unavailable estimates', () => {
const report = data(); report.current.summary.queued = 2; report.current.summary.estimatedServers = null;
const report = data();
report.current.summary.queued = 2;
report.current.summary.estimatedServers = null;
const body = render(CapacityPage, { props: { data: report } }).body;
expect(body).toContain('Capacity estimate unavailable');
expect(body).toContain('href="/provisioning"');
expect(body).toContain('2 servers queued');
expect(body.replace(/\s+/g, ' ')).toContain('2 servers queued');
expect(body).toContain('Fleet-wide');
});
it('keeps ineligible hosts and their reasons visible while collapsing detailed assumptions', () => {
const body = render(CapacityHosts, { props: { returnTo: '/capacity', hosts: [host(), host({ id: 'missing-files', name: 'Missing files', eligible: false, estimatedServers: 0, limitingResource: null, reasons: ['Latest game files are not ready.'] }), host({ id: 'offline', name: 'Offline host', connected: false, eligible: false, estimatedServers: 0, cpuCoresAvailable: null, memoryBytesAvailable: null, limitingResource: null, reasons: ['Waiting for a fresh host report.'] })] } }).body;
const body = render(CapacityHosts, {
props: {
returnTo: '/capacity',
hosts: [
host(),
host({
id: 'missing-files',
name: 'Missing files',
eligible: false,
estimatedServers: 0,
limitingResource: null,
reasons: ['Latest game files are not ready.']
}),
host({
id: 'offline',
name: 'Offline host',
connected: false,
eligible: false,
estimatedServers: 0,
cpuCoresAvailable: null,
memoryBytesAvailable: null,
limitingResource: null,
reasons: ['Waiting for a fresh host report.']
})
]
}
}).body;
expect(body).toContain('Additional servers</th>');
expect(body).toContain('Not eligible');
expect(body).toContain('Latest game files are not ready.');
@@ -75,7 +174,9 @@ it('preserves chart gaps, keyboard inspection and reporting coverage in the comp
expect(body).toContain('The game filter applies to current launch estimates only.');
expect(body).toContain('About this chart');
expect(body).not.toMatch(/<details[^>]*open/);
const empty = render(CapacityChart, { props: { history: { ...history, points: [history.points[1]] }, scope: 'All hosts' } }).body;
const empty = render(CapacityChart, {
props: { history: { ...history, points: [history.points[1]] }, scope: 'All hosts' }
}).body;
expect(empty).toContain('Waiting for capacity history');
expect(empty).toContain('No complete report');
});