Files
restitution/tests/unit/CaptureProgressUI.test.js
kaykayyali 8fc45968b5 M2.3 + M2.4 + TeamManager integration: projectile sprites, death handling, build menu, production panel, building placer
- ProjectileSprite.js: physics arcade sprite, faction tint, off-screen culling
- CombatSystem: refactored enemy selection to use TeamManager instead of legacy containers
- Death handling: DYING alpha tween (500ms), smoke puff (300ms), unit:killed event, cleanup
- TeamManager: centralized team registry replacing goodGuys/badGuys containers
- HealthBarSystem, ResourceBar, CaptureProgressUI, BuildMenu, BuildingPlacer, BuildingRenderer, ProductionPanel
- Map_Player: wired new subsystems, removed legacy container creation
- Tests: ProjectileSprite (4), DeathHandling (13), CombatSystem updated

47 tests passed at dev time (M2.3), 158/158 at dev time (M2.4)
2026-06-01 05:18:33 +00:00

137 lines
4.1 KiB
JavaScript

/**
* CaptureProgressUI.test.js -- S4.2: Capture progress world-space HUD
*
* Tests:
* 1. drawBar -- lazily creates Graphics for a CP on first update
* 2. update -- refreshes fill based on getCaptureProgress()
* 3. Color by state: neutral grey, contested yellow, captured green/red
* 4. destroy(cp) cleans up graphics
* 5. shutdown clears all
*/
import CaptureProgressUI from 'Systems/CaptureProgressUI';
function buildMockScene() {
const added = [];
return {
add: {
graphics: jest.fn(() => {
const g = {
clear: jest.fn(),
fillStyle: jest.fn().mockReturnThis(),
fillRect: jest.fn().mockReturnThis(),
fillCircle: jest.fn().mockReturnThis(),
strokeCircle: jest.fn().mockReturnThis(),
lineStyle: jest.fn().mockReturnThis(),
setDepth: jest.fn().mockReturnThis(),
setPosition: jest.fn().mockReturnThis(),
setVisible: jest.fn().mockReturnThis(),
setAlpha: jest.fn().mockReturnThis(),
destroy: jest.fn(),
active: true,
x: 0, y: 0,
};
added.push(g);
return g;
}),
},
_graphicsAdded: added,
};
}
function buildMockCP(state = 'NEUTRAL', progress = 0, owner = null, overrides = {}) {
return {
id: 'cp_test_01',
x: 400,
y: 300,
radiusPx: 80,
active: true,
getCaptureProgress: jest.fn(() => progress),
getState: jest.fn(() => state),
getOwner: jest.fn(() => owner),
zone: { active: true },
...overrides,
};
}
describe('CaptureProgressUI', () => {
let scene;
let ui;
beforeEach(() => {
scene = buildMockScene();
ui = new CaptureProgressUI(scene);
});
afterEach(() => {
ui?.shutdown?.();
});
// -- 1. drawBar lazily creates Graphics --------------------------------
test('update lazily draws a bar for a new CP', () => {
const cp = buildMockCP('NEUTRAL', 0, null);
ui.update(cp);
expect(scene.add.graphics).toHaveBeenCalledTimes(1);
const g = ui._bars.get(cp);
expect(g).toBeDefined();
expect(g.setDepth).toHaveBeenCalled();
});
// -- 2. update refreshes fill based on progress --------------------------
test('bar fill reflects capture progress at 50%', () => {
const cp = buildMockCP('CONTESTED', 50, null);
ui.update(cp);
const g = ui._bars.get(cp);
expect(g.fillStyle).toHaveBeenCalled();
expect(g.fillRect).toHaveBeenCalled();
});
test('bar fill width scales with progress fraction', () => {
const cp = buildMockCP('CONTESTED', 75, null, { radiusPx: 100 });
ui.update(cp);
const g = ui._bars.get(cp);
// Should call fillRect for background + foreground + possibly border
expect(g.fillRect.mock.calls.length).toBeGreaterThanOrEqual(1);
});
// -- 3. Colors by state ------------------------------------------------
test('getColor returns grey for NEUTRAL', () => {
expect(ui.getColor('NEUTRAL')).toBe(0xaaaaaa);
});
test('getColor returns yellow for CONTESTED', () => {
expect(ui.getColor('CONTESTED')).toBe(0xffcc00);
});
test('getColor returns green when captured by player', () => {
expect(ui.getColor('CAPTURED', 'player')).toBe(0x00ff00);
});
test('getColor returns red when captured by enemy', () => {
expect(ui.getColor('CAPTURED', 'enemy')).toBe(0xff3333);
});
// -- 4. destroy(cp) cleans up graphics ---------------------------------
test('destroy(cp) removes bar from Map and destroys graphics', () => {
const cp = buildMockCP('CAPTURED', 100, 'player');
ui.update(cp);
const g = ui._bars.get(cp);
const destroySpy = g.destroy;
ui.destroy(cp);
expect(destroySpy).toHaveBeenCalled();
expect(ui._bars.has(cp)).toBe(false);
});
// -- 5. shutdown clears all --------------------------------------------
test('shutdown destroys all bars and clears Map', () => {
const cp1 = buildMockCP('NEUTRAL', 0);
const cp2 = buildMockCP('CAPTURED', 100, 'player');
ui.update(cp1);
ui.update(cp2);
expect(ui._bars.size).toBe(2);
ui.shutdown();
expect(ui._bars.size).toBe(0);
expect(scene._graphicsAdded.every(g => g.destroy.mock.calls.length > 0)).toBe(true);
});
});