Add bats test suite for git-manager and obsidian-vault-kb
Isolated per-test $HOME sandboxing via tests/helpers/common.bash. Covers both plugins' wrapper scripts, their setup.sh, and git-manager's two PreToolUse hooks (53 tests). Verified the suite catches regressions by temporarily reintroducing the recently-fixed vault_search.sh -g/-- ordering bug and confirming it fails.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# 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 <dir> — 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 <config_file> <name>=<path> [<name>=<path> ...]
|
||||
# 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 <dir> — 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 <config_file> <mode> <name>=<path> [<name>=<path> ...]
|
||||
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 <file> <dotted.path> — 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"
|
||||
}
|
||||
Reference in New Issue
Block a user