Files
josh-sync/tests/unit/cli.bats

124 lines
4.6 KiB
Plaintext
Raw Normal View History

#!/usr/bin/env bats
bats_require_minimum_version 1.5.0
# tests/unit/cli.bats — bin/josh-sync CLI surface tests
#
# Invokes the CLI as a subprocess (not by sourcing libs) so flag parsing,
# command dispatch, help/usage text, and the `adopt → onboard --mode=adopt`
# alias regress cleanly. These tests deliberately stay at the parse/dispatch
# layer — anything that would reach out to git remotes is set up to fail at
# target-lookup time, before any side effects.
#
# Uses `run --separate-stderr` so we can assert on stderr separately (most of
# josh-sync's output is logged via core.sh's `log()` which writes to stderr).
setup() {
JOSH_SYNC_ROOT="$(cd "$BATS_TEST_DIRNAME/../.." && pwd)"
JOSH_BIN="${JOSH_SYNC_ROOT}/bin/josh-sync"
FIXTURES="${JOSH_SYNC_ROOT}/tests/fixtures"
TEST_ROOT="$(mktemp -d)"
}
teardown() {
cd "$BATS_TEST_DIRNAME" 2>/dev/null || true
rm -rf "$TEST_ROOT"
}
# Drop the minimal fixture config into a clean cwd. Most cmd_* paths read
# .josh-sync.yml from the working directory.
seed_minimal_config() {
cp "${FIXTURES}/minimal.yml" "${TEST_ROOT}/.josh-sync.yml"
cd "$TEST_ROOT"
}
# ─── Global flags ───────────────────────────────────────────────────
@test "--version exits 0 and prints the version" {
run "$JOSH_BIN" --version
[ "$status" -eq 0 ]
[[ "$output" == *"josh-sync"* ]]
}
@test "--help exits 0 and advertises onboard, the adopt alias, and --mode" {
run "$JOSH_BIN" --help
[ "$status" -eq 0 ]
# Help text is printed to stderr via `cat >&2`, so combine with --separate.
run --separate-stderr "$JOSH_BIN" --help
[ "$status" -eq 0 ]
[[ "$stderr" == *"onboard <target>"* ]]
[[ "$stderr" == *"adopt <target>"* ]]
[[ "$stderr" == *"Alias for 'onboard --mode=adopt'"* ]]
[[ "$stderr" == *"--mode={reset,adopt}"* ]]
}
# ─── onboard flag parsing & dispatch ────────────────────────────────
@test "onboard with no target exits non-zero and prints usage including --mode" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" onboard
[ "$status" -ne 0 ]
[[ "$stderr" == *"Usage: josh-sync onboard"* ]]
[[ "$stderr" == *"--mode=reset|adopt"* ]]
}
@test "onboard --mode=invalid is rejected with a clear error" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" onboard --mode=invalid example
[ "$status" -ne 0 ]
[[ "$stderr" == *"Invalid --mode"* ]]
}
@test "onboard --mode=adopt against an unknown target reports target-not-found" {
seed_minimal_config
# Proves --mode parses correctly: parse_config succeeds, then cmd_onboard
# fails at target lookup, before any git/network activity.
run --separate-stderr "$JOSH_BIN" onboard --mode=adopt nonexistent
[ "$status" -ne 0 ]
[[ "$stderr" == *"not found"* ]]
}
# ─── adopt alias ────────────────────────────────────────────────────
@test "adopt alias forwards to onboard --mode=adopt (visible via alias log line + target lookup)" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" adopt nonexistent
[ "$status" -ne 0 ]
# Alias notice from cmd_adopt:
[[ "$stderr" == *"alias for: josh-sync onboard --mode=adopt"* ]]
# And the forwarded call lands in cmd_onboard's target lookup:
[[ "$stderr" == *"not found"* ]]
}
@test "onboard usage listing shows --restart and --mode flags together" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" onboard
[ "$status" -ne 0 ]
[[ "$stderr" == *"--restart"* ]]
[[ "$stderr" == *"--mode"* ]]
}
# ─── --mode value-parsing guards ────────────────────────────────────
@test "onboard --mode (no value) fails with a helpful message instead of crashing on unbound \$2" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" onboard example --mode
[ "$status" -ne 0 ]
[[ "$stderr" == *"--mode requires a value"* ]]
}
@test "onboard --mode= (empty after equals) is rejected explicitly, not silently ignored" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" onboard example --mode=
[ "$status" -ne 0 ]
[[ "$stderr" == *"Empty --mode="* ]]
}
@test "adopt alias dies when a conflicting --mode=reset is also passed (instead of silently honouring reset)" {
seed_minimal_config
run --separate-stderr "$JOSH_BIN" adopt example --mode=reset
[ "$status" -ne 0 ]
[[ "$stderr" == *"alias for --mode=adopt"* ]]
[[ "$stderr" == *"conflicting"* ]]
}