Skip to content

Commit 20fc8d9

Browse files
committed
fix(test): mock fs dependencies instead of self-module spy and add afterEach cleanup
1 parent c1b1001 commit 20fc8d9

File tree

1 file changed

+55
-21
lines changed

1 file changed

+55
-21
lines changed

src/shared/session-utils.test.ts

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,96 @@
1-
import { describe, test, expect, beforeEach, mock, spyOn } from "bun:test"
1+
import { describe, test, expect, beforeEach, afterEach, spyOn, mock } from "bun:test"
2+
import * as fs from "node:fs"
23
import { initializeAgentNameAliases, resetAgentNameAliases } from "./agent-name-aliases"
4+
5+
//#given mocked fs module to control getMessageDir behavior
6+
mock.module("node:fs", () => ({
7+
existsSync: mock(() => true),
8+
readdirSync: mock(() => []),
9+
}))
10+
311
import * as sessionUtils from "./session-utils"
412

513
describe("session-utils", () => {
6-
let getMessageDirSpy: ReturnType<typeof spyOn>
7-
let findNearestSpy: ReturnType<typeof mock>
14+
//#given mocked hook-message-injector dependencies
15+
//#when testing isCallerOrchestrator
16+
//#then all tests should pass with proper cleanup
17+
18+
let injectorSpy: ReturnType<typeof spyOn> | null = null
819

920
beforeEach(() => {
1021
resetAgentNameAliases()
11-
getMessageDirSpy = spyOn(sessionUtils, "getMessageDir").mockReturnValue("/tmp/fake-dir")
22+
})
23+
24+
afterEach(() => {
25+
//#then restore all mocks to prevent test pollution
26+
if (injectorSpy) {
27+
injectorSpy.mockRestore()
28+
injectorSpy = null
29+
}
1230
})
1331

1432
test("returns false when sessionID is undefined", () => {
33+
//#when sessionID is undefined
34+
//#then isCallerOrchestrator returns false
1535
expect(sessionUtils.isCallerOrchestrator(undefined)).toBe(false)
1636
})
1737

1838
test("returns false when no message directory exists", () => {
19-
getMessageDirSpy.mockReturnValue(null)
39+
//#given getMessageDir returns null (no message directory found)
40+
//#when calling isCallerOrchestrator with a sessionID
41+
//#then it returns false
42+
const injectorModule = require("../features/hook-message-injector")
43+
injectorSpy = spyOn(injectorModule, "findNearestMessageWithFields").mockReturnValue(null)
2044
expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(false)
2145
})
2246

2347
test("returns true when nearest message agent is atlas", () => {
24-
const injector = require("../features/hook-message-injector")
25-
spyOn(injector, "findNearestMessageWithFields").mockReturnValue({ agent: "atlas" })
26-
48+
//#given findNearestMessageWithFields returns an object with agent: "atlas"
49+
const injectorModule = require("../features/hook-message-injector")
50+
injectorSpy = spyOn(injectorModule, "findNearestMessageWithFields").mockReturnValue({ agent: "atlas" })
51+
//#when calling isCallerOrchestrator
52+
//#then it returns true
2753
expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(true)
2854
})
2955

3056
test("returns true for Atlas with different casing", () => {
31-
const injector = require("../features/hook-message-injector")
32-
spyOn(injector, "findNearestMessageWithFields").mockReturnValue({ agent: "Atlas" })
33-
57+
//#given findNearestMessageWithFields returns an object with agent: "Atlas" (uppercase)
58+
const injectorModule = require("../features/hook-message-injector")
59+
injectorSpy = spyOn(injectorModule, "findNearestMessageWithFields").mockReturnValue({ agent: "Atlas" })
60+
//#when calling isCallerOrchestrator
61+
//#then it returns true (case-insensitive comparison)
3462
expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(true)
3563
})
3664

3765
test("returns false when nearest message agent is not atlas", () => {
38-
const injector = require("../features/hook-message-injector")
39-
spyOn(injector, "findNearestMessageWithFields").mockReturnValue({ agent: "sisyphus" })
40-
66+
//#given findNearestMessageWithFields returns an object with agent: "sisyphus"
67+
const injectorModule = require("../features/hook-message-injector")
68+
injectorSpy = spyOn(injectorModule, "findNearestMessageWithFields").mockReturnValue({ agent: "sisyphus" })
69+
//#when calling isCallerOrchestrator
70+
//#then it returns false
4171
expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(false)
4272
})
4373

4474
test("canonicalizes renamed atlas agent when checking orchestrator", () => {
75+
//#given agent name aliases are initialized with atlas -> "Master Orchestrator"
4576
initializeAgentNameAliases(
4677
{ atlas: "Master Orchestrator" },
4778
["atlas", "sisyphus", "prometheus"],
4879
)
49-
50-
const injector = require("../features/hook-message-injector")
51-
spyOn(injector, "findNearestMessageWithFields").mockReturnValue({ agent: "Master Orchestrator" })
52-
80+
//#and findNearestMessageWithFields returns the renamed agent name
81+
const injectorModule = require("../features/hook-message-injector")
82+
injectorSpy = spyOn(injectorModule, "findNearestMessageWithFields").mockReturnValue({ agent: "Master Orchestrator" })
83+
//#when calling isCallerOrchestrator
84+
//#then it canonicalizes the name and returns true
5385
expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(true)
5486
})
5587

5688
test("returns false when agent field is missing from nearest message", () => {
57-
const injector = require("../features/hook-message-injector")
58-
spyOn(injector, "findNearestMessageWithFields").mockReturnValue({})
59-
89+
//#given findNearestMessageWithFields returns an object without agent field
90+
const injectorModule = require("../features/hook-message-injector")
91+
injectorSpy = spyOn(injectorModule, "findNearestMessageWithFields").mockReturnValue({})
92+
//#when calling isCallerOrchestrator
93+
//#then it returns false (agent defaults to empty string, not "atlas")
6094
expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(false)
6195
})
6296
})

0 commit comments

Comments
 (0)