|
| 1 | +# Shell Script Tests |
| 2 | + |
| 3 | +Automated tests for DeepWork shell scripts, with a focus on validating Claude Code hooks JSON response formats. |
| 4 | + |
| 5 | +## Scripts Tested |
| 6 | + |
| 7 | +| Script | Type | Description | |
| 8 | +|--------|------|-------------| |
| 9 | +| `policy_stop_hook.sh` | Stop Hook | Evaluates policies and blocks agent stop if policies are triggered | |
| 10 | +| `user_prompt_submit.sh` | UserPromptSubmit Hook | Captures work tree state when user submits a prompt | |
| 11 | +| `capture_prompt_work_tree.sh` | Helper | Records current git state for `compare_to: prompt` policies | |
| 12 | +| `make_new_job.sh` | Utility | Creates directory structure for new DeepWork jobs | |
| 13 | + |
| 14 | +## Claude Code Hooks JSON Format |
| 15 | + |
| 16 | +Hook scripts must return valid JSON responses. The tests enforce these formats: |
| 17 | + |
| 18 | +### Stop Hooks (`hooks.after_agent`) |
| 19 | +```json |
| 20 | +{} // Allow stop |
| 21 | +{"decision": "block", "reason": "..."} // Block stop with reason |
| 22 | +``` |
| 23 | + |
| 24 | +### UserPromptSubmit Hooks (`hooks.before_prompt`) |
| 25 | +```json |
| 26 | +{} // No output or empty object (side-effect only hooks) |
| 27 | +``` |
| 28 | + |
| 29 | +### All Hooks |
| 30 | +- Must return valid JSON if producing output |
| 31 | +- Non-JSON output on stdout is **not allowed** (stderr is ok) |
| 32 | +- Exit code 0 indicates success (even when blocking) |
| 33 | + |
| 34 | +## Running Tests |
| 35 | + |
| 36 | +```bash |
| 37 | +# Run all shell script tests |
| 38 | +uv run pytest tests/shell_script_tests/ -v |
| 39 | + |
| 40 | +# Run tests for a specific script |
| 41 | +uv run pytest tests/shell_script_tests/test_policy_stop_hook.py -v |
| 42 | + |
| 43 | +# Run with coverage |
| 44 | +uv run pytest tests/shell_script_tests/ --cov=src/deepwork |
| 45 | +``` |
| 46 | + |
| 47 | +## Test Structure |
| 48 | + |
| 49 | +``` |
| 50 | +tests/shell_script_tests/ |
| 51 | +├── conftest.py # Shared fixtures and helpers |
| 52 | +├── test_policy_stop_hook.py # Stop hook blocking/allowing tests |
| 53 | +├── test_user_prompt_submit.py # Prompt submission hook tests |
| 54 | +├── test_capture_prompt_work_tree.py # Work tree capture tests |
| 55 | +├── test_hooks_json_format.py # JSON format validation tests |
| 56 | +└── test_make_new_job.py # Job directory creation tests |
| 57 | +``` |
| 58 | + |
| 59 | +## Shared Fixtures |
| 60 | + |
| 61 | +Available in `conftest.py`: |
| 62 | + |
| 63 | +| Fixture | Description | |
| 64 | +|---------|-------------| |
| 65 | +| `git_repo` | Basic git repo with initial commit | |
| 66 | +| `git_repo_with_policy` | Git repo with a Python file policy | |
| 67 | +| `policy_hooks_dir` | Path to policy hooks scripts | |
| 68 | +| `jobs_scripts_dir` | Path to job management scripts | |
| 69 | + |
| 70 | +## Adding New Tests |
| 71 | + |
| 72 | +1. Use shared fixtures from `conftest.py` when possible |
| 73 | +2. Use `run_shell_script()` helper for running scripts |
| 74 | +3. Validate JSON output with `validate_json_output()` and `validate_stop_hook_response()` |
| 75 | +4. Test both success and failure cases |
| 76 | +5. Verify exit codes (hooks should exit 0 even when blocking) |
0 commit comments