#!/usr/bin/env bats # # Tests for scripts/rename-ai-artifact.sh — rename an .ai artifact (workflow or # script) across the canonical + mirror trees, rewriting every reference and # leaving archived session records (history) untouched. # # Strategy: build a synthetic git repo mirroring the canonical/mirror layout in # a temp dir, copy the real script in, and run it there. The script resolves # the repo root from git, so it operates entirely on the fixture. The verify # step (workflow-integrity / sync-check) is best-effort and skips when those # scripts are absent, which they are in the fixture. REAL_REPO="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)" SCRIPT_SRC="$REAL_REPO/scripts/rename-ai-artifact.sh" setup() { REPO="$(mktemp -d -t rename-bats.XXXXXX)" mkdir -p "$REPO/scripts" cp "$SCRIPT_SRC" "$REPO/scripts/rename-ai-artifact.sh" # Canonical + mirror trees. for base in "$REPO/claude-templates/.ai" "$REPO/.ai"; do mkdir -p "$base/workflows" "$base/scripts" "$base/sessions" printf '* Summary\nThe foo workflow.\nTriggers: "run the foo workflow"\n' > "$base/workflows/foo.org" printf '#+TITLE: Index\n- =foo.org= — the foo workflow.\n- =foobar.org= — unrelated, must survive.\n' > "$base/workflows/INDEX.org" printf '* Summary\nThe foobar workflow (must not be touched by a foo rename).\n' > "$base/workflows/foobar.org" printf '#!/usr/bin/env python3\n# foo-helper for the foo workflow\nprint("foo-helper")\n' > "$base/scripts/foo-helper.py" printf 'Old session mentioning foo and foo.org — this is history.\n' > "$base/sessions/2026-01-01-old.org" done printf 'See foo.org and foo-helper.py. Also foobar.org stays.\n' > "$REPO/notes.org" ( cd "$REPO" && git init -q && git add -A && git -c user.email=t@t -c user.name=t commit -qm init ) } teardown() { rm -rf "$REPO" } run_rename() { # OLD NEW ( cd "$REPO" && bash scripts/rename-ai-artifact.sh "$1" "$2" ) } # --- Normal: workflow rename across both trees --- @test "rename: moves a workflow in both canonical and mirror" { run run_rename foo.org bar.org [ "$status" -eq 0 ] [ -f "$REPO/claude-templates/.ai/workflows/bar.org" ] [ -f "$REPO/.ai/workflows/bar.org" ] [ ! -e "$REPO/claude-templates/.ai/workflows/foo.org" ] [ ! -e "$REPO/.ai/workflows/foo.org" ] } @test "rename: rewrites references in the index and prose" { run_rename foo.org bar.org grep -q "=bar.org=" "$REPO/.ai/workflows/INDEX.org" grep -q "run the bar workflow" "$REPO/.ai/workflows/bar.org" grep -q "bar.org" "$REPO/notes.org" ! grep -q "foo.org" "$REPO/notes.org" } # --- The kernel: history is untouched, near-miss names survive --- @test "rename: archived session records are left as history" { run_rename foo.org bar.org grep -q "mentioning foo and foo.org" "$REPO/.ai/sessions/2026-01-01-old.org" grep -q "mentioning foo and foo.org" "$REPO/claude-templates/.ai/sessions/2026-01-01-old.org" } @test "rename: a longer name sharing the prefix is not corrupted" { run_rename foo.org bar.org # foobar.org and its index row must be intact — token-boundary matching. [ -f "$REPO/.ai/workflows/foobar.org" ] grep -q "=foobar.org=" "$REPO/.ai/workflows/INDEX.org" grep -q "foobar.org stays" "$REPO/notes.org" } # --- Script artifact (no .org extension to strip cleanly) --- @test "rename: renames a script artifact and its references" { run run_rename foo-helper.py baz-helper.py [ "$status" -eq 0 ] [ -f "$REPO/.ai/scripts/baz-helper.py" ] [ -f "$REPO/claude-templates/.ai/scripts/baz-helper.py" ] grep -q "baz-helper.py" "$REPO/notes.org" ! grep -q "foo-helper" "$REPO/notes.org" } @test "rename: also rewrites the underscore module-name variant" { # A python test imports the hyphenated script under an underscored module # name, the way importlib.spec_from_file_location does. Renaming the script # must update both the hyphen path and the underscore module name. for base in "$REPO/claude-templates/.ai" "$REPO/.ai"; do printf 'spec_from_file_location("foo_helper", "foo-helper.py")\n' \ > "$base/scripts/uses-helper.py" done ( cd "$REPO" && git add -A && git -c user.email=t@t -c user.name=t commit -qm add ) run run_rename foo-helper.py baz-helper.py [ "$status" -eq 0 ] grep -q 'spec_from_file_location("baz_helper", "baz-helper.py")' "$REPO/.ai/scripts/uses-helper.py" ! grep -q "foo_helper" "$REPO/.ai/scripts/uses-helper.py" } # --- Errors --- @test "rename: refuses when the source artifact does not exist" { run run_rename nope.org bar.org [ "$status" -ne 0 ] [[ "$output" == *"not found"* ]] } @test "rename: refuses when the target already exists" { run run_rename foo.org foobar.org [ "$status" -ne 0 ] [[ "$output" == *"exists"* ]] } @test "rename: refuses bad usage (missing args)" { run bash "$REPO/scripts/rename-ai-artifact.sh" only-one-arg [ "$status" -ne 0 ] }