blob: 12ecb835e59ba5c48a0a139f820ab945ae4526a8 (
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
|
#!/usr/bin/env bats
#
# Tests for claude-templates/.ai/scripts/capture-guard — detects live
# org-capture buffers visiting a target file before a workflow edits that
# file on disk (the roam inbox, in inbox-zero Phase D). Editing the file
# underneath an indirect org-capture buffer wedges the capture (see emacs.md).
#
# Contract under test:
# capture-guard [TARGET_FILE] (default TARGET_FILE = ~/org/roam/inbox.org)
# exit 0 → safe to edit: emacsclient absent, daemon unreachable, or no
# capture buffer visits TARGET_FILE.
# exit 1 → a live capture buffer visits TARGET_FILE; its name(s) printed.
#
# Strategy: the emacsclient boundary is mocked with a PATH stub. The stub
# answers the reachability probe (`-e t`) per STUB_REACHABLE and returns a
# canned, real-emacsclient-shaped result (quoted string) for the buffer query
# per STUB_BUFS. The script's own quote-stripping and exit logic is the code
# under test; the file-equal-p precision is real-Emacs behavior we trust.
SCRIPT="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)/capture-guard"
BASH_BIN="$(command -v bash)"
setup() {
TEST_DIR="$(mktemp -d -t capture-guard-bats.XXXXXX)"
STUB_DIR="$TEST_DIR/bin"
mkdir -p "$STUB_DIR"
cat > "$STUB_DIR/emacsclient" <<'STUB'
#!/usr/bin/env bash
# Mock emacsclient. `-e t` is the reachability probe; anything else is the
# buffer query, answered with the real-emacsclient-shaped quoted string.
expr="$2"
if [ "$expr" = "t" ]; then
[ "${STUB_REACHABLE:-1}" = "1" ] && { echo t; exit 0; }
exit 1
fi
printf '%s\n' "${STUB_BUFS:-\"\"}"
exit 0
STUB
chmod +x "$STUB_DIR/emacsclient"
EMPTY_DIR="$TEST_DIR/empty"
mkdir -p "$EMPTY_DIR"
}
teardown() {
rm -rf "$TEST_DIR"
}
# ---- Safe-to-edit (exit 0) cases ------------------------------------
@test "capture-guard: emacsclient absent is safe (exit 0, no output)" {
run env PATH="$EMPTY_DIR" "$BASH_BIN" "$SCRIPT"
[ "$status" -eq 0 ]
[ -z "$output" ]
}
@test "capture-guard: daemon unreachable is safe (exit 0)" {
run env PATH="$STUB_DIR:$PATH" STUB_REACHABLE=0 "$BASH_BIN" "$SCRIPT"
[ "$status" -eq 0 ]
[ -z "$output" ]
}
@test "capture-guard: reachable with no capture buffers is safe (exit 0)" {
run env PATH="$STUB_DIR:$PATH" STUB_REACHABLE=1 STUB_BUFS='""' "$BASH_BIN" "$SCRIPT"
[ "$status" -eq 0 ]
[ -z "$output" ]
}
# ---- Blocked (exit 1) cases -----------------------------------------
@test "capture-guard: one live capture buffer blocks (exit 1, name printed)" {
run env PATH="$STUB_DIR:$PATH" STUB_REACHABLE=1 STUB_BUFS='"CAPTURE-inbox.org"' \
"$BASH_BIN" "$SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" == *"CAPTURE-inbox.org"* ]]
}
@test "capture-guard: multiple live capture buffers all reported (exit 1)" {
run env PATH="$STUB_DIR:$PATH" STUB_REACHABLE=1 \
STUB_BUFS='"CAPTURE-inbox.org,CAPTURE-2-inbox.org"' \
"$BASH_BIN" "$SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" == *"CAPTURE-inbox.org"* ]]
[[ "$output" == *"CAPTURE-2-inbox.org"* ]]
}
@test "capture-guard: blocked output does not contain stray surrounding quotes" {
run env PATH="$STUB_DIR:$PATH" STUB_REACHABLE=1 STUB_BUFS='"CAPTURE-inbox.org"' \
"$BASH_BIN" "$SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" != \"* ]]
[[ "$output" != *\" ]]
}
# ---- Argument handling ----------------------------------------------
@test "capture-guard: accepts an explicit target-file argument" {
run env PATH="$STUB_DIR:$PATH" STUB_REACHABLE=1 STUB_BUFS='""' \
"$BASH_BIN" "$SCRIPT" "$TEST_DIR/some-other-inbox.org"
[ "$status" -eq 0 ]
[ -z "$output" ]
}
|