179 lines
6.4 KiB
JavaScript
179 lines
6.4 KiB
JavaScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
vi.mock("../../src/ollamaClient.js", () => ({ callOllama: vi.fn() }));
|
|
|
|
const { callOllama } = await import("../../src/ollamaClient.js");
|
|
const { generateDungeon } = await import("../../src/dungeonGenerator.js");
|
|
|
|
describe("generateDungeon (mocked Ollama)", () => {
|
|
beforeEach(() => {
|
|
vi.mocked(callOllama)
|
|
.mockResolvedValueOnce(
|
|
"1. Dark Hall\n2. Lost Mines\n3. Shadow Keep"
|
|
)
|
|
.mockResolvedValueOnce(
|
|
"Central Conflict: The power source fails. Primary Faction: The Guard. Dynamic Element: Temporal rifts."
|
|
)
|
|
.mockResolvedValueOnce(
|
|
"Description:\nA dark place under the earth.\nHooks & Rumors:\n1. A merchant vanished near the entrance.\n2. Strange lights in the depths.\n3. The Guard seeks the artifact.\n4. Rifts cause brief time skips."
|
|
)
|
|
.mockResolvedValueOnce(
|
|
"1. Entrance Hall: A dark entrance with torches and damp walls. Pillars offer cover. The air smells of earth.\n2. Climax Chamber: The final room where the power source pulses. The Guard holds the artifact. Multiple approaches possible."
|
|
)
|
|
.mockResolvedValueOnce(
|
|
`Locations:
|
|
1. Corridor: A long corridor with flickering lights.
|
|
2. Chamber: A side chamber with debris.
|
|
3. Shrine: A small shrine to the old gods.
|
|
|
|
Encounters:
|
|
1. Patrol: Hall: Guard patrol passes through.
|
|
2. Rift: Corridor: A temporal rift causes disorientation.
|
|
3. Ambush: Chamber: Bandits lie in wait.
|
|
4. Guardian: Shrine: A warden challenges intruders.
|
|
5. Boss: Climax Chamber: The leader defends the artifact.
|
|
6. Trap: Corridor: A pressure plate triggers darts.
|
|
|
|
NPCs:
|
|
1. Captain: Leader of the Guard, stern and duty-bound.
|
|
2. Scout: Young scout, curious about the rifts.
|
|
3. Priest: Keeper of the shrine, knows old lore.
|
|
4. Merchant: Survivor who lost his cargo.
|
|
|
|
Treasures:
|
|
1. Artifact: The power source core.
|
|
2. Journal: Captain's log with tactical notes.
|
|
3. Key: Opens the climax chamber.
|
|
4. Gem: A glowing temporal crystal.
|
|
|
|
Random Events:
|
|
1. Rift Shift: Time skips forward one hour.
|
|
2. Guard Patrol: A patrol approaches.
|
|
3. Echo: Voices from the past echo.
|
|
4. Light Flicker: Lights go out for a moment.
|
|
5. Distant Cry: Someone calls for help.
|
|
6. Dust Fall: Ceiling dust falls, revealing a hidden symbol.`
|
|
)
|
|
.mockResolvedValueOnce(
|
|
"1. The adventurers could ally with the Guard and secure the artifact.\n2. They might destroy the source and end the rifts.\n3. They could bargain with the faction for passage.\n4. They might flee and seal the entrance."
|
|
);
|
|
});
|
|
|
|
it("returns dungeon data with all required fields", async () => {
|
|
const result = await generateDungeon();
|
|
expect(result).toBeDefined();
|
|
expect(result.title).toBeTruthy();
|
|
expect(result.flavor).toBeTruthy();
|
|
expect(result.hooksRumors).toBeDefined();
|
|
expect(Array.isArray(result.rooms)).toBe(true);
|
|
expect(Array.isArray(result.encounters)).toBe(true);
|
|
expect(Array.isArray(result.npcs)).toBe(true);
|
|
expect(Array.isArray(result.treasure)).toBe(true);
|
|
expect(Array.isArray(result.randomEvents)).toBe(true);
|
|
expect(Array.isArray(result.plotResolutions)).toBe(true);
|
|
}, 10000);
|
|
|
|
});
|
|
|
|
describe("generateDungeon with fewer items (mocked Ollama)", () => {
|
|
beforeEach(() => {
|
|
vi.mocked(callOllama)
|
|
.mockResolvedValueOnce("1. Dark Hall\n2. Lost Mines")
|
|
.mockResolvedValueOnce("Central Conflict: War. Primary Faction: Guard. Dynamic Element: Magic.")
|
|
.mockResolvedValueOnce("Description: A place.\nHooks & Rumors:\n1. One.\n2. Two.\n3. Three.\n4. Four.")
|
|
.mockResolvedValueOnce("1. Entrance: First room.\n2. Climax: Final room.")
|
|
.mockResolvedValueOnce(
|
|
`Locations:
|
|
1. Corridor: A corridor.
|
|
2. Chamber: A chamber.
|
|
|
|
Encounters:
|
|
1. Patrol: Corridor: A patrol.
|
|
2. Ambush: Chamber: Bandits.
|
|
|
|
NPCs:
|
|
1. Captain: Leader.
|
|
2. Scout: Scout.
|
|
|
|
Treasures:
|
|
1. Gold: Coins.
|
|
2. Gem: A gem.
|
|
|
|
Random Events:
|
|
1. Rift Shift: Time skips.
|
|
2. Guard Patrol: Patrol approaches.`
|
|
)
|
|
.mockResolvedValueOnce("1. The adventurers could win.\n2. They might flee.");
|
|
});
|
|
|
|
it("pads random events and encounters when step 5 returns fewer than 6", async () => {
|
|
const result = await generateDungeon();
|
|
expect(result.randomEvents.length).toBe(6);
|
|
expect(result.encounters.length).toBe(6);
|
|
expect(result.npcs.length).toBeGreaterThanOrEqual(4);
|
|
}, 10000);
|
|
|
|
it("builds six encounters from scratch when step 5 returns none", async () => {
|
|
vi.mocked(callOllama)
|
|
.mockResolvedValueOnce("1. Dark Hall\n2. Lost Mines")
|
|
.mockResolvedValueOnce("Central Conflict: War. Primary Faction: Guard. Dynamic Element: Magic.")
|
|
.mockResolvedValueOnce("Description: A place.\nHooks & Rumors:\n1. One.\n2. Two.\n3. Three.\n4. Four.")
|
|
.mockResolvedValueOnce("1. Entrance: First room.\n2. Climax: Final room.")
|
|
.mockResolvedValueOnce(
|
|
`Locations:
|
|
1. Corridor: A corridor.
|
|
2. Chamber: A chamber.
|
|
|
|
Encounters:
|
|
|
|
NPCs:
|
|
1. Captain: Leader.
|
|
|
|
Treasures:
|
|
1. Gold: Coins.
|
|
|
|
Random Events:
|
|
1. Rift: Time skips.`
|
|
)
|
|
.mockResolvedValueOnce("1. The adventurers could win.");
|
|
const result = await generateDungeon();
|
|
expect(result.encounters.length).toBe(6);
|
|
expect(result.encounters.every((e) => e.name && e.details)).toBe(true);
|
|
}, 10000);
|
|
|
|
it("handles random events with no colon and short text (fallback name)", async () => {
|
|
vi.mocked(callOllama)
|
|
.mockResolvedValueOnce("1. Dark Hall\n2. Lost Mines")
|
|
.mockResolvedValueOnce("Central Conflict: War. Primary Faction: Guard. Dynamic Element: Magic.")
|
|
.mockResolvedValueOnce("Description: A place.\nHooks & Rumors:\n1. One.\n2. Two.\n3. Three.\n4. Four.")
|
|
.mockResolvedValueOnce("1. Entrance: First room.\n2. Climax: Final room.")
|
|
.mockResolvedValueOnce(
|
|
`Locations:
|
|
1. Corridor: A corridor.
|
|
2. Chamber: A chamber.
|
|
|
|
Encounters:
|
|
1. Patrol: Corridor: A patrol.
|
|
2. Ambush: Chamber: Bandits.
|
|
|
|
NPCs:
|
|
1. Captain: Leader.
|
|
2. Scout: Scout.
|
|
|
|
Treasures:
|
|
1. Gold: Coins.
|
|
2. Gem: A gem.
|
|
|
|
Random Events:
|
|
1. One two three
|
|
2. Event Name: Placeholder event
|
|
3. Rift Shift Time Skips Forward One Hour
|
|
4. Rift Shift: Time skips forward one hour.`
|
|
)
|
|
.mockResolvedValueOnce("1. The adventurers could win.\n2. They might flee.");
|
|
const result = await generateDungeon();
|
|
expect(result.randomEvents.length).toBe(6);
|
|
expect(result.randomEvents.some((e) => e.name && e.description)).toBe(true);
|
|
}, 10000);
|
|
});
|