import { describe, expect, it } from 'vitest'; import { metricRecommendations } from '../../src/lib/metrics-insights.js'; import type { MapMetrics } from '../../src/lib/metrics.js'; const map = (values: Partial = {}): MapMetrics => ({ game: 't5', map: 'Moon', observed: 10, active: 5, idle: 5, unknown: 0, playerHours: 10, full: 0, capacityObserved: 5, ...values }); describe('advisory hosting experiments', () => { it('uses map capacity time rather than summed server time for expansion', () => { const [result] = metricRecommendations([map({ observed: 100, active: 50, idle: 50, full: 1, capacityObserved: 4 })]); expect(result.kind).toBe('expand'); expect(result.evidence).toContain('25.0%'); expect(result.tentative).toBe(false); }); it('offers a tentative trial even with a tiny recorded sample', () => { const [result] = metricRecommendations([map({ observed: 1 / 120, active: 1 / 120, idle: 0, full: 1 / 120, capacityObserved: 1 / 120 })]); expect(result.kind).toBe('expand'); expect(result.tentative).toBe(true); expect(result.evidence).toContain('30 s'); }); it('uses explicitly tentative occupancy advice when capacity is missing', () => { const [result] = metricRecommendations([map({ active: 8, idle: 2, capacityObserved: 0 })]); expect(result.kind).toBe('expand'); expect(result.tentative).toBe(true); expect(result.reason).toContain('not evidence of saturation'); }); it('does not confuse unknown occupancy with an idle fleet', () => { const [result] = metricRecommendations([map({ observed: 0, active: 0, idle: 0, unknown: 10, playerHours: 0, capacityObserved: 0 })]); expect(result.kind).toBe('capacity'); expect(result.title).toBe('Check occupancy reporting'); expect(result.tentative).toBe(true); }); it('keeps advice scoped to input maps and considers idle trials with incomplete capacity', () => { const [result] = metricRecommendations([map({ game: 't6', map: 'Town', active: 1, idle: 9, capacityObserved: 0 })]); expect(result).toMatchObject({ game: 't6', map: 'Town', kind: 'consolidate', tentative: true }); expect(result.reason).toContain('preserve access'); expect(metricRecommendations([])).toEqual([]); }); it('distinguishes a zero-duration sample from failed occupancy reporting', () => { const [result] = metricRecommendations([map({ observed: 0, active: 0, idle: 0, playerHours: 0, capacityObserved: 0 })]); expect(result.title).toBe('Let observations accumulate'); expect(result.reason).toContain('no elapsed observations'); }); it('leaves the lineup alone when measured evidence does not trigger a rule', () => { expect(metricRecommendations([map({ active: 9, idle: 1, full: 0 })])[0].kind).toBe('watch'); }); });