@@ -4,7 +4,7 @@ import { describe, expect, it } from 'bun:test';
44import { CommanderError } from 'commander' ;
55import { type RunAnnotationArgs , runAnnotation } from '#src/annotation/runAnnotation.ts' ;
66import { claudeHookResponse } from '#src/formatters/plan/claudeHookResponse.ts' ;
7- import { annotationArgs } from '#src/testFactories.ts' ;
7+ import { annotationArgs , claudeHookPayload } from '#src/testFactories.ts' ;
88import { createAnnotationDependencies , createStubContext , readErrorLogs } from '#src/testHelpers/index.ts' ;
99import { type HookClaudeDependencies , runHookClaude } from './hookClaude.ts' ;
1010
@@ -13,50 +13,30 @@ describe('hookClaude handler', () => {
1313 const { context, io } = createStubContext ( ) ;
1414 const submission = annotationSubmission . build ( { status : 'approved' , threads : [ ] } ) ;
1515 const deps = createHookDependencies ( { submission } ) ;
16- const toolInput = { plan : '# Plan\n\nStep 1.\n' , planFilePath : '/home/user/.claude/plans/sample.md' } ;
17- io . stdin . write (
18- JSON . stringify ( {
19- session_id : 'sess_123' ,
20- transcript_path : '/tmp/transcript.json' ,
21- cwd : '/work' ,
22- permission_mode : 'plan' ,
23- hook_event_name : 'PermissionRequest' ,
24- tool_name : 'ExitPlanMode' ,
25- tool_input : toolInput ,
26- } ) ,
27- ) ;
16+ const payload = claudeHookPayload . build ( ) ;
17+ io . stdin . write ( JSON . stringify ( payload ) ) ;
2818 io . stdin . end ( ) ;
2919
3020 await runHookClaude ( context , deps ) ;
3121
32- expect ( io . stdout . text ( ) ) . toBe ( `${ JSON . stringify ( claudeHookResponse ( submission , toolInput ) ) } \n` ) ;
22+ expect ( io . stdout . text ( ) ) . toBe ( `${ JSON . stringify ( claudeHookResponse ( submission , payload . tool_input ) ) } \n` ) ;
3323 const parsed = JSON . parse ( io . stdout . text ( ) . trim ( ) ) as ReturnType < typeof claudeHookResponse > ;
3424 if ( parsed . hookSpecificOutput . decision . behavior !== 'allow' ) throw new Error ( 'expected allow' ) ;
35- expect ( parsed . hookSpecificOutput . decision . updatedInput ) . toEqual ( toolInput ) ;
36- expect ( deps . calls ) . toEqual ( [ annotationArgs . build ( { content : '# Plan\n\nStep 1.\n' , entrypoint : 'hook_claude' } ) ] ) ;
25+ expect ( parsed . hookSpecificOutput . decision . updatedInput ) . toEqual ( payload . tool_input ) ;
26+ expect ( deps . calls ) . toEqual ( [ annotationArgs . build ( { content : payload . tool_input . plan , entrypoint : 'hook_claude' } ) ] ) ;
3727 } ) ;
3828
3929 it ( 'emits a deny envelope with the markdown feedback when changes are requested' , async ( ) => {
4030 const { context, io } = createStubContext ( ) ;
4131 const submission = annotationSubmission . build ( ) ;
4232 const deps = createHookDependencies ( { submission } ) ;
43- const planContent = '# Plan\n\nStep 1.\n' ;
44- io . stdin . write (
45- JSON . stringify ( {
46- session_id : 'sess_123' ,
47- transcript_path : '/tmp/transcript.json' ,
48- cwd : '/work' ,
49- permission_mode : 'plan' ,
50- hook_event_name : 'PermissionRequest' ,
51- tool_name : 'ExitPlanMode' ,
52- tool_input : { plan : planContent } ,
53- } ) ,
54- ) ;
33+ const payload = claudeHookPayload . build ( ) ;
34+ io . stdin . write ( JSON . stringify ( payload ) ) ;
5535 io . stdin . end ( ) ;
5636
5737 await runHookClaude ( context , deps ) ;
5838
59- const expected = claudeHookResponse ( submission , { plan : planContent } ) ;
39+ const expected = claudeHookResponse ( submission , payload . tool_input ) ;
6040 expect ( io . stdout . text ( ) ) . toBe ( `${ JSON . stringify ( expected ) } \n` ) ;
6141 const parsed = JSON . parse ( io . stdout . text ( ) . trim ( ) ) as typeof expected ;
6242 expect ( parsed . hookSpecificOutput . decision . behavior ) . toBe ( 'deny' ) ;
@@ -70,17 +50,7 @@ describe('hookClaude handler', () => {
7050 const deps : HookClaudeDependencies = {
7151 runReview : ( reviewCtx , args ) => runAnnotation ( reviewCtx , args , createAnnotationDependencies ( { submission } ) ) ,
7252 } ;
73- io . stdin . write (
74- JSON . stringify ( {
75- session_id : 'sess_123' ,
76- transcript_path : '/tmp/transcript.json' ,
77- cwd : '/work' ,
78- permission_mode : 'plan' ,
79- hook_event_name : 'PermissionRequest' ,
80- tool_name : 'ExitPlanMode' ,
81- tool_input : { plan : '# Plan\n\nStep 1.\n' } ,
82- } ) ,
83- ) ;
53+ io . stdin . write ( JSON . stringify ( claudeHookPayload . build ( ) ) ) ;
8454 io . stdin . end ( ) ;
8555
8656 await runHookClaude ( context , deps ) ;
@@ -99,16 +69,7 @@ describe('hookClaude handler', () => {
9969 it ( 'aborts when hook_event_name is unsupported' , ( ) => {
10070 const { context, io, logs } = createStubContext ( ) ;
10171 const deps = createHookDependencies ( ) ;
102- io . stdin . write (
103- JSON . stringify ( {
104- session_id : 'sess_123' ,
105- transcript_path : '/tmp/transcript.json' ,
106- cwd : '/work' ,
107- hook_event_name : 'PreToolUse' ,
108- tool_name : 'ExitPlanMode' ,
109- tool_input : { plan : '# x' } ,
110- } ) ,
111- ) ;
72+ io . stdin . write ( JSON . stringify ( claudeHookPayload . build ( { hook_event_name : 'PreToolUse' } ) ) ) ;
11273 io . stdin . end ( ) ;
11374
11475 expect ( runHookClaude ( context , deps ) ) . rejects . toBeInstanceOf ( CommanderError ) ;
@@ -120,16 +81,7 @@ describe('hookClaude handler', () => {
12081 it ( 'aborts when PermissionRequest arrives for a tool other than ExitPlanMode' , ( ) => {
12182 const { context, io, logs } = createStubContext ( ) ;
12283 const deps = createHookDependencies ( ) ;
123- io . stdin . write (
124- JSON . stringify ( {
125- session_id : 'sess_123' ,
126- transcript_path : '/tmp/transcript.json' ,
127- cwd : '/work' ,
128- hook_event_name : 'PermissionRequest' ,
129- tool_name : 'Bash' ,
130- tool_input : { plan : 'unused' } ,
131- } ) ,
132- ) ;
84+ io . stdin . write ( JSON . stringify ( claudeHookPayload . build ( { tool_name : 'Bash' } ) ) ) ;
13385 io . stdin . end ( ) ;
13486
13587 expect ( runHookClaude ( context , deps ) ) . rejects . toBeInstanceOf ( CommanderError ) ;
0 commit comments