This commit is contained in:
@@ -3,12 +3,20 @@ import { createMetricsRefresh } from '../../src/lib/ui/metrics-refresh.js';
|
||||
|
||||
afterEach(() => vi.useRealTimers());
|
||||
const totals = { observed: 0, active: 0, idle: 0, unknown: 0, playerHours: 0 };
|
||||
const emptyMatches = {
|
||||
started: 0,
|
||||
withRecordedPlayers: 0,
|
||||
averageGroupSize: null,
|
||||
solo: 0,
|
||||
soloShare: null
|
||||
};
|
||||
const report = (days: number) => ({
|
||||
days,
|
||||
now: 1000,
|
||||
since: 0,
|
||||
summary: totals,
|
||||
running: { average: null, peak: 0, capturedHours: 0 },
|
||||
matches: emptyMatches,
|
||||
points: [],
|
||||
maps: [],
|
||||
servers: [],
|
||||
@@ -134,6 +142,60 @@ describe('metrics background refresh', () => {
|
||||
expect(refresh.onLoading).toHaveBeenLastCalledWith(false);
|
||||
});
|
||||
|
||||
it('preserves successful match reports when fleet or map match data is malformed', async () => {
|
||||
const matches = {
|
||||
started: 3,
|
||||
withRecordedPlayers: 2,
|
||||
averageGroupSize: 1.5,
|
||||
solo: 1,
|
||||
soloShare: 50
|
||||
};
|
||||
const map = {
|
||||
...totals,
|
||||
game: 't5',
|
||||
map: 'Moon',
|
||||
matches,
|
||||
noEmpty: 0,
|
||||
availabilityObserved: 0,
|
||||
availabilityUnknown: 0,
|
||||
noEmptyAtMaximum: 0,
|
||||
noEmptyBelowMaximum: 0,
|
||||
policy: null
|
||||
};
|
||||
const value = { ...report(7), matches, maps: [map] };
|
||||
const invalidMatches = [
|
||||
undefined,
|
||||
null,
|
||||
{ ...matches, withRecordedPlayers: undefined },
|
||||
{ ...matches, started: -1 },
|
||||
{ ...matches, solo: 0.5 },
|
||||
{ ...matches, averageGroupSize: '1.5' },
|
||||
{ ...matches, soloShare: 101 }
|
||||
];
|
||||
const invalid = invalidMatches.flatMap((incomplete) => [
|
||||
{ ...value, matches: incomplete },
|
||||
{ ...value, maps: [{ ...map, matches: incomplete }] }
|
||||
]);
|
||||
const fetcher = vi.fn().mockResolvedValueOnce(Response.json(value));
|
||||
for (const incomplete of invalid) fetcher.mockResolvedValueOnce(Response.json(incomplete));
|
||||
const empty = { ...report(7), maps: [{ ...map, matches: emptyMatches }] };
|
||||
fetcher.mockResolvedValueOnce(Response.json(empty));
|
||||
const refresh = setup(fetcher);
|
||||
await refresh.refresh();
|
||||
expect(refresh.onData).toHaveBeenLastCalledWith(value);
|
||||
for (const _ of invalid) {
|
||||
await refresh.refresh();
|
||||
expect(refresh.onData).toHaveBeenCalledTimes(1);
|
||||
expect(refresh.onError).toHaveBeenLastCalledWith(
|
||||
'The metrics response was incomplete.'
|
||||
);
|
||||
}
|
||||
await refresh.refresh();
|
||||
expect(refresh.onData).toHaveBeenLastCalledWith(empty);
|
||||
expect(refresh.onData).toHaveBeenCalledTimes(2);
|
||||
expect(refresh.onError).toHaveBeenLastCalledWith(null);
|
||||
});
|
||||
|
||||
it('accepts availability reports and rejects incomplete running or policy evidence', async () => {
|
||||
const value = {
|
||||
...report(7),
|
||||
@@ -142,6 +204,7 @@ describe('metrics background refresh', () => {
|
||||
...totals,
|
||||
game: 't5',
|
||||
map: 'Moon',
|
||||
matches: emptyMatches,
|
||||
noEmpty: 0,
|
||||
availabilityObserved: 0,
|
||||
availabilityUnknown: 1,
|
||||
|
||||
Reference in New Issue
Block a user