#!/usr/bin/env python3 """Claude Hooks Test Script for NPM Distribution""" import os import sys import json import subprocess import tempfile from pathlib import Path # Colors for terminal output class Colors: RED = '\033[0;31m' GREEN = '\033[0;32m' YELLOW = '\033[1;33m' BLUE = '\033[0;34m' NC = '\033[0m' # No Color def print_colored(message, color): print(f"{color}{message}{Colors.NC}") def print_status(message, status="INFO"): colors = { "SUCCESS": Colors.GREEN, "ERROR": Colors.RED, "WARNING": Colors.YELLOW, "INFO": Colors.BLUE } print_colored(f"[{status}] {message}", colors.get(status, Colors.NC)) def test_hook_script(hook_path, test_input=None): """Test a single hook script""" if not hook_path.exists(): return False, "Script not found" try: cmd = [sys.executable, str(hook_path)] result = subprocess.run( cmd, input=test_input or "", text=True, capture_output=True, timeout=10 ) if result.returncode == 0: return True, "Success" else: return False, f"Exit code {result.returncode}: {result.stderr.strip()}" except subprocess.TimeoutExpired: return False, "Timeout" except Exception as e: return False, str(e) def main(): print_colored("Claude Hooks Test Suite", Colors.BLUE) print("=" * 30) # Get package root package_root = Path(__file__).parent.parent hooks_dir = package_root / "hooks" claude_config_dir = Path.home() / ".config" / "claude" hooks_config_file = claude_config_dir / "hooks.json" tests_passed = 0 tests_total = 0 # Test 1: Check configuration exists print("Testing configuration...") tests_total += 1 if hooks_config_file.exists(): print_status("✓ Hooks configuration found", "SUCCESS") tests_passed += 1 else: print_status("✗ Hooks configuration missing", "ERROR") print(" Run: claude-hooks init") # Test 2: Check Python version print("Testing Python compatibility...") tests_total += 1 if sys.version_info >= (3, 8): print_status(f"✓ Python {sys.version_info.major}.{sys.version_info.minor} compatible", "SUCCESS") tests_passed += 1 else: print_status(f"✗ Python 3.8+ required, found {sys.version_info.major}.{sys.version_info.minor}", "ERROR") # Test 3: Test hook scripts hook_tests = [ ("context_monitor.py", '{"prompt": "test prompt", "context_size": 1000}'), ("command_validator.py", '{"command": "pip install requests", "cwd": "/tmp"}'), ("session_logger.py", '{"tool": "Bash", "args": {"command": "echo test"}}'), ("session_finalizer.py", '{"session_duration": 300, "tools_used": ["Bash", "Edit"]}') ] for script_name, test_input in hook_tests: print(f"Testing {script_name}...") tests_total += 1 hook_path = hooks_dir / script_name success, message = test_hook_script(hook_path, test_input) if success: print_status(f"✓ {script_name} working", "SUCCESS") tests_passed += 1 else: print_status(f"✗ {script_name} failed: {message}", "ERROR") # Test 4: Check runtime directories print("Testing runtime directories...") tests_total += 1 runtime_dir = package_root / ".claude_hooks" required_dirs = ["backups", "logs", "patterns"] missing_dirs = [] for dirname in required_dirs: if not (runtime_dir / dirname).exists(): missing_dirs.append(dirname) if not missing_dirs: print_status("✓ Runtime directories present", "SUCCESS") tests_passed += 1 else: print_status(f"✗ Missing directories: {', '.join(missing_dirs)}", "ERROR") # Test 5: Test shadow learner print("Testing shadow learner...") tests_total += 1 try: # Import test sys.path.insert(0, str(package_root)) from lib.shadow_learner import ShadowLearner learner = ShadowLearner(str(package_root / ".claude_hooks" / "patterns")) # Basic functionality test learner.learn_command_failure("pip", "pip3", 0.9) suggestion = learner.get_suggestion("pip") if suggestion and suggestion.get('suggestion') == 'pip3': print_status("✓ Shadow learner functional", "SUCCESS") tests_passed += 1 else: print_status("✗ Shadow learner not learning correctly", "ERROR") except Exception as e: print_status(f"✗ Shadow learner error: {e}", "ERROR") # Summary print() print_colored("Test Results", Colors.BLUE) print("-" * 20) if tests_passed == tests_total: print_status(f"All {tests_total} tests passed! 🎉", "SUCCESS") print() print_colored("Claude Hooks is ready to use!", Colors.GREEN) print("Try running some commands to see the learning in action:") print("- pip install requests (should suggest pip3)") print("- python script.py (should suggest python3)") return 0 else: print_status(f"{tests_passed}/{tests_total} tests passed", "WARNING") print() print_colored("Some issues detected. Check installation:", Colors.YELLOW) print("1. Run: claude-hooks init") print("2. Restart Claude Code") print("3. Run tests again") return 1 if __name__ == "__main__": sys.exit(main())