181 lines
6.1 KiB
JavaScript
181 lines
6.1 KiB
JavaScript
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");
|
|
});
|
|
});
|
|
|