Setting the file. One moment. Test Hook · Hook Development · anthropics/claude-code · Skills Docsscripts/test-hook.sh
scripts/test-hook.sh
Shell·252 lines·5 KB
14 echo " -t, --timeout N Set timeout in seconds (default: 60)"
15 echo ""
16 echo "Examples:"
17 echo " $0 validate-bash.sh test-input.json"
18 echo " $0 -v -t 30 validate-write.sh write-input.json"
19 echo ""
20 echo "Creates sample test input with:"
21 echo " $0 --create-sample <event-type>"
22 exit 0
23}
24
25# Create sample input
26create_sample() {
27 event_type="$1"
28
29 case "$event_type" in
30 PreToolUse)
31 cat <<'EOF'
32{
33 "session_id": "test-session",
34 "transcript_path": "/tmp/transcript.txt",
35 "cwd": "/tmp/test-project",
36 "permission_mode": "ask",
37 "hook_event_name": "PreToolUse",
38 "tool_name": "Write",
39 "tool_input": {
40 "file_path": "/tmp/test.txt",
41 "content": "Test content"
42 }
43}
44EOF
45 ;;
46 PostToolUse)
47 cat <<'EOF'
48{
49 "session_id": "test-session",
50 "transcript_path": "/tmp/transcript.txt",
51 "cwd": "/tmp/test-project",
52 "permission_mode": "ask",
53 "hook_event_name": "PostToolUse",
54 "tool_name": "Bash",
55 "tool_result": "Command executed successfully"
56}
57EOF
58 ;;
59 Stop|SubagentStop)
60 cat <<'EOF'
61{
62 "session_id": "test-session",
63 "transcript_path": "/tmp/transcript.txt",
64 "cwd": "/tmp/test-project",
65 "permission_mode": "ask",
66 "hook_event_name": "Stop",
67 "reason": "Task appears complete"
68}
69EOF
70 ;;
71 UserPromptSubmit)
72 cat <<'EOF'
73{
74 "session_id": "test-session",
75 "transcript_path": "/tmp/transcript.txt",
76 "cwd": "/tmp/test-project",
77 "permission_mode": "ask",
78 "hook_event_name": "UserPromptSubmit",
79 "user_prompt": "Test user prompt"
80}
81EOF
82 ;;
83 SessionStart|SessionEnd)
84 cat <<'EOF'
85{
86 "session_id": "test-session",
87 "transcript_path": "/tmp/transcript.txt",
88 "cwd": "/tmp/test-project",
89 "permission_mode": "ask",
90 "hook_event_name": "SessionStart"
91}
92EOF
93 ;;
94 *)
95 echo "Unknown event type: $event_type"
96 echo "Valid types: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit, SessionStart, SessionEnd"
97 exit 1
98 ;;
99 esac
100}
101
102# Parse arguments
103VERBOSE=false
104TIMEOUT=60
105
106while [ $# -gt 0 ]; do
107 case "$1" in
108 -h|--help)
109 show_usage
110 ;;
111 -v|--verbose)
112 VERBOSE=true
113 shift
114 ;;
115 -t|--timeout)
116 TIMEOUT="$2"
117 shift 2
118 ;;
119 --create-sample)
120 create_sample "$2"
121 exit 0
122 ;;
123 *)
124 break
125 ;;
126 esac
127done
128
129if [ $# -ne 2 ]; then
130 echo "Error: Missing required arguments"
131 echo ""
132 show_usage
133fi
134
135HOOK_SCRIPT="$1"
136TEST_INPUT="$2"
137
138# Validate inputs
139if [ ! -f "$HOOK_SCRIPT" ]; then
140 echo "❌ Error: Hook script not found: $HOOK_SCRIPT"
141 exit 1
142fi
143
144if [ ! -x "$HOOK_SCRIPT" ]; then
145 echo "⚠️ Warning: Hook script is not executable. Attempting to run with bash..."
146 HOOK_SCRIPT="bash $HOOK_SCRIPT"
147fi
148
149if [ ! -f "$TEST_INPUT" ]; then
150 echo "❌ Error: Test input not found: $TEST_INPUT"
151 exit 1
152fi
153
154# Validate test input JSON
155if ! jq empty "$TEST_INPUT" 2>/dev/null; then
156 echo "❌ Error: Test input is not valid JSON"
157 exit 1
158fi
159
160echo "🧪 Testing hook: $HOOK_SCRIPT"
161echo "📥 Input: $TEST_INPUT"
162echo ""
163
164if [ "$VERBOSE" = true ]; then
165 echo "Input JSON:"
166 jq . "$TEST_INPUT"
167 echo ""
168fi
169
170# Set up environment
171export CLAUDE_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-/tmp/test-project}"
172export CLAUDE_PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(pwd)}"
173export CLAUDE_ENV_FILE="${CLAUDE_ENV_FILE:-/tmp/test-env-$$}"
174
175if [ "$VERBOSE" = true ]; then
176 echo "Environment:"
177 echo " CLAUDE_PROJECT_DIR=$CLAUDE_PROJECT_DIR"
178 echo " CLAUDE_PLUGIN_ROOT=$CLAUDE_PLUGIN_ROOT"
179 echo " CLAUDE_ENV_FILE=$CLAUDE_ENV_FILE"
180 echo ""
181fi
182
183# Run the hook
184echo "▶️ Running hook (timeout: ${TIMEOUT}s)..."
185echo ""
186
187start_time=$(date +%s)
188
189set +e
190output=$(timeout "$TIMEOUT" bash -c "cat '$TEST_INPUT' | $HOOK_SCRIPT" 2>&1)
191exit_code=$?
192set -e
193
194end_time=$(date +%s)
195duration=$((end_time - start_time))
196
197# Analyze results
198echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
199echo "Results:"
200echo ""
201echo "Exit Code: $exit_code"
202echo "Duration: ${duration}s"
203echo ""
204
205case $exit_code in
206 0)
207 echo "✅ Hook approved/succeeded"
208 ;;
209 2)
210 echo "🚫 Hook blocked/denied"
211 ;;
212 124)
213 echo "⏱️ Hook timed out after ${TIMEOUT}s"
214 ;;
215 *)
216 echo "⚠️ Hook returned unexpected exit code: $exit_code"
217 ;;
218esac
219
220echo ""
221echo "Output:"
222if [ -n "$output" ]; then
223 echo "$output"
224 echo ""
225
226 # Try to parse as JSON
227 if echo "$output" | jq empty 2>/dev/null; then
228 echo "Parsed JSON output:"
229 echo "$output" | jq .
230 fi
231else
232 echo "(no output)"
233fi
234
235# Check for environment file
236if [ -f "$CLAUDE_ENV_FILE" ]; then
237 echo ""
238 echo "Environment file created:"
239 cat "$CLAUDE_ENV_FILE"
240 rm -f "$CLAUDE_ENV_FILE"
241fi
242
243echo ""
244echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
245
246if [ $exit_code -eq 0 ] || [ $exit_code -eq 2 ]; then
247 echo "✅ Test completed successfully"
248 exit 0
249else
250 echo "❌ Test failed"
251 exit 1
252fi