test: add review-gate unit tests (43 tests)

Tests cover:
- All CLI commands (check, enable, approve, reject, status, list, clean)
- Exit codes (0 for allow, 1 for block)
- State file creation and JSON structure
- Session ID auto-detection from env vars
- Multiple issues in reject
- Workflow reset (re-enable after approve)
- Error handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
dan 2026-01-09 23:09:33 -08:00
parent 061556e003
commit 4130dd4614

View file

@ -0,0 +1,321 @@
#!/usr/bin/env bash
# Tests for review-gate CLI
# Run: bash skills/review-gate/tests/test-review-gate.sh
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REVIEW_GATE="$SCRIPT_DIR/../scripts/review-gate"
PASSED=0
FAILED=0
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'
# Test state directory (isolated per test run)
TEST_STATE_DIR=$(mktemp -d)
export REVIEW_STATE_DIR="$TEST_STATE_DIR"
cleanup() {
rm -rf "$TEST_STATE_DIR"
}
trap cleanup EXIT
# Test helpers
assert_exit_code() {
local description="$1"
local expected="$2"
local actual="$3"
if [[ "$actual" == "$expected" ]]; then
echo -e "${GREEN}PASS${NC}: $description"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: $description"
echo " Expected exit code: $expected, Actual: $actual"
((FAILED++))
fi
}
assert_output_contains() {
local description="$1"
local pattern="$2"
local output="$3"
if echo "$output" | grep -q "$pattern"; then
echo -e "${GREEN}PASS${NC}: $description"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: $description"
echo " Pattern not found: '$pattern'"
echo " Output was:"
echo "$output" | sed 's/^/ /'
((FAILED++))
fi
}
assert_output_not_contains() {
local description="$1"
local pattern="$2"
local output="$3"
if ! echo "$output" | grep -q "$pattern"; then
echo -e "${GREEN}PASS${NC}: $description"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: $description"
echo " Pattern found but should not be: '$pattern'"
((FAILED++))
fi
}
assert_file_exists() {
local description="$1"
local file="$2"
if [[ -f "$file" ]]; then
echo -e "${GREEN}PASS${NC}: $description"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: $description"
echo " File does not exist: $file"
((FAILED++))
fi
}
assert_file_not_exists() {
local description="$1"
local file="$2"
if [[ ! -f "$file" ]]; then
echo -e "${GREEN}PASS${NC}: $description"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: $description"
echo " File exists but should not: $file"
((FAILED++))
fi
}
assert_json_field() {
local description="$1"
local expected="$2"
local field="$3"
local file="$4"
local actual
actual=$(jq -r "$field" "$file" 2>/dev/null)
if [[ "$actual" == "$expected" ]]; then
echo -e "${GREEN}PASS${NC}: $description"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: $description"
echo " Expected $field: '$expected', Actual: '$actual'"
((FAILED++))
fi
}
run_gate() {
"$REVIEW_GATE" "$@" 2>&1
}
run_gate_status() {
"$REVIEW_GATE" "$@" 2>&1
echo $?
}
echo "=== Review Gate CLI Tests ==="
echo "State dir: $TEST_STATE_DIR"
echo ""
# --- Help Command ---
echo "## Help Command"
output=$(run_gate help)
assert_output_contains "Help shows check command" "check \[session\]" "$output"
assert_output_contains "Help shows enable command" "enable \[session\]" "$output"
assert_output_contains "Help shows approve command" "approve \[session\]" "$output"
assert_output_contains "Help shows reject command" "reject \[session\]" "$output"
# --- Check Without State ---
echo ""
echo "## Check Without State (No Review Required)"
output=$(run_gate check no-state-session)
exit_code=$?
assert_exit_code "Check returns 0 when no state exists" "0" "$exit_code"
assert_output_contains "Check indicates no review required" "No review required" "$output"
# --- Enable Command ---
echo ""
echo "## Enable Command"
output=$(run_gate enable test-enable)
assert_output_contains "Enable confirms session" "Review enabled" "$output"
assert_file_exists "State file created" "$TEST_STATE_DIR/test-enable.json"
assert_json_field "Status is pending" "pending" ".status" "$TEST_STATE_DIR/test-enable.json"
assert_json_field "Session ID stored" "test-enable" ".session_id" "$TEST_STATE_DIR/test-enable.json"
# --- Check When Pending ---
echo ""
echo "## Check When Pending (Should Block)"
run_gate enable test-pending > /dev/null
output=$(run_gate check test-pending)
exit_code=$?
assert_exit_code "Check returns 1 when pending" "1" "$exit_code"
assert_output_contains "Check shows BLOCKED" "BLOCKED" "$output"
assert_output_contains "Check shows pending status" "pending" "$output"
# --- Approve Command ---
echo ""
echo "## Approve Command"
run_gate enable test-approve > /dev/null
output=$(run_gate approve test-approve)
assert_output_contains "Approve confirms" "Review approved" "$output"
assert_json_field "Status changed to approved" "approved" ".status" "$TEST_STATE_DIR/test-approve.json"
# --- Check When Approved ---
echo ""
echo "## Check When Approved (Should Allow)"
output=$(run_gate check test-approve)
exit_code=$?
assert_exit_code "Check returns 0 when approved" "0" "$exit_code"
assert_output_contains "Check shows approved" "approved" "$output"
# --- Reject Command ---
echo ""
echo "## Reject Command"
run_gate enable test-reject > /dev/null
output=$(run_gate reject test-reject "Missing tests")
assert_output_contains "Reject confirms" "Review rejected" "$output"
assert_output_contains "Reject shows reason" "Missing tests" "$output"
assert_json_field "Status changed to rejected" "rejected" ".status" "$TEST_STATE_DIR/test-reject.json"
assert_json_field "Reason stored" "Missing tests" ".reason" "$TEST_STATE_DIR/test-reject.json"
# --- Check When Rejected ---
echo ""
echo "## Check When Rejected (Should Block)"
output=$(run_gate check test-reject)
exit_code=$?
assert_exit_code "Check returns 1 when rejected" "1" "$exit_code"
assert_output_contains "Check shows BLOCKED" "BLOCKED" "$output"
assert_output_contains "Check shows reason" "Missing tests" "$output"
# --- Reject With Issues ---
echo ""
echo "## Reject With Multiple Issues"
run_gate enable test-issues > /dev/null
output=$(run_gate reject test-issues "Quality issues" "No unit tests" "Missing docs" "Bad naming")
issues=$(jq -r '.issues | length' "$TEST_STATE_DIR/test-issues.json")
if [[ "$issues" == "3" ]]; then
echo -e "${GREEN}PASS${NC}: Three issues stored"
((PASSED++))
else
echo -e "${RED}FAIL${NC}: Three issues stored (got $issues)"
((FAILED++))
fi
assert_json_field "First issue stored" "No unit tests" ".issues[0]" "$TEST_STATE_DIR/test-issues.json"
# Check displays issues
output=$(run_gate check test-issues)
assert_output_contains "Check displays issues" "No unit tests" "$output"
# --- Status Command ---
echo ""
echo "## Status Command"
output=$(run_gate status test-issues)
assert_output_contains "Status shows session" "test-issues" "$output"
assert_output_contains "Status shows rejected" "rejected" "$output"
# Status for non-existent session
output=$(run_gate status nonexistent)
assert_output_contains "Status handles missing session" "No review state" "$output"
# --- List Command ---
echo ""
echo "## List Command"
output=$(run_gate list)
assert_output_contains "List shows test-enable" "test-enable" "$output"
assert_output_contains "List shows test-approve" "test-approve" "$output"
assert_output_contains "List shows statuses" "approved" "$output"
assert_output_contains "List shows rejected" "rejected" "$output"
# --- Session ID Auto-Detection ---
echo ""
echo "## Session ID Auto-Detection"
# From REVIEW_SESSION_ID
export REVIEW_SESSION_ID="env-review-id"
output=$(run_gate enable)
assert_file_exists "Uses REVIEW_SESSION_ID" "$TEST_STATE_DIR/env-review-id.json"
unset REVIEW_SESSION_ID
# From CLAUDE_SESSION_ID
export CLAUDE_SESSION_ID="env-claude-id"
output=$(run_gate enable)
assert_file_exists "Uses CLAUDE_SESSION_ID" "$TEST_STATE_DIR/env-claude-id.json"
unset CLAUDE_SESSION_ID
# --- Approve Without Prior Enable ---
echo ""
echo "## Approve Without Prior Enable"
output=$(run_gate approve new-approve)
assert_output_contains "Approve works without enable" "approved" "$output"
assert_file_exists "State file created on approve" "$TEST_STATE_DIR/new-approve.json"
# --- Re-enable After Approve ---
echo ""
echo "## Re-enable After Approve (Workflow Reset)"
run_gate approve reset-session > /dev/null
run_gate enable reset-session > /dev/null
assert_json_field "Status reset to pending" "pending" ".status" "$TEST_STATE_DIR/reset-session.json"
output=$(run_gate check reset-session)
exit_code=$?
assert_exit_code "Check blocks after re-enable" "1" "$exit_code"
# --- Clean Command ---
echo ""
echo "## Clean Command"
# Create an old file (touch with old timestamp not reliable in all envs, so just test the command runs)
output=$(run_gate clean 0d)
assert_output_contains "Clean runs" "Cleaning" "$output"
# --- Unknown Command ---
echo ""
echo "## Error Handling"
output=$(run_gate unknown-cmd 2>&1)
exit_code=$?
assert_exit_code "Unknown command returns 1" "1" "$exit_code"
assert_output_contains "Unknown command shows error" "Unknown command" "$output"
# --- Summary ---
echo ""
echo "=== Summary ==="
echo -e "Passed: ${GREEN}$PASSED${NC}"
echo -e "Failed: ${RED}$FAILED${NC}"
if [[ $FAILED -gt 0 ]]; then
exit 1
fi
echo ""
echo -e "${GREEN}All tests passed!${NC}"