# Shared helpers for this repo's bats suites. Loaded with `load
# '../helpers/common'` at the top of each .bats file.
#
# The core trick used throughout: point $HOME at a fresh
# $BATS_TEST_TMPDIR/home before each test, so every script under test that
# reads/writes ~/.agent-skills/... or ~/.claude/settings.json is fully
# sandboxed and cleaned up automatically by bats after the test — no shared
# state between tests, and never touches the real machine's config.
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Call from a test file's setup() after exporting HOME.
sandbox_home() {
export HOME="$BATS_TEST_TMPDIR/home"
mkdir -p "$HOME"
}
# make_test_repo
— git-init a throwaway repo with one commit so
# `git status`/`log`/etc have something real to operate on.
make_test_repo() {
local dir="$1"
mkdir -p "$dir"
git -C "$dir" init -q
git -C "$dir" -c user.email=test@test -c user.name=test \
commit -q --allow-empty -m "init"
}
# write_git_manager_config = [= ...]
# Writes a git-manager config.json registering the given repos.
write_git_manager_config() {
local config_file="$1"; shift
mkdir -p "$(dirname "$config_file")"
python3 - "$config_file" "$@" << 'PYEOF'
import json, sys
config_file, pairs = sys.argv[1], sys.argv[2:]
repos = []
for p in pairs:
name, path = p.split("=", 1)
repos.append({"name": name, "path": path})
with open(config_file, "w") as f:
json.dump({"repos": repos}, f)
PYEOF
}
# make_test_vault — a small Obsidian-shaped vault: two notes with
# frontmatter tags that wikilink each other, plus .obsidian/.git noise and
# a non-markdown attachment, so exclusion behavior is exercisable.
make_test_vault() {
local dir="$1"
mkdir -p "$dir/Notes" "$dir/.obsidian" "$dir/.git"
cat > "$dir/Notes/dns-setup.md" << 'EOF'
---
tags: [networking, dns]
---
# DNS Setup
Configured pihole as the primary resolver. See [[homelab-overview]].
EOF
cat > "$dir/Notes/homelab-overview.md" << 'EOF'
---
tags: [homelab, overview]
---
# Homelab Overview
Links to [[dns-setup]] and other topics.
EOF
echo "obsidian-internal-marker" > "$dir/.obsidian/config"
echo "attachment-only-marker" > "$dir/Notes/attachment.pdf"
}
# write_vault_config = [= ...]
write_vault_config() {
local config_file="$1"; local mode="$2"; shift 2
mkdir -p "$(dirname "$config_file")"
python3 - "$config_file" "$mode" "$@" << 'PYEOF'
import json, sys
config_file, mode, pairs = sys.argv[1], sys.argv[2], sys.argv[3:]
vaults = []
for p in pairs:
name, path = p.split("=", 1)
vaults.append({"name": name, "path": path})
with open(config_file, "w") as f:
json.dump({"vaults": vaults, "mode": mode}, f)
PYEOF
}
# json_get — small helper for assertions against JSON
# written by setup.sh, without needing jq as a test dependency.
json_get() {
local file="$1" path="$2"
python3 -c '
import json, sys
with open(sys.argv[1]) as f:
data = json.load(f)
for key in sys.argv[2].split("."):
if key == "":
continue
data = data[int(key)] if key.isdigit() else data[key]
print(json.dumps(data))
' "$file" "$path"
}