aboutsummaryrefslogtreecommitdiff
path: root/scripts/tests/rename-ai-artifact.bats
blob: f00c92fa7afbc78a0e3710a8a6b1dd2c09a57166 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/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 ]
}