#!/usr/bin/env bash set -euo pipefail # Test check-skills script SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT="$SCRIPT_DIR/../scripts/check-skills" GREEN='\033[0;32m' RED='\033[0;31m' NC='\033[0m' pass=0 fail=0 assert_exit() { local desc="$1" expected="$2" shift 2 local actual if "$@" >/dev/null 2>&1; then actual=0; else actual=$?; fi if [[ "$actual" -eq "$expected" ]]; then echo -e " ${GREEN}PASS${NC} $desc" pass=$((pass + 1)) else echo -e " ${RED}FAIL${NC} $desc (expected exit $expected, got $actual)" fail=$((fail + 1)) fi } assert_output_contains() { local desc="$1" pattern="$2" shift 2 local output output="$("$@" 2>&1)" || true if echo "$output" | grep -qE "$pattern"; then echo -e " ${GREEN}PASS${NC} $desc" pass=$((pass + 1)) else echo -e " ${RED}FAIL${NC} $desc (pattern '$pattern' not found in output)" fail=$((fail + 1)) fi } # Setup temp dirs TMPDIR_ROOT="$(mktemp -d)" trap 'rm -rf "$TMPDIR_ROOT"' EXIT # Create a fake skills source with two skills FAKE_SOURCE="$TMPDIR_ROOT/source" mkdir -p "$FAKE_SOURCE/skill-a" "$FAKE_SOURCE/skill-b" "$FAKE_SOURCE/not-a-skill" echo "---" > "$FAKE_SOURCE/skill-a/SKILL.md" echo "---" > "$FAKE_SOURCE/skill-b/SKILL.md" # not-a-skill has no SKILL.md — should be skipped # Test 1: All linked echo "Test: All skills linked" FAKE_PROFILE="$TMPDIR_ROOT/profile-all" mkdir -p "$FAKE_PROFILE/skills" ln -s "$FAKE_SOURCE/skill-a" "$FAKE_PROFILE/skills/skill-a" ln -s "$FAKE_SOURCE/skill-b" "$FAKE_PROFILE/skills/skill-b" assert_exit "exits 0 when all linked" 0 "$SCRIPT" --profile "$FAKE_PROFILE" "$FAKE_SOURCE" assert_output_contains "shows LINKED for skill-a" "LINKED.*skill-a" "$SCRIPT" --profile "$FAKE_PROFILE" "$FAKE_SOURCE" assert_output_contains "shows LINKED for skill-b" "LINKED.*skill-b" "$SCRIPT" --profile "$FAKE_PROFILE" "$FAKE_SOURCE" assert_output_contains "summary shows 2 linked" "2 linked" "$SCRIPT" --profile "$FAKE_PROFILE" "$FAKE_SOURCE" # Test 2: Missing skill echo "Test: Missing skill" FAKE_PROFILE2="$TMPDIR_ROOT/profile-missing" mkdir -p "$FAKE_PROFILE2/skills" ln -s "$FAKE_SOURCE/skill-a" "$FAKE_PROFILE2/skills/skill-a" assert_exit "exits 1 when skill missing" 1 "$SCRIPT" --profile "$FAKE_PROFILE2" "$FAKE_SOURCE" assert_output_contains "shows MISSING for skill-b" "MISSING.*skill-b" "$SCRIPT" --profile "$FAKE_PROFILE2" "$FAKE_SOURCE" # Test 3: Stale symlink (points elsewhere) echo "Test: Stale symlink" FAKE_PROFILE3="$TMPDIR_ROOT/profile-stale" mkdir -p "$FAKE_PROFILE3/skills" ln -s "$FAKE_SOURCE/skill-a" "$FAKE_PROFILE3/skills/skill-a" ln -s "/some/other/path" "$FAKE_PROFILE3/skills/skill-b" assert_exit "exits 1 when stale" 1 "$SCRIPT" --profile "$FAKE_PROFILE3" "$FAKE_SOURCE" assert_output_contains "shows STALE for skill-b" "STALE.*skill-b" "$SCRIPT" --profile "$FAKE_PROFILE3" "$FAKE_SOURCE" # Test 4: Orphan skill echo "Test: Orphan skill" FAKE_PROFILE4="$TMPDIR_ROOT/profile-orphan" mkdir -p "$FAKE_PROFILE4/skills/extra-skill" ln -s "$FAKE_SOURCE/skill-a" "$FAKE_PROFILE4/skills/skill-a" ln -s "$FAKE_SOURCE/skill-b" "$FAKE_PROFILE4/skills/skill-b" assert_exit "exits 0 (orphans are informational)" 0 "$SCRIPT" --profile "$FAKE_PROFILE4" "$FAKE_SOURCE" assert_output_contains "shows ORPHAN for extra-skill" "ORPHAN.*extra-skill" "$SCRIPT" --profile "$FAKE_PROFILE4" "$FAKE_SOURCE" # Test 5: No profile skills dir echo "Test: No profile skills directory" FAKE_PROFILE5="$TMPDIR_ROOT/profile-empty" mkdir -p "$FAKE_PROFILE5" assert_exit "exits 1 when no skills dir (all missing)" 1 "$SCRIPT" --profile "$FAKE_PROFILE5" "$FAKE_SOURCE" assert_output_contains "shows MISSING for both" "2 missing" "$SCRIPT" --profile "$FAKE_PROFILE5" "$FAKE_SOURCE" # Test 6: Invalid source dir echo "Test: Invalid source directory" assert_exit "exits 1 for nonexistent source" 1 "$SCRIPT" --profile "$FAKE_PROFILE" "/nonexistent/path" # Test 7: --help echo "Test: Help flag" assert_exit "--help exits 0" 0 "$SCRIPT" --help assert_output_contains "--help shows usage" "Usage:" "$SCRIPT" --help # Test 8: --dryrun accepted echo "Test: Dryrun flag" assert_exit "--dryrun accepted" 0 "$SCRIPT" --dryrun --profile "$FAKE_PROFILE" "$FAKE_SOURCE" # Test 9: Skips dirs without SKILL.md echo "Test: Skips non-skill directories" output="$("$SCRIPT" --profile "$FAKE_PROFILE" "$FAKE_SOURCE" 2>&1)" if echo "$output" | grep -q "not-a-skill"; then echo -e " ${RED}FAIL${NC} should not list not-a-skill" fail=$((fail + 1)) else echo -e " ${GREEN}PASS${NC} correctly skips dir without SKILL.md" pass=$((pass + 1)) fi echo "" echo "Results: $pass passed, $fail failed" [[ $fail -eq 0 ]]