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
@@ -0,0 +1,180 @@
import { describe, it, expect } from 'vitest';
import { processAchievements } from './achievementSystem';
import { createTestState } from '../__test-utils__';
import type { AchievementDefinition } from '@ai-tycoon/shared';
function makeDef(overrides: Partial<AchievementDefinition> = {}): AchievementDefinition {
return {
id: 'ach-1',
name: 'First Million',
description: 'Earn $1,000',
icon: 'money',
condition: { field: 'economy.money', operator: 'gte', value: 1000 },
...overrides,
};
}
describe('processAchievements', () => {
it('returns unchanged state when tickCount is not divisible by 10', () => {
const state = createTestState({
meta: { tickCount: 7 },
economy: { money: 999999 },
});
const defs = [makeDef()];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual([]);
expect(result.achievements).toBe(state.achievements);
});
it('checks achievements when tickCount % 10 === 0', () => {
const state = createTestState({
meta: { tickCount: 10 },
economy: { money: 5000 },
});
const defs = [makeDef({ condition: { field: 'economy.money', operator: 'gte', value: 1000 } })];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual(['First Million']);
expect(result.achievements.unlocked).toHaveLength(1);
expect(result.achievements.unlocked[0]).toMatchObject({ id: 'ach-1', unlockedAtTick: 10 });
});
it('does not unlock when gte condition is not met', () => {
const state = createTestState({
meta: { tickCount: 10 },
economy: { money: 500 },
});
const defs = [makeDef({ condition: { field: 'economy.money', operator: 'gte', value: 1000 } })];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual([]);
expect(result.achievements.unlocked).toHaveLength(0);
});
it('handles gt operator as strictly greater than', () => {
const state = createTestState({
meta: { tickCount: 20 },
economy: { money: 1000 },
});
const defs = [makeDef({ condition: { field: 'economy.money', operator: 'gt', value: 1000 } })];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual([]);
const state2 = createTestState({
meta: { tickCount: 20 },
economy: { money: 1001 },
});
const result2 = processAchievements(state2, defs);
expect(result2.newAchievements).toEqual(['First Million']);
});
it('handles eq operator as exact match', () => {
const state = createTestState({
meta: { tickCount: 30 },
economy: { money: 1000 },
});
const defs = [makeDef({ condition: { field: 'economy.money', operator: 'eq', value: 1000 } })];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual(['First Million']);
const state2 = createTestState({
meta: { tickCount: 30 },
economy: { money: 1001 },
});
const result2 = processAchievements(state2, defs);
expect(result2.newAchievements).toEqual([]);
});
it('does not duplicate already-unlocked achievements', () => {
const state = createTestState({
meta: { tickCount: 20 },
economy: { money: 5000 },
achievements: {
unlocked: [{ id: 'ach-1', unlockedAtTick: 10 }],
progress: {},
},
});
const defs = [makeDef()];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual([]);
expect(result.achievements.unlocked).toHaveLength(1);
});
it('can unlock multiple achievements in one tick', () => {
const state = createTestState({
meta: { tickCount: 10 },
economy: { money: 5000 },
});
const defs = [
makeDef({ id: 'ach-1', name: 'First K', condition: { field: 'economy.money', operator: 'gte', value: 1000 } }),
makeDef({ id: 'ach-2', name: 'Five K', condition: { field: 'economy.money', operator: 'gte', value: 5000 } }),
makeDef({ id: 'ach-3', name: 'Ten K', condition: { field: 'economy.money', operator: 'gte', value: 10000 } }),
];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual(['First K', 'Five K']);
expect(result.achievements.unlocked).toHaveLength(2);
});
it('resolves meta._eraIndex for era-based achievements', () => {
const state = createTestState({
meta: { tickCount: 10, currentEra: 'bigtech' },
});
const defs = [
makeDef({ id: 'era-ach', name: 'Big Tech Era', condition: { field: 'meta._eraIndex', operator: 'gte', value: 2 } }),
];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual(['Big Tech Era']);
});
it('resolves meta._deployedModelCount for deployed model achievements', () => {
const state = createTestState({
meta: { tickCount: 10 },
models: {
baseModels: [
{ isDeployed: true },
{ isDeployed: true },
{ isDeployed: false },
] as any,
},
});
const defs = [
makeDef({ id: 'model-ach', name: 'Two Models', condition: { field: 'meta._deployedModelCount', operator: 'eq', value: 2 } }),
];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual(['Two Models']);
});
it('resolves nested fields like economy.money', () => {
const state = createTestState({
meta: { tickCount: 0 },
economy: { money: 42 },
});
const defs = [
makeDef({ id: 'exact', name: 'Exact 42', condition: { field: 'economy.money', operator: 'eq', value: 42 } }),
];
const result = processAchievements(state, defs);
expect(result.newAchievements).toEqual(['Exact 42']);
});
});