Add Vitest test suite with 184 tests covering all game engine systems
Balance Check / balance-simulation (push) Successful in 7m0s
Balance Check / multi-run-balance (push) Failing after 20m5s
CI / build-and-push (push) Successful in 1m18s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 09:41:56 -04:00
parent 1f50f6c86c
commit a8746246f8
29 changed files with 3966 additions and 6 deletions
+139
View File
@@ -0,0 +1,139 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { processTick, setAchievementDefinitions } from './tick';
import { createTestState, createSeededRNG } from './__test-utils__';
import { ACHIEVEMENT_DEFINITIONS } from './data/achievements';
import { resetResearchBonusCache } from './systems/researchBonuses';
const rng = createSeededRNG(42);
beforeEach(() => {
rng.install();
resetResearchBonusCache();
setAchievementDefinitions(ACHIEVEMENT_DEFINITIONS);
});
afterEach(() => rng.uninstall());
describe('processTick', () => {
it('returns a valid partial state from initial state', () => {
const state = createTestState();
const result = processTick(state);
expect(result.meta).toBeDefined();
expect(result.economy).toBeDefined();
expect(result.infrastructure).toBeDefined();
expect(result.compute).toBeDefined();
expect(result.research).toBeDefined();
expect(result.models).toBeDefined();
expect(result.market).toBeDefined();
expect(result.talent).toBeDefined();
expect(result.reputation).toBeDefined();
expect(result.data).toBeDefined();
expect(result.competitors).toBeDefined();
expect(result.achievements).toBeDefined();
});
it('increments tickCount by 1', () => {
const state = createTestState({ meta: { tickCount: 100 } });
const result = processTick(state);
expect(result.meta!.tickCount).toBe(101);
});
it('increments totalPlayTime by 1', () => {
const state = createTestState({ meta: { totalPlayTime: 500 } });
const result = processTick(state);
expect(result.meta!.totalPlayTime).toBe(501);
});
it('preserves money when no revenue or expenses', () => {
const state = createTestState({ economy: { money: 600_000 } });
const result = processTick(state);
expect(result.economy!.money).toBeGreaterThanOrEqual(0);
});
it('attaches notifications array', () => {
const state = createTestState();
const result = processTick(state);
const notifications = (result as Record<string, unknown>)['_notifications'];
expect(Array.isArray(notifications)).toBe(true);
});
it('generates era transition notification when thresholds met', () => {
const deployedModel = {
id: 'model-1', familyId: 'fam-1', name: 'Test v1',
architecture: { type: 'dense' as const, totalParameters: 7e9, activeParameters: 7e9, contextWindow: 8192, vocabularySize: 32000 },
rawCapability: 20, capabilities: { reasoning: 20, coding: 20, creative: 20, math: 20, knowledge: 20, multimodal: 0, agents: 10, speed: 50, contextUtilization: 50 },
safetyProfile: { overallSafety: 50, refusalRate: 0.05, harmAvoidance: 50, instructionFollowing: 50, honesty: 50 },
isDeployed: true, trainedAtTick: 0, trainingCostTotal: 0, trainingStagesCompleted: ['pretraining' as const],
sizeTier: 'small' as const, version: 1.0, sftSpecializations: ['general' as const], alignmentMethod: 'rlhf' as const,
dataMix: { web: 0.4, code: 0.2, books: 0.15, academic: 0.1, conversational: 0.1, specialized: 0.05 },
benchmarkResults: {},
};
const state = createTestState({
meta: { currentEra: 'startup' },
economy: { totalRevenue: 10_000 },
models: { bestDeployedModelScore: 20, bestDeployedSafetyScore: 50, baseModels: [deployedModel], families: [] },
reputation: { score: 50, safetyRecord: 60, publicPerception: 50, employeeSatisfaction: 50, regulatoryStanding: 50 },
});
const result = processTick(state);
expect(result.meta!.currentEra).toBe('scaleup');
const notifications = (result as Record<string, unknown>)['_notifications'] as Array<{ title: string }>;
expect(notifications.some(n => n.title === 'Era Transition!')).toBe(true);
});
it('does not transition era when thresholds not met', () => {
const state = createTestState({
meta: { currentEra: 'startup' },
economy: { totalRevenue: 100 },
models: { bestDeployedModelScore: 5 },
reputation: { score: 20 },
});
const result = processTick(state);
expect(result.meta!.currentEra).toBe('startup');
});
it('recomputes valuation each tick', () => {
const state = createTestState({
economy: { revenuePerTick: 10 },
market: { consumerTiers: { totalUsers: 100 } },
models: { bestDeployedModelScore: 30 },
});
const result = processTick(state);
expect(result.economy!.funding.valuation).toBeGreaterThan(0);
});
it('research completion generates notification', () => {
const state = createTestState({
research: {
activeResearch: {
researchId: 'advanced-cooling',
progressTicks: 59,
totalTicks: 60,
allocatedResearchers: 1,
allocatedCompute: 5,
},
researchQueue: [],
completedResearch: [],
researchPoints: 0,
},
talent: {
departments: {
research: { headcount: 1, effectiveness: 0.5 },
},
},
});
const result = processTick(state);
const notifications = (result as Record<string, unknown>)['_notifications'] as Array<{ title: string }>;
expect(notifications.some(n => n.title === 'Research Complete')).toBe(true);
expect(result.research!.completedResearch).toContain('advanced-cooling');
});
it('multiple ticks are stable (no crash on sequential processing)', () => {
let state = createTestState();
for (let i = 0; i < 10; i++) {
const result = processTick(state);
state = { ...state, ...result };
}
expect(state.meta.tickCount).toBe(10);
expect(state.economy.money).toBeGreaterThanOrEqual(0);
});
});