aether-shards/test/managers/MissionManager.test.js

182 lines
6.1 KiB
JavaScript
Raw Normal View History

import { expect } from "@esm-bundle/chai";
import sinon from "sinon";
import { MissionManager } from "../../src/managers/MissionManager.js";
import { narrativeManager } from "../../src/managers/NarrativeManager.js";
describe("Manager: MissionManager", () => {
let manager;
let mockNarrativeManager;
beforeEach(() => {
manager = new MissionManager();
// Mock narrativeManager
mockNarrativeManager = {
startSequence: sinon.stub(),
addEventListener: sinon.stub(),
removeEventListener: sinon.stub(),
};
// Replace the singleton reference in the manager if possible
// Since it's imported, we'll need to stub the methods we use
sinon.stub(narrativeManager, "startSequence");
sinon.stub(narrativeManager, "addEventListener");
sinon.stub(narrativeManager, "removeEventListener");
});
afterEach(() => {
sinon.restore();
});
it("CoA 1: Should initialize with tutorial mission registered", () => {
expect(manager.missionRegistry.has("MISSION_TUTORIAL_01")).to.be.true;
expect(manager.activeMissionId).to.be.null;
expect(manager.completedMissions).to.be.instanceof(Set);
});
it("CoA 2: registerMission should add mission to registry", () => {
const newMission = {
id: "MISSION_TEST_01",
config: { title: "Test Mission" },
objectives: { primary: [] },
};
manager.registerMission(newMission);
expect(manager.missionRegistry.has("MISSION_TEST_01")).to.be.true;
expect(manager.missionRegistry.get("MISSION_TEST_01")).to.equal(newMission);
});
it("CoA 3: getActiveMission should return tutorial if no active mission", () => {
const mission = manager.getActiveMission();
expect(mission).to.exist;
expect(mission.id).to.equal("MISSION_TUTORIAL_01");
});
it("CoA 4: getActiveMission should return active mission if set", () => {
const testMission = {
id: "MISSION_TEST_01",
config: { title: "Test" },
objectives: { primary: [] },
};
manager.registerMission(testMission);
manager.activeMissionId = "MISSION_TEST_01";
const mission = manager.getActiveMission();
expect(mission.id).to.equal("MISSION_TEST_01");
});
it("CoA 5: setupActiveMission should initialize objectives", () => {
const mission = manager.getActiveMission();
mission.objectives = {
primary: [
{ type: "ELIMINATE_ALL", target_count: 5 },
{ type: "ELIMINATE_UNIT", target_def_id: "ENEMY_GOBLIN", target_count: 3 },
],
};
manager.setupActiveMission();
expect(manager.currentObjectives).to.have.length(2);
expect(manager.currentObjectives[0].current).to.equal(0);
expect(manager.currentObjectives[0].complete).to.be.false;
expect(manager.currentObjectives[1].target_count).to.equal(3);
});
it("CoA 6: onGameEvent should update ELIMINATE_ALL objectives", () => {
manager.setupActiveMission();
manager.currentObjectives = [
{ type: "ELIMINATE_ALL", target_count: 3, current: 0, complete: false },
];
manager.onGameEvent("ENEMY_DEATH", { unitId: "ENEMY_1" });
manager.onGameEvent("ENEMY_DEATH", { unitId: "ENEMY_2" });
manager.onGameEvent("ENEMY_DEATH", { unitId: "ENEMY_3" });
expect(manager.currentObjectives[0].current).to.equal(3);
expect(manager.currentObjectives[0].complete).to.be.true;
});
it("CoA 7: onGameEvent should update ELIMINATE_UNIT objectives for specific unit", () => {
manager.setupActiveMission();
manager.currentObjectives = [
{
type: "ELIMINATE_UNIT",
target_def_id: "ENEMY_GOBLIN",
target_count: 2,
current: 0,
complete: false,
},
];
manager.onGameEvent("ENEMY_DEATH", { unitId: "ENEMY_GOBLIN" });
manager.onGameEvent("ENEMY_DEATH", { unitId: "ENEMY_OTHER" }); // Should not count
manager.onGameEvent("ENEMY_DEATH", { unitId: "ENEMY_GOBLIN" });
expect(manager.currentObjectives[0].current).to.equal(2);
expect(manager.currentObjectives[0].complete).to.be.true;
});
it("CoA 8: checkVictory should dispatch mission-victory event when all objectives complete", () => {
const victorySpy = sinon.spy();
window.addEventListener("mission-victory", victorySpy);
manager.setupActiveMission();
manager.currentObjectives = [
{ type: "ELIMINATE_ALL", target_count: 2, current: 2, complete: true },
];
manager.activeMissionId = "MISSION_TUTORIAL_01";
manager.checkVictory();
expect(victorySpy.called).to.be.true;
expect(manager.completedMissions.has("MISSION_TUTORIAL_01")).to.be.true;
window.removeEventListener("mission-victory", victorySpy);
});
it("CoA 9: completeActiveMission should add mission to completed set", () => {
manager.activeMissionId = "MISSION_TUTORIAL_01";
manager.completeActiveMission();
expect(manager.completedMissions.has("MISSION_TUTORIAL_01")).to.be.true;
});
it("CoA 10: load should restore completed missions", () => {
const saveData = {
completedMissions: ["MISSION_TUTORIAL_01", "MISSION_TEST_01"],
};
manager.load(saveData);
expect(manager.completedMissions.has("MISSION_TUTORIAL_01")).to.be.true;
expect(manager.completedMissions.has("MISSION_TEST_01")).to.be.true;
});
it("CoA 11: save should serialize completed missions", () => {
manager.completedMissions.add("MISSION_TUTORIAL_01");
manager.completedMissions.add("MISSION_TEST_01");
const saved = manager.save();
expect(saved.completedMissions).to.be.an("array");
expect(saved.completedMissions).to.include("MISSION_TUTORIAL_01");
expect(saved.completedMissions).to.include("MISSION_TEST_01");
});
it("CoA 12: _mapNarrativeIdToFileName should convert narrative IDs to filenames", () => {
expect(manager._mapNarrativeIdToFileName("NARRATIVE_TUTORIAL_INTRO")).to.equal(
"tutorial_intro"
);
expect(manager._mapNarrativeIdToFileName("NARRATIVE_TUTORIAL_SUCCESS")).to.equal(
"tutorial_success"
);
// The implementation converts NARRATIVE_UNKNOWN to narrative_unknown (lowercase with NARRATIVE_ prefix removed)
expect(manager._mapNarrativeIdToFileName("NARRATIVE_UNKNOWN")).to.equal("narrative_unknown");
});
});