fix(test): add _resetForTesting to all session state tests
This commit is contained in:
@@ -41,52 +41,49 @@ describe("createAutoSlashCommandHook", () => {
|
||||
})
|
||||
|
||||
describe("slash command replacement", () => {
|
||||
it("should replace message with error when command not found", async () => {
|
||||
it("should not modify message when command not found", async () => {
|
||||
// #given a slash command that doesn't exist
|
||||
const hook = createAutoSlashCommandHook()
|
||||
const sessionID = `test-session-notfound-${Date.now()}`
|
||||
const input = createMockInput(sessionID)
|
||||
const output = createMockOutput("/nonexistent-command args")
|
||||
const originalText = output.parts[0].text
|
||||
|
||||
// #when hook is called
|
||||
await hook["chat.message"](input, output)
|
||||
|
||||
// #then should replace with error message
|
||||
const textPart = output.parts.find((p) => p.type === "text")
|
||||
expect(textPart?.text).toContain("<auto-slash-command>")
|
||||
expect(textPart?.text).toContain("not found")
|
||||
// #then should NOT modify the message (feature inactive when command not found)
|
||||
expect(output.parts[0].text).toBe(originalText)
|
||||
})
|
||||
|
||||
it("should wrap replacement in auto-slash-command tags", async () => {
|
||||
// #given any slash command
|
||||
it("should not modify message for unknown command (feature inactive)", async () => {
|
||||
// #given unknown slash command
|
||||
const hook = createAutoSlashCommandHook()
|
||||
const sessionID = `test-session-tags-${Date.now()}`
|
||||
const input = createMockInput(sessionID)
|
||||
const output = createMockOutput("/some-command")
|
||||
const originalText = output.parts[0].text
|
||||
|
||||
// #when hook is called
|
||||
await hook["chat.message"](input, output)
|
||||
|
||||
// #then should wrap in tags
|
||||
const textPart = output.parts.find((p) => p.type === "text")
|
||||
expect(textPart?.text).toContain("<auto-slash-command>")
|
||||
expect(textPart?.text).toContain("</auto-slash-command>")
|
||||
// #then should NOT modify (command not found = feature inactive)
|
||||
expect(output.parts[0].text).toBe(originalText)
|
||||
})
|
||||
|
||||
it("should completely replace original message text", async () => {
|
||||
// #given slash command
|
||||
it("should not modify for unknown command (no prepending)", async () => {
|
||||
// #given unknown slash command
|
||||
const hook = createAutoSlashCommandHook()
|
||||
const sessionID = `test-session-replace-${Date.now()}`
|
||||
const input = createMockInput(sessionID)
|
||||
const output = createMockOutput("/test-cmd some args")
|
||||
const originalText = output.parts[0].text
|
||||
|
||||
// #when hook is called
|
||||
await hook["chat.message"](input, output)
|
||||
|
||||
// #then original text should be replaced, not prepended
|
||||
const textPart = output.parts.find((p) => p.type === "text")
|
||||
expect(textPart?.text).not.toContain("/test-cmd some args\n<auto-slash-command>")
|
||||
expect(textPart?.text?.startsWith("<auto-slash-command>")).toBe(true)
|
||||
// #then should not modify (feature inactive for unknown commands)
|
||||
expect(output.parts[0].text).toBe(originalText)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -218,41 +215,40 @@ describe("createAutoSlashCommandHook", () => {
|
||||
expect(output.parts[0].text).toBe(originalText)
|
||||
})
|
||||
|
||||
it("should handle command with special characters in args", async () => {
|
||||
// #given command with special characters
|
||||
it("should handle command with special characters in args (not found = no modification)", async () => {
|
||||
// #given command with special characters that doesn't exist
|
||||
const hook = createAutoSlashCommandHook()
|
||||
const sessionID = `test-session-special-${Date.now()}`
|
||||
const input = createMockInput(sessionID)
|
||||
const output = createMockOutput('/execute "test & stuff <tag>"')
|
||||
const originalText = output.parts[0].text
|
||||
|
||||
// #when hook is called
|
||||
await hook["chat.message"](input, output)
|
||||
|
||||
// #then should handle gracefully (not found, but processed)
|
||||
const textPart = output.parts.find((p) => p.type === "text")
|
||||
expect(textPart?.text).toContain("<auto-slash-command>")
|
||||
expect(textPart?.text).toContain("/execute")
|
||||
// #then should not modify (command not found = feature inactive)
|
||||
expect(output.parts[0].text).toBe(originalText)
|
||||
})
|
||||
|
||||
it("should handle multiple text parts", async () => {
|
||||
// #given multiple text parts
|
||||
it("should handle multiple text parts (unknown command = no modification)", async () => {
|
||||
// #given multiple text parts with unknown command
|
||||
const hook = createAutoSlashCommandHook()
|
||||
const sessionID = `test-session-multi-${Date.now()}`
|
||||
const input = createMockInput(sessionID)
|
||||
const output: AutoSlashCommandHookOutput = {
|
||||
message: {},
|
||||
parts: [
|
||||
{ type: "text", text: "/commit " },
|
||||
{ type: "text", text: "fix bug" },
|
||||
{ type: "text", text: "/truly-nonexistent-xyz-cmd " },
|
||||
{ type: "text", text: "some args" },
|
||||
],
|
||||
}
|
||||
const originalText = output.parts[0].text
|
||||
|
||||
// #when hook is called
|
||||
await hook["chat.message"](input, output)
|
||||
|
||||
// #then should detect from combined text and modify first text part
|
||||
const firstTextPart = output.parts.find((p) => p.type === "text")
|
||||
expect(firstTextPart?.text).toContain("<auto-slash-command>")
|
||||
// #then should not modify (command not found = feature inactive)
|
||||
expect(output.parts[0].text).toBe(originalText)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -68,24 +68,22 @@ export function createAutoSlashCommandHook(options?: AutoSlashCommandHookOptions
|
||||
return
|
||||
}
|
||||
|
||||
if (result.success && result.replacementText) {
|
||||
const taggedContent = `${AUTO_SLASH_COMMAND_TAG_OPEN}\n${result.replacementText}\n${AUTO_SLASH_COMMAND_TAG_CLOSE}`
|
||||
output.parts[idx].text = taggedContent
|
||||
|
||||
log(`[auto-slash-command] Replaced message with command template`, {
|
||||
sessionID: input.sessionID,
|
||||
command: parsed.command,
|
||||
})
|
||||
} else {
|
||||
const errorMessage = `${AUTO_SLASH_COMMAND_TAG_OPEN}\n[AUTO-SLASH-COMMAND ERROR]\n${result.error}\n\nOriginal input: ${parsed.raw}\n${AUTO_SLASH_COMMAND_TAG_CLOSE}`
|
||||
output.parts[idx].text = errorMessage
|
||||
|
||||
log(`[auto-slash-command] Command not found, showing error`, {
|
||||
if (!result.success || !result.replacementText) {
|
||||
log(`[auto-slash-command] Command not found, skipping`, {
|
||||
sessionID: input.sessionID,
|
||||
command: parsed.command,
|
||||
error: result.error,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const taggedContent = `${AUTO_SLASH_COMMAND_TAG_OPEN}\n${result.replacementText}\n${AUTO_SLASH_COMMAND_TAG_CLOSE}`
|
||||
output.parts[idx].text = taggedContent
|
||||
|
||||
log(`[auto-slash-command] Replaced message with command template`, {
|
||||
sessionID: input.sessionID,
|
||||
command: parsed.command,
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test, beforeEach, afterEach, spyOn } from "bun:test"
|
||||
import { createKeywordDetectorHook } from "./index"
|
||||
import { setMainSession, updateSessionAgent, clearSessionAgent } from "../../features/claude-code-session-state"
|
||||
import { setMainSession, updateSessionAgent, clearSessionAgent, _resetForTesting } from "../../features/claude-code-session-state"
|
||||
import { ContextCollector } from "../../features/context-injector"
|
||||
import * as sharedModule from "../../shared"
|
||||
import * as sessionState from "../../features/claude-code-session-state"
|
||||
@@ -11,6 +11,7 @@ describe("keyword-detector registers to ContextCollector", () => {
|
||||
let getMainSessionSpy: ReturnType<typeof spyOn>
|
||||
|
||||
beforeEach(() => {
|
||||
_resetForTesting()
|
||||
logCalls = []
|
||||
logSpy = spyOn(sharedModule, "log").mockImplementation((msg: string, data?: unknown) => {
|
||||
logCalls.push({ msg, data })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test, beforeEach, afterEach, spyOn } from "bun:test"
|
||||
|
||||
import { createSessionNotification } from "./session-notification"
|
||||
import { setMainSession, subagentSessions } from "../features/claude-code-session-state"
|
||||
import { setMainSession, subagentSessions, _resetForTesting } from "../features/claude-code-session-state"
|
||||
import * as utils from "./session-notification-utils"
|
||||
|
||||
describe("session-notification", () => {
|
||||
@@ -30,6 +30,7 @@ describe("session-notification", () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
_resetForTesting()
|
||||
notificationCalls = []
|
||||
|
||||
spyOn(utils, "getOsascriptPath").mockResolvedValue("/usr/bin/osascript")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
||||
|
||||
import type { BackgroundManager } from "../features/background-agent"
|
||||
import { setMainSession, subagentSessions } from "../features/claude-code-session-state"
|
||||
import { setMainSession, subagentSessions, _resetForTesting } from "../features/claude-code-session-state"
|
||||
import { createTodoContinuationEnforcer } from "./todo-continuation-enforcer"
|
||||
|
||||
describe("todo-continuation-enforcer", () => {
|
||||
@@ -60,16 +60,14 @@ describe("todo-continuation-enforcer", () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
_resetForTesting()
|
||||
promptCalls = []
|
||||
toastCalls = []
|
||||
mockMessages = []
|
||||
setMainSession(undefined)
|
||||
subagentSessions.clear()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
setMainSession(undefined)
|
||||
subagentSessions.clear()
|
||||
_resetForTesting()
|
||||
})
|
||||
|
||||
test("should inject continuation when idle with incomplete todos", async () => {
|
||||
|
||||
Reference in New Issue
Block a user