adds round telemetry support
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
|
||||
import { newFixture, type Fixture } from '../helpers/fixture.js';
|
||||
|
||||
let fixture: Fixture;
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
fixture = await newFixture();
|
||||
const { seedServerRegistry } = await import('../../src/lib/server/fleet/servers.js');
|
||||
await seedServerRegistry();
|
||||
});
|
||||
afterEach(async () => fixture.cleanup());
|
||||
|
||||
const payload = { event: 'round_change', server: 't5_zombie_theater_1', round: 17, players: 4 };
|
||||
async function post(body: unknown, contentType = 'application/json') {
|
||||
const { POST } = await import('../../src/routes/api/telemetry/+server.js');
|
||||
return POST({ request: new Request('http://localhost/api/telemetry', {
|
||||
method: 'POST', headers: { 'Content-Type': contentType }, body: JSON.stringify(body)
|
||||
}) });
|
||||
}
|
||||
|
||||
it('persists reports, broadcasts updates, and leaves RCON safety data untouched', async () => {
|
||||
const { subscribe } = await import('../../src/lib/server/pipeline/bus.js');
|
||||
const listener = vi.fn();
|
||||
const unsubscribe = subscribe(listener);
|
||||
expect((await post(payload)).status).toBe(200);
|
||||
expect(listener).toHaveBeenCalledWith(expect.objectContaining({ type: 'server-telemetry' }));
|
||||
unsubscribe();
|
||||
// A new match can legitimately report a lower round; retries overwrite one row.
|
||||
await post({ ...payload, round: 1 });
|
||||
await post({ ...payload, round: 1 });
|
||||
const { closeDb } = await import('../../src/lib/server/db/index.js');
|
||||
closeDb();
|
||||
const { listTelemetry } = await import('../../src/lib/server/fleet/telemetry.js');
|
||||
expect(listTelemetry()).toEqual([expect.objectContaining({ round: 1, players: 4 })]);
|
||||
const { getServer } = await import('../../src/lib/server/fleet/servers.js');
|
||||
expect(getServer(payload.server)?.last_players).toBeNull();
|
||||
const { GET } = await import('../../src/routes/api/events/servers/+server.js');
|
||||
const response = await GET();
|
||||
const reader = response.body!.getReader();
|
||||
await reader.read(); // greeting
|
||||
const snapshot = await reader.read();
|
||||
expect(new TextDecoder().decode(snapshot.value)).toContain('"round":1');
|
||||
await reader.cancel();
|
||||
});
|
||||
|
||||
it.each([null, [], {}, { ...payload, event: 'other' }, { ...payload, round: -1 },
|
||||
{ ...payload, round: 1.5 }, { ...payload, round: '17' }, { ...payload, players: -1 },
|
||||
{ ...payload, players: null }])('rejects invalid telemetry: %j', async (body) => {
|
||||
expect((await post(body)).status).toBe(400);
|
||||
});
|
||||
|
||||
it('rejects unknown and destroyed servers and non-JSON requests', async () => {
|
||||
expect((await post({ ...payload, server: 'unknown' })).status).toBe(404);
|
||||
expect((await post(payload, 'text/plain')).status).toBe(415);
|
||||
const { setServerField } = await import('../../src/lib/server/fleet/servers.js');
|
||||
setServerField(payload.server, 'destroyed_at', new Date().toISOString());
|
||||
expect((await post(payload)).status).toBe(404);
|
||||
});
|
||||
|
||||
it('rejects malformed JSON', async () => {
|
||||
const { POST } = await import('../../src/routes/api/telemetry/+server.js');
|
||||
expect((await POST({ request: new Request('http://localhost/api/telemetry', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{'
|
||||
}) })).status).toBe(400);
|
||||
});
|
||||
Reference in New Issue
Block a user