|
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" |
2 | 3 | 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 | + |
3 | 11 | import * as sessionUtils from "./session-utils" |
4 | 12 |
|
5 | 13 | 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 |
8 | 19 |
|
9 | 20 | beforeEach(() => { |
10 | 21 | 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 | + } |
12 | 30 | }) |
13 | 31 |
|
14 | 32 | test("returns false when sessionID is undefined", () => { |
| 33 | + //#when sessionID is undefined |
| 34 | + //#then isCallerOrchestrator returns false |
15 | 35 | expect(sessionUtils.isCallerOrchestrator(undefined)).toBe(false) |
16 | 36 | }) |
17 | 37 |
|
18 | 38 | 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) |
20 | 44 | expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(false) |
21 | 45 | }) |
22 | 46 |
|
23 | 47 | 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 |
27 | 53 | expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(true) |
28 | 54 | }) |
29 | 55 |
|
30 | 56 | 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) |
34 | 62 | expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(true) |
35 | 63 | }) |
36 | 64 |
|
37 | 65 | 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 |
41 | 71 | expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(false) |
42 | 72 | }) |
43 | 73 |
|
44 | 74 | test("canonicalizes renamed atlas agent when checking orchestrator", () => { |
| 75 | + //#given agent name aliases are initialized with atlas -> "Master Orchestrator" |
45 | 76 | initializeAgentNameAliases( |
46 | 77 | { atlas: "Master Orchestrator" }, |
47 | 78 | ["atlas", "sisyphus", "prometheus"], |
48 | 79 | ) |
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 |
53 | 85 | expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(true) |
54 | 86 | }) |
55 | 87 |
|
56 | 88 | 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") |
60 | 94 | expect(sessionUtils.isCallerOrchestrator("ses_test")).toBe(false) |
61 | 95 | }) |
62 | 96 | }) |
0 commit comments