aether-shards/test/core/GameStateManager.test.js
Matthew Mone ac0f3cc396 Enhance testing and integration of inventory and character management systems
Add comprehensive tests for the InventoryManager and InventoryContainer to validate item management functionalities. Implement integration tests for the CharacterSheet component, ensuring proper interaction with the inventory system. Update the Explorer class to support new inventory features and maintain backward compatibility. Refactor related components for improved clarity and performance.
2025-12-27 16:54:03 -08:00

149 lines
4.7 KiB
JavaScript

import { expect } from "@esm-bundle/chai";
import sinon from "sinon";
// Import the singleton instance AND the class for constants
import {
gameStateManager,
GameStateManager,
} from "../../src/core/GameStateManager.js";
describe("Core: GameStateManager (Singleton)", () => {
let mockPersistence;
let mockGameLoop;
beforeEach(() => {
// 1. Reset Singleton State
gameStateManager.reset();
// 2. Mock Persistence
mockPersistence = {
init: sinon.stub().resolves(),
saveRun: sinon.stub().resolves(),
loadRun: sinon.stub().resolves(null),
loadRoster: sinon.stub().resolves(null),
saveRoster: sinon.stub().resolves(),
};
// Inject Mock (replacing the real Persistence instance)
gameStateManager.persistence = mockPersistence;
// 3. Mock GameLoop
mockGameLoop = {
init: sinon.spy(),
startLevel: sinon.spy(),
stop: sinon.spy(),
};
// 4. Mock MissionManager
gameStateManager.missionManager = {
setupActiveMission: sinon.stub(),
getActiveMission: sinon.stub().returns({
id: "MISSION_TUTORIAL_01",
config: { title: "Test Mission" },
biome: {
generator_config: {
seed_type: "RANDOM",
seed: 12345,
},
},
objectives: [],
}),
playIntro: sinon.stub().resolves(),
};
});
it("CoA 1: Should initialize and transition to MAIN_MENU", async () => {
const eventSpy = sinon.spy();
window.addEventListener("gamestate-changed", eventSpy);
await gameStateManager.init();
expect(mockPersistence.init.calledOnce).to.be.true;
expect(gameStateManager.currentState).to.equal(
GameStateManager.STATES.MAIN_MENU
);
expect(eventSpy.called).to.be.true;
});
it("CoA 2: startNewGame should transition to TEAM_BUILDER", async () => {
await gameStateManager.init();
gameStateManager.startNewGame();
expect(gameStateManager.currentState).to.equal(
GameStateManager.STATES.TEAM_BUILDER
);
});
it("CoA 3: handleEmbark should initialize run, save, and start engine", async () => {
// Mock RosterManager.recruitUnit to return async unit with generated name
const mockRecruitedUnit = {
id: "UNIT_123",
name: "Valerius", // Generated character name
className: "Vanguard", // Class name
classId: "CLASS_VANGUARD",
};
gameStateManager.rosterManager.recruitUnit = sinon.stub().resolves(mockRecruitedUnit);
gameStateManager.setGameLoop(mockGameLoop);
await gameStateManager.init();
const mockSquad = [{ id: "u1", isNew: false }]; // Existing unit, not new
// Mock startLevel to resolve immediately
mockGameLoop.startLevel = sinon.stub().resolves();
// Await the full async chain
await gameStateManager.handleEmbark({ detail: { squad: mockSquad, mode: "SELECT" } });
expect(gameStateManager.currentState).to.equal(
GameStateManager.STATES.DEPLOYMENT
);
expect(mockPersistence.saveRun.calledWith(gameStateManager.activeRunData))
.to.be.true;
expect(mockGameLoop.startLevel.calledWith(gameStateManager.activeRunData))
.to.be.true;
});
it("CoA 3b: handleEmbark should dispatch run-data-updated event", async () => {
// Mock RosterManager.recruitUnit
const mockRecruitedUnit = {
id: "UNIT_123",
name: "Valerius",
className: "Vanguard",
classId: "CLASS_VANGUARD",
};
gameStateManager.rosterManager.recruitUnit = sinon.stub().resolves(mockRecruitedUnit);
gameStateManager.setGameLoop(mockGameLoop);
await gameStateManager.init();
const mockSquad = [{ id: "u1", isNew: true, name: "Vanguard", classId: "CLASS_VANGUARD" }];
mockGameLoop.startLevel = sinon.stub().resolves();
let eventDispatched = false;
let eventData = null;
window.addEventListener("run-data-updated", (e) => {
eventDispatched = true;
eventData = e.detail.runData;
});
await gameStateManager.handleEmbark({ detail: { squad: mockSquad, mode: "DRAFT" } });
expect(eventDispatched).to.be.true;
expect(eventData).to.exist;
expect(eventData.squad).to.exist;
expect(eventData.squad[0].name).to.equal("Valerius");
expect(eventData.squad[0].className).to.equal("Vanguard");
});
it("CoA 4: continueGame should load save and resume engine", async () => {
gameStateManager.setGameLoop(mockGameLoop);
const savedData = { seed: 999, depth: 5, squad: [] };
mockPersistence.loadRun.resolves(savedData);
await gameStateManager.init();
await gameStateManager.continueGame();
expect(mockPersistence.loadRun.called).to.be.true;
expect(gameStateManager.activeRunData).to.deep.equal(savedData);
expect(mockGameLoop.startLevel.calledWith(savedData)).to.be.true;
});
});