Files
restitution/tests/EconomySystem.test.js
root 2e07519648 Refactor: Component-based architecture + 10 sub-systems
- Implemented 10 sub-systems (Economy, Pathfinding, Combat, Selection, Network, Map, Entity/Building/ControlPoint state machines, Orchestrator)
- Refactored Custom_Entity.js → Unit.js with 5 components (health, owner, inventory, movement, combat)
- Added Jest test suite with 100+ tests (EconomySystem 100%, EntityStateMachine 100%, PathfindingSystem 99%, Unit.js 72%)
- All webpack builds pass (0 errors)
- BMAD-auto team-respawn flow: 10 parallel sub-agents implemented systems

Architecture: Phaser 3 + XState + socket.io + EasyStar
Mode: team-respawn
Model: custom/ollama-cloud-pro
2026-05-29 22:13:44 +00:00

152 lines
4.6 KiB
JavaScript

/**
* EconomySystem Unit Tests
*/
import EconomySystem from '../src/systems/EconomySystem';
// Mock Phaser Scene
const createMockScene = () => ({
events: {
emit: jest.fn(),
on: jest.fn()
}
});
describe('EconomySystem', () => {
let scene;
let economy;
beforeEach(() => {
scene = createMockScene();
economy = new EconomySystem(scene);
});
describe('initPlayer', () => {
it('should initialize player with default resources', () => {
economy.initPlayer('player1');
const resources = economy.getResources('player1');
expect(resources.fuel).toBe(100);
expect(resources.ammo).toBe(100);
expect(resources.capturePoints).toBe(0);
});
it('should initialize player with custom resources', () => {
economy.initPlayer('player1', { fuel: 200, ammo: 50, capturePoints: 10 });
const resources = economy.getResources('player1');
expect(resources.fuel).toBe(200);
expect(resources.ammo).toBe(50);
expect(resources.capturePoints).toBe(10);
});
});
describe('canAfford', () => {
beforeEach(() => {
economy.initPlayer('player1', { fuel: 100, ammo: 50 });
});
it('should return true when player has enough resources', () => {
expect(economy.canAfford('player1', { fuel: 50, ammo: 25 })).toBe(true);
});
it('should return false when player lacks fuel', () => {
expect(economy.canAfford('player1', { fuel: 150, ammo: 25 })).toBe(false);
});
it('should return false when player lacks ammo', () => {
expect(economy.canAfford('player1', { fuel: 50, ammo: 100 })).toBe(false);
});
it('should return false for non-existent player', () => {
expect(economy.canAfford('player2', { fuel: 10 })).toBe(false);
});
});
describe('deduct', () => {
beforeEach(() => {
economy.initPlayer('player1', { fuel: 100, ammo: 50 });
});
it('should deduct resources and return true', () => {
const result = economy.deduct('player1', { fuel: 30, ammo: 20 });
const resources = economy.getResources('player1');
expect(result).toBe(true);
expect(resources.fuel).toBe(70);
expect(resources.ammo).toBe(30);
});
it('should not deduct and return false when insufficient resources', () => {
const result = economy.deduct('player1', { fuel: 150, ammo: 20 });
const resources = economy.getResources('player1');
expect(result).toBe(false);
expect(resources.fuel).toBe(100); // Unchanged
expect(resources.ammo).toBe(50); // Unchanged
});
it('should emit economy:purchaseFailed on insufficient resources', () => {
economy.deduct('player1', { fuel: 150, ammo: 20 });
expect(scene.events.emit).toHaveBeenCalledWith(
'economy:purchaseFailed',
expect.objectContaining({ playerId: 'player1', reason: expect.any(String) })
);
});
});
describe('addIncome', () => {
it('should add income to player resources', () => {
economy.initPlayer('player1', { fuel: 100, ammo: 50 });
economy.addIncome('player1', { fuel: 25, ammo: 10, capturePoints: 5 });
const resources = economy.getResources('player1');
expect(resources.fuel).toBe(125);
expect(resources.ammo).toBe(60);
expect(resources.capturePoints).toBe(5);
});
it('should auto-initialize player if not exists', () => {
economy.addIncome('player2', { fuel: 50 });
const resources = economy.getResources('player2');
expect(resources.fuel).toBe(50);
});
it('should emit economy:incomeReceived and economy:updated', () => {
economy.initPlayer('player1');
economy.addIncome('player1', { fuel: 10 });
expect(scene.events.emit).toHaveBeenCalledWith(
'economy:incomeReceived',
expect.objectContaining({ playerId: 'player1' })
);
expect(scene.events.emit).toHaveBeenCalledWith(
'economy:updated',
expect.objectContaining({ playerId: 'player1' })
);
});
});
describe('update', () => {
it('should call addIncome every 1000ms', () => {
const addIncomeSpy = jest.spyOn(economy, 'addIncome');
// First call at 1000ms
economy.update(1000, 1000);
expect(addIncomeSpy).toHaveBeenCalled();
// Second call at 2000ms
economy.update(2000, 1000);
expect(addIncomeSpy).toHaveBeenCalledTimes(2);
});
it('should not call addIncome before 1000ms', () => {
const addIncomeSpy = jest.spyOn(economy, 'addIncome');
economy.update(500, 500);
expect(addIncomeSpy).not.toHaveBeenCalled();
});
});
});