Files
small-scripts/tests/test-check-skills.sh
Paul O'Reilly cbde292dd7 Add check-skills: verify skill symlinks match source repo
Compares installed skill symlinks against the source directory,
reporting missing, stale, and orphan entries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:14:25 +13:00

126 lines
4.6 KiB
Bash
Executable File

#!/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 ]]