Files
skill-repo/tests/git-manager/git_cmd.bats
T
Henner M. Kruse dc4a5c5b5e Close bats coverage gaps, add hide_command helper, wire up kcov
- tests/helpers/common.bash: hide_command hides python3/jq/rg via a
  per-directory-batched PATH shim (not per-file — that took minutes),
  making the fail-open/grep-fallback branches testable.
- 20 new tests across all 7 .bats files: unknown flags, invalid
  --settings-scope, missing python3/jq, grep fallback when rg is
  unavailable, empty/multi-vault config edge cases, a vault path that
  stops existing or isn't a directory, and the previously-untested
  tool_name != Bash branch of force-ask-on-raw-git.sh. 53 -> 73 tests.
- hooks.bats: deploy the hooks once in setup_file() (BATS_FILE_TMPDIR)
  instead of per-test (BATS_TEST_TMPDIR) -- faster, and gives kcov one
  stable path per hook to aggregate coverage against instead of a
  fragmented copy per test.
- .gitignore (first in this repo) + tests/README.md Coverage section
  documenting the kcov invocation and why --include-pattern needs three
  entries, not two.

Real, tool-measured coverage via kcov: 86.15% (255/296 lines) across
all 10 wrapper/setup/hook scripts in both plugins, replacing an earlier
manual ~68% branch-coverage estimate.
2026-08-04 21:09:07 +00:00

132 lines
3.9 KiB
Bash

#!/usr/bin/env bats
# Tests for skills/git-manager/scripts/git_cmd.sh + _lib.sh.
load '../helpers/common'
setup() {
sandbox_home
SCRIPT="$REPO_ROOT/skills/git-manager/scripts/git_cmd.sh"
CONFIG_FILE="$HOME/.agent-skills/git-manager/config.json"
REPO="$BATS_TEST_TMPDIR/repo"
make_test_repo "$REPO"
}
# --- subcommand allowlist ---
@test "allowed subcommand (status) runs and returns real git output" {
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO"
run "$SCRIPT" status --repo myrepo
[ "$status" -eq 0 ]
[[ "$output" == *"nothing to commit"* ]]
}
@test "disallowed subcommand (stash) is rejected before git ever runs" {
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO"
run "$SCRIPT" stash --repo myrepo
[ "$status" -eq 1 ]
[[ "$output" == *"is not allowed"* ]]
}
@test "no subcommand at all prints usage and exits 1" {
run "$SCRIPT"
[ "$status" -eq 1 ]
[[ "$output" == *"Usage:"* ]]
}
# --- repo resolution ---
@test "no config file at all errors" {
run "$SCRIPT" status
[ "$status" -eq 1 ]
[[ "$output" == *"no configuration found"* ]]
}
@test "zero repos registered errors" {
write_git_manager_config "$CONFIG_FILE"
run "$SCRIPT" status
[ "$status" -eq 1 ]
[[ "$output" == *"no repos registered"* ]]
}
@test "exactly one repo registered auto-resolves without --repo" {
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO"
run "$SCRIPT" status
[ "$status" -eq 0 ]
[[ "$output" == *"$REPO"* ]]
}
@test "multiple repos registered without --repo errors and lists names" {
REPO2="$BATS_TEST_TMPDIR/repo2"
make_test_repo "$REPO2"
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO" "other=$REPO2"
run "$SCRIPT" status
[ "$status" -eq 1 ]
[[ "$output" == *"multiple repos configured"* ]]
[[ "$output" == *"myrepo"* ]]
[[ "$output" == *"other"* ]]
}
@test "--repo selects the named repo among several registered" {
REPO2="$BATS_TEST_TMPDIR/repo2"
make_test_repo "$REPO2"
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO" "other=$REPO2"
run "$SCRIPT" status --repo other
[ "$status" -eq 0 ]
[[ "$output" == *"$REPO2"* ]]
}
@test "unknown --repo name errors and lists registered names" {
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO"
run "$SCRIPT" status --repo doesnotexist
[ "$status" -eq 1 ]
[[ "$output" == *"no repo named 'doesnotexist'"* ]]
[[ "$output" == *"myrepo"* ]]
}
# --- canonicalize_and_check_repo ---
@test "registered path that no longer exists errors" {
write_git_manager_config "$CONFIG_FILE" "gone=$BATS_TEST_TMPDIR/does-not-exist"
run "$SCRIPT" status --repo gone
[ "$status" -eq 1 ]
[[ "$output" == *"does not exist"* ]]
}
@test "registered path that isn't a git work tree errors" {
PLAIN_DIR="$BATS_TEST_TMPDIR/not-a-repo"
mkdir -p "$PLAIN_DIR"
write_git_manager_config "$CONFIG_FILE" "plain=$PLAIN_DIR"
run "$SCRIPT" status --repo plain
[ "$status" -eq 1 ]
[[ "$output" == *"not inside a git work tree"* ]]
}
@test "a registered path nested inside the repo still resolves to the toplevel" {
mkdir -p "$REPO/subdir"
write_git_manager_config "$CONFIG_FILE" "nested=$REPO/subdir"
run "$SCRIPT" status --repo nested
[ "$status" -eq 0 ]
[[ "$output" == *"== Repo: $REPO =="* ]]
}
# --- -- passthrough ---
@test "args after -- reach git unmodified" {
git -C "$REPO" -c user.email=test@test -c user.name=test \
commit -q --allow-empty -m "second"
git -C "$REPO" -c user.email=test@test -c user.name=test \
commit -q --allow-empty -m "third"
write_git_manager_config "$CONFIG_FILE" "myrepo=$REPO"
run "$SCRIPT" log --repo myrepo -- --oneline -n2
[ "$status" -eq 0 ]
# 2 commit lines + the script's own "== Repo ==" / "== Running ==" banner lines
commit_lines=$(printf '%s\n' "$output" | grep -c '^[0-9a-f]\{7,\} ')
[ "$commit_lines" -eq 2 ]
}
@test "an argument outside --repo/-- is rejected" {
run "$SCRIPT" status extra
[ "$status" -eq 1 ]
[[ "$output" == *"unexpected argument 'extra'"* ]]
}