#!/usr/bin/env bats # # Tests for scripts/sweep-gitignore-tooling.sh — backfill the personal-tooling # gitignore set across existing gitignore-mode AI projects. # # Strategy: scaffold fake AI projects (a .ai/protocols.org marker + a git repo) # under a temp root, run the sweep against that root, and assert on each # project's .gitignore. REAL_REPO="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)" SWEEP="$REAL_REPO/scripts/sweep-gitignore-tooling.sh" setup() { ROOT="$(mktemp -d -t sweep-bats.XXXXXX)" } teardown() { rm -rf "$ROOT" } # Scaffold a project: $1 = name, $2 = initial .gitignore content (may be empty), # $3 = "git" to init a repo (default), "nogit" to skip. make_project() { local name="$1" gitignore="${2-}" git="${3-git}" mkdir -p "$ROOT/$name/.ai" echo "marker" > "$ROOT/$name/.ai/protocols.org" [ -n "$gitignore" ] && printf '%s' "$gitignore" > "$ROOT/$name/.gitignore" [ "$git" = "git" ] && (cd "$ROOT/$name" && git init -q) return 0 } @test "sweep: gitignore-mode project missing all three gets them appended" { make_project gimode $'# tooling\n.ai/\n' run bash "$SWEEP" "$ROOT" [ "$status" -eq 0 ] grep -qFx ".claude/" "$ROOT/gimode/.gitignore" grep -qFx "CLAUDE.md" "$ROOT/gimode/.gitignore" grep -qFx "AGENTS.md" "$ROOT/gimode/.gitignore" } @test "sweep: is idempotent — a second run adds nothing" { make_project gimode $'.ai/\n' bash "$SWEEP" "$ROOT" >/dev/null run bash "$SWEEP" "$ROOT" [ "$status" -eq 0 ] [[ "$output" == *"already complete"* ]] # No line is duplicated. [ "$(grep -cFx '.claude/' "$ROOT/gimode/.gitignore")" -eq 1 ] [ "$(grep -cFx 'CLAUDE.md' "$ROOT/gimode/.gitignore")" -eq 1 ] [ "$(grep -cFx 'AGENTS.md' "$ROOT/gimode/.gitignore")" -eq 1 ] } @test "sweep: track-mode project (.ai/ not ignored) is skipped untouched" { make_project trackmode $'# build\nout/\n' run bash "$SWEEP" "$ROOT" [ "$status" -eq 0 ] [[ "$output" == *"track-mode"* ]] # .gitignore is untouched — none of the tooling lines were added. ! grep -qFx ".claude/" "$ROOT/trackmode/.gitignore" ! grep -qFx "CLAUDE.md" "$ROOT/trackmode/.gitignore" } @test "sweep: partial project gets only the missing lines" { make_project partial $'.ai/\n.claude/\n' run bash "$SWEEP" "$ROOT" [ "$status" -eq 0 ] [ "$(grep -cFx '.claude/' "$ROOT/partial/.gitignore")" -eq 1 ] grep -qFx "CLAUDE.md" "$ROOT/partial/.gitignore" grep -qFx "AGENTS.md" "$ROOT/partial/.gitignore" } @test "sweep: --dry-run reports without writing" { make_project gimode $'.ai/\n' run bash "$SWEEP" --dry-run "$ROOT" [ "$status" -eq 0 ] [[ "$output" == *"would add"* ]] [[ "$output" == *"no files written"* ]] # Nothing was actually written. ! grep -qFx ".claude/" "$ROOT/gimode/.gitignore" } @test "sweep: warns when a now-ignored path is already tracked" { make_project tracked $'.ai/\n' echo "# project rules" > "$ROOT/tracked/CLAUDE.md" (cd "$ROOT/tracked" && git add CLAUDE.md && git -c user.email=t@t -c user.name=t commit -qm seed) run bash "$SWEEP" "$ROOT" [ "$status" -eq 0 ] [[ "$output" == *"WARN"* ]] [[ "$output" == *"CLAUDE.md is currently tracked"* ]] } @test "sweep: non-git project with .ai/ marker is skipped" { make_project nogit $'.ai/\n' "" nogit run bash "$SWEEP" "$ROOT" [ "$status" -eq 0 ] [[ "$output" == *"not a git checkout"* ]] }