test: localize stop hook command mocks
This commit is contained in:
@@ -1,26 +1,14 @@
|
||||
import { describe, it, expect, mock, beforeEach, afterAll } from "bun:test"
|
||||
import { describe, it, expect, mock, beforeEach, afterEach, spyOn } from "bun:test"
|
||||
import type { ClaudeHooksConfig } from "./types"
|
||||
import type { StopContext } from "./stop"
|
||||
import * as dispatchHookModule from "./dispatch-hook"
|
||||
import * as logger from "../../shared/logger"
|
||||
import { executeStopHooks } from "./stop"
|
||||
|
||||
const mockExecuteHookCommand = mock(() =>
|
||||
const mockDispatchHook = mock(() =>
|
||||
Promise.resolve({ exitCode: 0, stdout: "", stderr: "" })
|
||||
)
|
||||
|
||||
mock.module("../../shared/command-executor", () => ({
|
||||
executeHookCommand: mockExecuteHookCommand,
|
||||
executeCommand: mock(),
|
||||
resolveCommandsInText: mock(),
|
||||
}))
|
||||
|
||||
mock.module("../../shared/logger", () => ({
|
||||
log: () => {},
|
||||
getLogFilePath: () => "/tmp/test.log",
|
||||
}))
|
||||
|
||||
afterAll(() => { mock.restore() })
|
||||
|
||||
const { executeStopHooks } = await import("./stop")
|
||||
|
||||
function createStopContext(overrides?: Partial<StopContext>): StopContext {
|
||||
return {
|
||||
sessionId: "test-session",
|
||||
@@ -35,10 +23,19 @@ function createConfig(stopHooks: ClaudeHooksConfig["Stop"]): ClaudeHooksConfig {
|
||||
|
||||
describe("executeStopHooks", () => {
|
||||
beforeEach(() => {
|
||||
mockExecuteHookCommand.mockReset()
|
||||
mockExecuteHookCommand.mockImplementation(() =>
|
||||
mockDispatchHook.mockReset()
|
||||
mockDispatchHook.mockImplementation(() =>
|
||||
Promise.resolve({ exitCode: 0, stdout: "", stderr: "" })
|
||||
)
|
||||
|
||||
spyOn(dispatchHookModule, "dispatchHook").mockImplementation(
|
||||
async (_hook, _stdinJson, _cwd) => await mockDispatchHook()
|
||||
)
|
||||
spyOn(logger, "log").mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore()
|
||||
})
|
||||
|
||||
it("#given parent session #when stop hooks called #then skips execution", async () => {
|
||||
@@ -50,7 +47,7 @@ describe("executeStopHooks", () => {
|
||||
const result = await executeStopHooks(ctx, config)
|
||||
|
||||
expect(result.block).toBe(false)
|
||||
expect(mockExecuteHookCommand).not.toHaveBeenCalled()
|
||||
expect(mockDispatchHook).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("#given null config #when stop hooks called #then returns non-blocking", async () => {
|
||||
@@ -59,7 +56,7 @@ describe("executeStopHooks", () => {
|
||||
const result = await executeStopHooks(ctx, null)
|
||||
|
||||
expect(result.block).toBe(false)
|
||||
expect(mockExecuteHookCommand).not.toHaveBeenCalled()
|
||||
expect(mockDispatchHook).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("#given empty stop hooks #when stop hooks called #then returns non-blocking", async () => {
|
||||
@@ -76,7 +73,7 @@ describe("executeStopHooks", () => {
|
||||
const config = createConfig([
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "exit 2" }] },
|
||||
])
|
||||
mockExecuteHookCommand.mockResolvedValueOnce({
|
||||
mockDispatchHook.mockResolvedValueOnce({
|
||||
exitCode: 2,
|
||||
stdout: "",
|
||||
stderr: "blocked reason",
|
||||
@@ -93,7 +90,7 @@ describe("executeStopHooks", () => {
|
||||
const config = createConfig([
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "blocker" }] },
|
||||
])
|
||||
mockExecuteHookCommand.mockResolvedValueOnce({
|
||||
mockDispatchHook.mockResolvedValueOnce({
|
||||
exitCode: 0,
|
||||
stdout: JSON.stringify({ decision: "block", reason: "must fix" }),
|
||||
stderr: "",
|
||||
@@ -111,7 +108,7 @@ describe("executeStopHooks", () => {
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "hook-a" }] },
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "hook-b" }] },
|
||||
])
|
||||
mockExecuteHookCommand
|
||||
mockDispatchHook
|
||||
.mockResolvedValueOnce({
|
||||
exitCode: 0,
|
||||
stdout: JSON.stringify({ suppressOutput: true }),
|
||||
@@ -126,7 +123,7 @@ describe("executeStopHooks", () => {
|
||||
const result = await executeStopHooks(ctx, config)
|
||||
|
||||
expect(result.block).toBe(false)
|
||||
expect(mockExecuteHookCommand).toHaveBeenCalledTimes(2)
|
||||
expect(mockDispatchHook).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it("#given first hook returns stdin passthrough JSON #when multiple hooks #then executes all hooks", async () => {
|
||||
@@ -140,7 +137,7 @@ describe("executeStopHooks", () => {
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "check-console-log" }] },
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "task-complete-notify" }] },
|
||||
])
|
||||
mockExecuteHookCommand
|
||||
mockDispatchHook
|
||||
.mockResolvedValueOnce({
|
||||
exitCode: 0,
|
||||
stdout: JSON.stringify(stdinPassthrough),
|
||||
@@ -155,7 +152,7 @@ describe("executeStopHooks", () => {
|
||||
const result = await executeStopHooks(ctx, config)
|
||||
|
||||
expect(result.block).toBe(false)
|
||||
expect(mockExecuteHookCommand).toHaveBeenCalledTimes(2)
|
||||
expect(mockDispatchHook).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it("#given first hook blocks #when multiple hooks #then stops at blocking hook", async () => {
|
||||
@@ -164,7 +161,7 @@ describe("executeStopHooks", () => {
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "blocker" }] },
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "notifier" }] },
|
||||
])
|
||||
mockExecuteHookCommand.mockResolvedValueOnce({
|
||||
mockDispatchHook.mockResolvedValueOnce({
|
||||
exitCode: 0,
|
||||
stdout: JSON.stringify({ decision: "block", reason: "fix first" }),
|
||||
stderr: "",
|
||||
@@ -173,7 +170,7 @@ describe("executeStopHooks", () => {
|
||||
const result = await executeStopHooks(ctx, config)
|
||||
|
||||
expect(result.block).toBe(true)
|
||||
expect(mockExecuteHookCommand).toHaveBeenCalledTimes(1)
|
||||
expect(mockDispatchHook).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it("#given hook with non-JSON stdout #when stop hooks called #then continues to next hook", async () => {
|
||||
@@ -182,7 +179,7 @@ describe("executeStopHooks", () => {
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "hook-a" }] },
|
||||
{ matcher: "*", hooks: [{ type: "command", command: "hook-b" }] },
|
||||
])
|
||||
mockExecuteHookCommand
|
||||
mockDispatchHook
|
||||
.mockResolvedValueOnce({
|
||||
exitCode: 0,
|
||||
stdout: "not json",
|
||||
@@ -197,6 +194,6 @@ describe("executeStopHooks", () => {
|
||||
const result = await executeStopHooks(ctx, config)
|
||||
|
||||
expect(result.block).toBe(false)
|
||||
expect(mockExecuteHookCommand).toHaveBeenCalledTimes(2)
|
||||
expect(mockDispatchHook).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user