Add git-identity: switch git author identity from a saved menu
Identities live in ~/.git-identities (alias|Name|email). Interactive menu to select, add, or remove identities; direct mode via alias argument; --global/-g scope flag (defaults to local inside a repo, global fallback outside); --list/--current helpers. Full --dryrun support and a 27-assertion test suite driven through dryrun. GIT_IDENTITIES_FILE env override for testability.
This commit is contained in:
120
tests/test-git-identity.sh
Executable file
120
tests/test-git-identity.sh
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
GIT_IDENTITY="$SCRIPT_DIR/scripts/git-identity"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
assert_match() {
|
||||
local desc="$1" pattern="$2" actual="$3"
|
||||
if [[ "$actual" =~ $pattern ]]; then
|
||||
echo -e "${GREEN}PASS${NC}: $desc"
|
||||
((pass++))
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}: $desc"
|
||||
echo " pattern: $pattern"
|
||||
echo " actual: $actual"
|
||||
((fail++))
|
||||
fi
|
||||
}
|
||||
|
||||
assert_exit() {
|
||||
local desc="$1" expected="$2" actual="$3"
|
||||
if [[ "$expected" == "$actual" ]]; then
|
||||
echo -e "${GREEN}PASS${NC}: $desc"
|
||||
((pass++))
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}: $desc (expected exit $expected, got $actual)"
|
||||
((fail++))
|
||||
fi
|
||||
}
|
||||
|
||||
# Fixture: temp identities file and a temp git repo
|
||||
TMPDIR_T=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR_T"' EXIT
|
||||
IDFILE="$TMPDIR_T/identities"
|
||||
cat > "$IDFILE" <<'EOF'
|
||||
# alias|Name|email
|
||||
personal|Test Person|test@example.net
|
||||
work|Test Person|test.person@corp.example
|
||||
EOF
|
||||
REPO="$TMPDIR_T/repo"
|
||||
mkdir -p "$REPO" && git -C "$REPO" init -q
|
||||
|
||||
run() { GIT_IDENTITIES_FILE="$IDFILE" "$GIT_IDENTITY" "$@"; }
|
||||
|
||||
# --help
|
||||
out=$(run --help); rc=$?
|
||||
assert_exit "--help exits 0" 0 "$rc"
|
||||
assert_match "--help shows usage" "Usage: git-identity" "$out"
|
||||
|
||||
# --list
|
||||
out=$(run --list); rc=$?
|
||||
assert_exit "--list exits 0" 0 "$rc"
|
||||
assert_match "--list shows personal" "personal.*test@example\.net" "$out"
|
||||
assert_match "--list shows work" "work.*test\.person@corp\.example" "$out"
|
||||
|
||||
# direct apply, dryrun, inside repo -> local scope
|
||||
out=$(cd "$REPO" && run -n work); rc=$?
|
||||
assert_exit "dryrun apply exits 0" 0 "$rc"
|
||||
assert_match "dryrun apply previews local set" \
|
||||
"\[dryrun\] Would set user.name 'Test Person' and user.email 'test.person@corp.example' \(--local in " "$out"
|
||||
|
||||
# dryrun apply did not change config
|
||||
name=$(git -C "$REPO" config --local user.name 2>/dev/null || echo "UNSET")
|
||||
assert_match "dryrun did not write config" "UNSET" "$name"
|
||||
|
||||
# direct apply, dryrun, outside repo -> global fallback note
|
||||
out=$(cd "$TMPDIR_T" && run -n personal); rc=$?
|
||||
assert_exit "dryrun global fallback exits 0" 0 "$rc"
|
||||
assert_match "notes global fallback" "not inside a git repository" "$out"
|
||||
assert_match "previews global set" "\(--global\)" "$out"
|
||||
|
||||
# --global flag, dryrun
|
||||
out=$(cd "$REPO" && run -n -g personal); rc=$?
|
||||
assert_match "dryrun --global previews global scope" "\(--global\)" "$out"
|
||||
|
||||
# unknown alias
|
||||
out=$(cd "$REPO" && run -n nosuch 2>&1); rc=$?
|
||||
assert_exit "unknown alias exits 1" 1 "$rc"
|
||||
assert_match "unknown alias error names file" "No identity 'nosuch'" "$out"
|
||||
assert_match "unknown alias lists available" "Available: personal work" "$out"
|
||||
|
||||
# missing file, direct mode
|
||||
out=$(GIT_IDENTITIES_FILE="$TMPDIR_T/absent" "$GIT_IDENTITY" -n work 2>&1); rc=$?
|
||||
assert_exit "missing file exits 1" 1 "$rc"
|
||||
assert_match "missing file error" "No identities file" "$out"
|
||||
|
||||
# interactive menu: select identity 2 via stdin, dryrun
|
||||
out=$(cd "$REPO" && printf '2\n' | run -n); rc=$?
|
||||
assert_exit "interactive select exits 0" 0 "$rc"
|
||||
assert_match "interactive shows menu" "1\) personal" "$out"
|
||||
assert_match "interactive select previews apply" "\[dryrun\] Would set user.name 'Test Person' and user.email 'test.person@corp.example'" "$out"
|
||||
|
||||
# interactive: something else -> add, dryrun
|
||||
out=$(cd "$REPO" && printf 's\na\nnewalias\nNew Name\nnew@example.net\nn\n' | run -n); rc=$?
|
||||
assert_exit "interactive add exits 0" 0 "$rc"
|
||||
assert_match "add previews append" "\[dryrun\] Would append 'newalias\|New Name\|new@example.net'" "$out"
|
||||
grep -q "newalias" "$IDFILE" && added=yes || added=no
|
||||
assert_match "dryrun add did not write file" "no" "$added"
|
||||
|
||||
# interactive: something else -> remove, dryrun
|
||||
out=$(cd "$REPO" && printf 's\nr\n1\n' | run -n); rc=$?
|
||||
assert_exit "interactive remove exits 0" 0 "$rc"
|
||||
assert_match "remove previews deletion" "\[dryrun\] Would remove identity 'personal'" "$out"
|
||||
grep -q "^personal|" "$IDFILE" && still=yes || still=no
|
||||
assert_match "dryrun remove did not write file" "yes" "$still"
|
||||
|
||||
# duplicate alias rejected during add (then cancel with empty alias)
|
||||
out=$(cd "$REPO" && printf 's\na\nwork\n\n' | run -n); rc=$?
|
||||
assert_match "duplicate alias rejected" "Alias 'work' already exists" "$out"
|
||||
|
||||
echo ""
|
||||
echo "Results: $pass passed, $fail failed"
|
||||
[[ $fail -eq 0 ]]
|
||||
Reference in New Issue
Block a user