#!/usr/bin/env bats # Tests for vendor/claude-code/plugins/git-manager/scripts/setup.sh. load '../helpers/common' setup() { sandbox_home SETUP="$REPO_ROOT/vendor/claude-code/plugins/git-manager/scripts/setup.sh" SETTINGS_FILE="$HOME/.claude/settings.json" CONFIG_FILE="$HOME/.agent-skills/git-manager/config.json" REPO="$BATS_TEST_TMPDIR/repo" make_test_repo "$REPO" } @test "writes the two expected tilde-form permission rules" { run "$SETUP" --settings-scope user [ "$status" -eq 0 ] allow=$(json_get "$SETTINGS_FILE" "permissions.allow") [[ "$allow" == *'Bash(~/.agent-skills/git-manager/bin/git_cmd.sh:*)'* ]] [[ "$allow" == *'Read(~/.agent-skills/git-manager/config.json)'* ]] } @test "merges into an existing settings.json without disturbing unrelated keys" { mkdir -p "$(dirname "$SETTINGS_FILE")" cat > "$SETTINGS_FILE" << 'EOF' {"permissions": {"allow": ["Bash(ls:*)"]}, "unrelatedTopLevelKey": "keep-me"} EOF run "$SETUP" --settings-scope user [ "$status" -eq 0 ] allow=$(json_get "$SETTINGS_FILE" "permissions.allow") [[ "$allow" == *'Bash(ls:*)'* ]] [[ "$allow" == *'Bash(~/.agent-skills/git-manager/bin/git_cmd.sh:*)'* ]] kept=$(json_get "$SETTINGS_FILE" "unrelatedTopLevelKey") [ "$kept" = '"keep-me"' ] } @test "re-running setup is idempotent: no duplicate allow entries" { "$SETUP" --settings-scope user > /dev/null run "$SETUP" --settings-scope user [ "$status" -eq 0 ] count=$(python3 -c "import json; print(json.load(open('$SETTINGS_FILE'))['permissions']['allow'].count('Bash(~/.agent-skills/git-manager/bin/git_cmd.sh:*)'))") [ "$count" -eq 1 ] } @test "--repo registers a new repo in config.json" { run "$SETUP" --settings-scope user --repo myrepo="$REPO" [ "$status" -eq 0 ] path=$(json_get "$CONFIG_FILE" "repos.0.path") [ "$path" = "\"$REPO\"" ] } @test "registering the same repo name twice updates the path instead of duplicating" { REPO2="$BATS_TEST_TMPDIR/repo2" make_test_repo "$REPO2" "$SETUP" --settings-scope user --repo myrepo="$REPO" > /dev/null run "$SETUP" --settings-scope user --repo myrepo="$REPO2" [ "$status" -eq 0 ] count=$(python3 -c "import json; print(len(json.load(open('$CONFIG_FILE'))['repos']))") [ "$count" -eq 1 ] path=$(json_get "$CONFIG_FILE" "repos.0.path") [ "$path" = "\"$REPO2\"" ] } @test "without --install-hook or --install-raw-git-hook, no PreToolUse hooks are installed" { run "$SETUP" --settings-scope user [ "$status" -eq 0 ] run python3 -c "import json; print('hooks' in json.load(open('$SETTINGS_FILE')))" [ "$output" = "False" ] } @test "--install-hook installs only the anti-chaining hook" { run "$SETUP" --settings-scope user --install-hook [ "$status" -eq 0 ] run python3 -c " import json h = json.load(open('$SETTINGS_FILE'))['hooks']['PreToolUse'] cmds = [c['command'] for e in h for c in e['hooks']] print(len(cmds)) print(any('force-ask-on-chaining.sh' in c for c in cmds)) print(any('force-ask-on-raw-git.sh' in c for c in cmds)) " [[ "$output" == $'1\nTrue\nFalse' ]] } @test "--install-raw-git-hook installs only the raw-git nudge hook" { run "$SETUP" --settings-scope user --install-raw-git-hook [ "$status" -eq 0 ] run python3 -c " import json h = json.load(open('$SETTINGS_FILE'))['hooks']['PreToolUse'] cmds = [c['command'] for e in h for c in e['hooks']] print(len(cmds)) print(any('force-ask-on-chaining.sh' in c for c in cmds)) print(any('force-ask-on-raw-git.sh' in c for c in cmds)) " [[ "$output" == $'1\nFalse\nTrue' ]] } @test "--settings-scope project writes under /.claude/settings.json" { PROJECT_DIR="$BATS_TEST_TMPDIR/someproject" mkdir -p "$PROJECT_DIR" run "$SETUP" --settings-scope project --project-dir "$PROJECT_DIR" [ "$status" -eq 0 ] [ -f "$PROJECT_DIR/.claude/settings.json" ] [ ! -e "$HOME/.claude/settings.json" ] } @test "an unknown flag errors" { run "$SETUP" --settings-scope user --bogus-flag [ "$status" -eq 1 ] [[ "$output" == *"unknown argument '--bogus-flag'"* ]] } @test "an invalid --settings-scope value errors" { run "$SETUP" --settings-scope nonsense [ "$status" -eq 1 ] [[ "$output" == *"--settings-scope must be 'project' or 'user'"* ]] } @test "missing python3 fails with a clear error instead of a silent crash" { hide_command python3 run "$SETUP" --settings-scope user [ "$status" -eq 1 ] [[ "$output" == *"python3 is required"* ]] }