Files
electric-cherry/tests/unit/host-instances.test.ts

118 lines
5.2 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { newFixture, type Fixture } from '../helpers/fixture.js';
import { gameEvent } from '../helpers/telemetry.js';
let fixture: Fixture;
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture([]);
});
afterEach(async () => {
await fixture.cleanup();
});
describe('host detail instances', () => {
it('returns only current instances belonging to the requested host and refreshes their health', async () => {
const { createHost } = await import('../../src/lib/server/hosts/index.js');
const host = createHost({ name: 'Selected host' });
const other = createHost({ name: 'Other host' });
const { db } = await import('../../src/lib/server/db/index.js');
const now = new Date().toISOString();
const add = (name: string, hostId: string, retired = false, destroyed = false) => {
db()
.prepare(
`INSERT INTO native_instances (id, server, host_id, generation, library_id, image, port, created_at, retired_at)
VALUES (?, ?, ?, 1, 'library', 'runtime:test', 28960, ?, ?)`
)
.run(name, name, hostId, now, retired ? now : null);
db()
.prepare(
`INSERT INTO servers (name,
container_state, container_checked_at, last_seen_at, last_players, destroyed_at)
VALUES (?, 'running', ?, ?, 2, ?)`
)
.run(name, now, now, destroyed ? now : null);
};
add('running', host.id);
add('unavailable', host.id);
add('other-host', other.id);
add('retired', host.id, true);
add('destroyed', host.id, false, true);
db()
.prepare(
`INSERT INTO native_instances (id, server, host_id, library_id, image, port, created_at, retired_at)
VALUES ('old-placement', 'other-host', ?, 'library', 'runtime:test', 28960, ?, ?)`
)
.run(host.id, now, now);
db().prepare("UPDATE servers SET container_state='exited' WHERE name='unavailable'").run();
const { hostOverview } = await import('../../src/lib/server/hosts/overview.js');
const overview = hostOverview();
expect(overview.find((row) => row.id === host.id)).toMatchObject({
serverCount: 2,
playerCount: 2,
unreportedInstances: 1
});
expect(overview.find((row) => row.id === other.id)).toMatchObject({
serverCount: 1,
playerCount: 2,
unreportedInstances: 0
});
const { GET: list } = await import('../../src/routes/api/hosts/+server.js');
const listed = await list({ request: new Request('https://ec.test/api/hosts') }).json();
expect(listed.serverNow).toEqual(expect.any(Number));
expect(listed.hosts.find((row: { id: string }) => row.id === host.id)).toMatchObject({
serverCount: 2,
playerCount: 2,
unreportedInstances: 1
});
const { GET } = await import('../../src/routes/api/hosts/[id]/+server.js');
const read = async (id: string) =>
await GET({
request: new Request(`https://ec.test/api/hosts/${id}`),
params: { id }
}).json();
const body = await read(host.id);
expect(body.instances.map((instance: { name: string }) => instance.name)).toEqual([
'running',
'unavailable'
]);
expect(body.instances[0]).toMatchObject({ health: 'online', last_players: 2 });
expect(body.instances[1]).toMatchObject({ health: 'offline', last_players: null });
expect(body.serverNow).toEqual(expect.any(Number));
db().prepare("UPDATE servers SET last_players=0 WHERE name='running'").run();
expect((await read(host.id)).instances[0].last_players).toBe(0);
expect(
(await read(other.id)).instances.map((instance: { name: string }) => instance.name)
).toEqual(['other-host']);
const empty = createHost({ name: 'Empty host' });
expect((await read(empty.id)).instances).toEqual([]);
expect(hostOverview().find((row) => row.id === empty.id)).toMatchObject({
serverCount: 0,
playerCount: 0,
unreportedInstances: 0
});
const report = { ...gameEvent('heartbeat', 15, 4, 'running'), receivedAt: now };
db()
.prepare(
'INSERT INTO server_telemetry (server, round, players, received_at, payload) VALUES (?, ?, ?, ?, ?)'
)
.run('running', 15, 4, now, JSON.stringify(report));
expect(hostOverview().find((row) => row.id === host.id)).toMatchObject({
playerCount: 4,
unreportedInstances: 1
});
db().prepare("DELETE FROM server_telemetry WHERE server='running'").run();
db()
.prepare(
"UPDATE servers SET last_seen_at='2000-01-01T00:00:00Z',last_players=99 WHERE name='running'"
)
.run();
expect(hostOverview().find((row) => row.id === host.id)).toMatchObject({
playerCount: 0,
unreportedInstances: 2
});
});
});