Group settings with explicit modes and one save action

This commit is contained in:
2026-10-07 19:06:56 -04:00
parent e4f37f6964
commit bab78038dc
7 changed files with 425 additions and 78 deletions
+51 -1
View File
@@ -2,7 +2,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { newFixture, type Fixture } from '../helpers/fixture.js';
let fixture: Fixture;
import { defaultFleetSettings as defaults } from '../../src/lib/fleet-settings.js';
import { defaultFleetSettings as defaults, additionalConcurrencyKeys, fleetSettingLabels, settingDisplayValue, settingHelp,
settingMinimum, settingsGroups, settingUnit, settingZeroMode, validateFleetSettings, type FleetSettings } from '../../src/lib/fleet-settings.js';
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture([]);
@@ -139,3 +140,52 @@ it('saves a section without overwriting changes in the other section', async ()
expect(response.status).toBe(200);
expect(await GET().json()).toMatchObject({ deployKeepDays: 42, rebuildConcurrency: 2 });
});
describe('settings presentation semantics', () => {
it('places every saved setting in exactly one searchable group', () => {
const grouped = settingsGroups.flatMap(group => group.keys);
expect(grouped.length).toBe(Object.keys(defaults).length);
expect(new Set(grouped).size).toBe(grouped.length);
expect([...grouped].sort()).toEqual(Object.keys(defaults).sort());
expect(settingsGroups.map(group => group.title)).toEqual([
'Concurrency', 'Operation history', 'Matches & players', 'Telemetry & metrics', 'Files & versions', 'Accounts & audit'
]);
});
it('distinguishes an unlimited cap from permanent retention, age expiry, and minimum counts', () => {
for (const key of [...additionalConcurrencyKeys, 'telemetryMaxPerServer', 'telemetryMaxTotal'] as (keyof FleetSettings)[]) {
expect(settingZeroMode(key)).toBe('No limit');
}
for (const key of Object.keys(defaults) as (keyof FleetSettings)[]) {
if (key.endsWith('Days') && !['versionKeepDays', 'gameFileGraceDays'].includes(key)) expect(settingZeroMode(key)).toBe('Forever');
if (settingMinimum(key) === 1) expect(settingZeroMode(key)).toBeNull();
}
expect(settingZeroMode('versionKeepDays')).toBe('No age expiry');
expect(settingZeroMode('gameFileGraceDays')).toBe('No delay');
expect(settingZeroMode('versionKeepCount')).toBe('No minimum');
expect(settingZeroMode('historyKeepCount')).toBe('No minimum');
expect(settingHelp.versionKeepDays).toContain('version count policy may still remove');
expect(settingHelp.versionKeepCount).toContain('a positive count removes older unused versions');
});
it('formats numeric values and defaults without changing their stored meaning', () => {
const original = structuredClone(defaults);
for (const key of Object.keys(defaults) as (keyof FleetSettings)[]) {
const zero = settingZeroMode(key);
if (zero) {
expect(settingDisplayValue(key, 0)).toBe(zero);
expect(validateFleetSettings({ ...defaults, [key]: 0 })[key]).toBe(0);
}
expect(settingDisplayValue(key, 1)).toBe(`1 ${settingUnit(key).slice(0, -1)}`);
expect(settingDisplayValue(key, 14)).toBe(`14 ${settingUnit(key)}`);
expect(validateFleetSettings({ ...defaults, [key]: 14 })[key]).toBe(14);
}
expect(settingDisplayValue('telemetryMaxTotal', 10_000)).toBe('10,000 records');
expect(settingDisplayValue('preparationConcurrency', 2)).toBe('2 hosts');
expect(settingDisplayValue('versionKeepCount', 1)).toBe('1 version');
expect(settingDisplayValue('matchKeepDays', NaN)).toBe('—');
expect(defaults).toEqual(original);
expect(fleetSettingLabels.destroyConcurrency).toBe('Concurrent server removals');
expect(fleetSettingLabels.destroyConcurrencyPerHost).toBe('Concurrent server removals per host');
});
});