60 lines
3.5 KiB
TypeScript
60 lines
3.5 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { newFixture, type Fixture } from '../helpers/fixture.js';
|
|
|
|
let fixture: Fixture;
|
|
beforeEach(async () => { vi.resetModules(); fixture = await newFixture([]); });
|
|
afterEach(async () => { await fixture.cleanup(); });
|
|
|
|
describe('historical metrics', () => {
|
|
it('weights occupancy by time and excludes failed checks and collection gaps', async () => {
|
|
const { recordMetrics, readMetrics } = await import('../../src/lib/server/fleet/metrics.js');
|
|
const sample = { server: 'one', game: 't5', map: 'Moon', players: 2, capacity: 4 };
|
|
const at = Date.UTC(2026, 0, 2, 12);
|
|
recordMetrics([sample], at);
|
|
recordMetrics([{ ...sample, players: 0 }], at + 30_000);
|
|
recordMetrics([{ ...sample, players: null }], at + 60_000);
|
|
const result = readMetrics(1, at + 3600_000);
|
|
expect(result.summary.active * 3600).toBeCloseTo(30);
|
|
expect(result.summary.idle * 3600).toBeCloseTo(30);
|
|
expect(result.summary.unknown * 3600).toBeCloseTo(45);
|
|
expect(result.summary.playerHours * 3600).toBeCloseTo(60);
|
|
expect(result.points.reduce((sum, p) => sum + p.observed, 0)).toBeCloseTo(result.summary.observed);
|
|
});
|
|
|
|
it('only counts map saturation when every lobby has known capacity and is full', async () => {
|
|
const { recordMetrics, readMetrics } = await import('../../src/lib/server/fleet/metrics.js');
|
|
const at = Date.UTC(2026, 0, 2, 12);
|
|
const sample = { server: 'one', game: 't5', map: 'Moon', players: 4, capacity: 4 };
|
|
recordMetrics([sample, { ...sample, server: 'two' }], at);
|
|
recordMetrics([sample, { ...sample, server: 'two', players: 2 }], at + 30_000);
|
|
recordMetrics([sample, { ...sample, server: 'two', capacity: null }], at + 60_000);
|
|
recordMetrics([sample, { ...sample, server: 'two', players: null }], at + 90_000);
|
|
const result = readMetrics(1, at + 120_000);
|
|
expect(result.maps[0].full * 3600).toBeCloseTo(30);
|
|
expect(result.maps[0].capacityObserved * 3600).toBeCloseTo(60);
|
|
});
|
|
|
|
it('clips the reporting window and splits observations across UTC chart boundaries', async () => {
|
|
const { recordMetrics, readMetrics } = await import('../../src/lib/server/fleet/metrics.js');
|
|
const midnight = Date.UTC(2026, 0, 2);
|
|
const sample = { server: 'one', game: 't5', map: 'Moon', players: 1, capacity: 4 };
|
|
recordMetrics([sample], midnight - 15_000);
|
|
let result = readMetrics(1, midnight + 15_000);
|
|
expect(result.points.filter(p => p.active > 0).map(p => p.active * 3600)).toEqual([15, 15]);
|
|
result = readMetrics(1, midnight + 86400_000);
|
|
expect(result.summary.active * 3600).toBeCloseTo(30);
|
|
expect(result.points.reduce((sum, p) => sum + p.active, 0)).toBeCloseTo(result.summary.active);
|
|
});
|
|
|
|
it('retains history without a live server and prunes observations older than 31 days', async () => {
|
|
const { recordMetrics, readMetrics } = await import('../../src/lib/server/fleet/metrics.js');
|
|
const { db } = await import('../../src/lib/server/db/index.js');
|
|
const at = Date.UTC(2026, 0, 2);
|
|
const sample = { server: 'removed', game: 't6', map: 'Town', players: 1, capacity: null };
|
|
recordMetrics([sample], at);
|
|
expect(readMetrics(1, at + 30_000).servers[0].server).toBe('removed');
|
|
recordMetrics([sample], at + 32 * 86400_000);
|
|
expect(db().prepare('SELECT COUNT(*) AS n FROM metric_samples').get()).toEqual({ n: 1 });
|
|
});
|
|
});
|