From ba99c00ec93ab21d9fa14d1d6eb38a00a91b325a Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:41:08 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Add=20gener?= =?UTF-8?q?ated=20unit=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/cleanup-old-version-managers.bats | 229 ++++++++++++++++++++++++ tests/dfm.bats | 37 +++- tests/install-python-packages.bats | 157 ++++++++++++++++ 3 files changed, 415 insertions(+), 8 deletions(-) create mode 100644 tests/cleanup-old-version-managers.bats mode change 100755 => 100644 tests/dfm.bats create mode 100644 tests/install-python-packages.bats diff --git a/tests/cleanup-old-version-managers.bats b/tests/cleanup-old-version-managers.bats new file mode 100644 index 0000000..a43b83a --- /dev/null +++ b/tests/cleanup-old-version-managers.bats @@ -0,0 +1,229 @@ +#!/usr/bin/env bats + +setup() +{ + export DOTFILES="$PWD" + # Pre-set CURRENT_SHELL so config/shared.sh's x-path-prepend works + # even in environments where `ps` is unavailable. + export CURRENT_SHELL="bash" + # Use a temporary directory to isolate all XDG data operations + export XDG_DATA_HOME="$BATS_TMPDIR/share" + export XDG_BIN_HOME="$BATS_TMPDIR/bin" + export XDG_CONFIG_HOME="$BATS_TMPDIR/config" + export XDG_CACHE_HOME="$BATS_TMPDIR/cache" + export XDG_STATE_HOME="$BATS_TMPDIR/state" + mkdir -p "$XDG_DATA_HOME" + mkdir -p "$XDG_BIN_HOME" +} + +teardown() +{ + rm -rf "$BATS_TMPDIR/share" "$BATS_TMPDIR/bin" \ + "$BATS_TMPDIR/config" "$BATS_TMPDIR/cache" "$BATS_TMPDIR/state" +} + +# ── Group 1: Argument validation ────────────────────────────────────── + +@test "cleanup script rejects unknown arguments" { + run bash scripts/cleanup-old-version-managers.sh --unknown-flag + [ "$status" -eq 1 ] + [[ "$output" == *"Usage:"* ]] +} + +@test "cleanup script rejects positional argument" { + run bash scripts/cleanup-old-version-managers.sh some-arg + [ "$status" -eq 1 ] + [[ "$output" == *"Usage:"* ]] +} + +@test "cleanup script accepts --dry-run flag" { + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] +} + +@test "cleanup script runs successfully with no arguments" { + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] +} + +# ── Group 2: Dry-run does not remove directories ─────────────────────── + +@test "dry-run does not remove nvm data directory" { + mkdir -p "$XDG_DATA_HOME/nvm" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [ -d "$XDG_DATA_HOME/nvm" ] +} + +@test "dry-run does not remove fnm data directory" { + mkdir -p "$XDG_DATA_HOME/fnm" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [ -d "$XDG_DATA_HOME/fnm" ] +} + +@test "dry-run does not remove pyenv data directory" { + mkdir -p "$XDG_DATA_HOME/pyenv" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [ -d "$XDG_DATA_HOME/pyenv" ] +} + +@test "dry-run does not remove goenv data directory" { + mkdir -p "$XDG_DATA_HOME/goenv" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [ -d "$XDG_DATA_HOME/goenv" ] +} + +@test "dry-run does not remove bob-nvim data directory" { + mkdir -p "$XDG_DATA_HOME/bob" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [ -d "$XDG_DATA_HOME/bob" ] +} + +@test "dry-run output mentions DRY RUN for each existing directory" { + mkdir -p "$XDG_DATA_HOME/nvm" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [[ "$output" == *"DRY RUN"* ]] +} + +# ── Group 3: Dry-run does not remove files ───────────────────────────── + +@test "dry-run does not remove cargo-installed tool binaries" { + mkdir -p "$XDG_DATA_HOME/cargo/bin" + touch "$XDG_DATA_HOME/cargo/bin/bkt" + touch "$XDG_DATA_HOME/cargo/bin/eza" + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [ -f "$XDG_DATA_HOME/cargo/bin/bkt" ] + [ -f "$XDG_DATA_HOME/cargo/bin/eza" ] +} + +# ── Group 4: Live run removes directories ────────────────────────────── + +@test "live run removes nvm data directory when it exists" { + mkdir -p "$XDG_DATA_HOME/nvm" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -d "$XDG_DATA_HOME/nvm" ] +} + +@test "live run removes fnm data directory when it exists" { + mkdir -p "$XDG_DATA_HOME/fnm" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -d "$XDG_DATA_HOME/fnm" ] +} + +@test "live run removes pyenv data directory when it exists" { + mkdir -p "$XDG_DATA_HOME/pyenv" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -d "$XDG_DATA_HOME/pyenv" ] +} + +@test "live run removes goenv data directory when it exists" { + mkdir -p "$XDG_DATA_HOME/goenv" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -d "$XDG_DATA_HOME/goenv" ] +} + +@test "live run removes bob-nvim data directory when it exists" { + mkdir -p "$XDG_DATA_HOME/bob" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -d "$XDG_DATA_HOME/bob" ] +} + +@test "live run removes all version manager directories in one pass" { + mkdir -p "$XDG_DATA_HOME/nvm" + mkdir -p "$XDG_DATA_HOME/fnm" + mkdir -p "$XDG_DATA_HOME/pyenv" + mkdir -p "$XDG_DATA_HOME/goenv" + mkdir -p "$XDG_DATA_HOME/bob" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -d "$XDG_DATA_HOME/nvm" ] + [ ! -d "$XDG_DATA_HOME/fnm" ] + [ ! -d "$XDG_DATA_HOME/pyenv" ] + [ ! -d "$XDG_DATA_HOME/goenv" ] + [ ! -d "$XDG_DATA_HOME/bob" ] +} + +# ── Group 5: Live run removes cargo-installed files ──────────────────── + +@test "live run removes cargo-installed bkt binary" { + mkdir -p "$XDG_DATA_HOME/cargo/bin" + touch "$XDG_DATA_HOME/cargo/bin/bkt" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -f "$XDG_DATA_HOME/cargo/bin/bkt" ] +} + +@test "live run removes cargo-installed eza binary" { + mkdir -p "$XDG_DATA_HOME/cargo/bin" + touch "$XDG_DATA_HOME/cargo/bin/eza" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -f "$XDG_DATA_HOME/cargo/bin/eza" ] +} + +@test "live run removes cargo-installed rg binary" { + mkdir -p "$XDG_DATA_HOME/cargo/bin" + touch "$XDG_DATA_HOME/cargo/bin/rg" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -f "$XDG_DATA_HOME/cargo/bin/rg" ] +} + +@test "live run is idempotent when directories do not exist" { + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] +} + +# ── Group 6: Go bin skipped when equal to XDG_BIN_HOME ──────────────── + +@test "go binaries are not removed when GO_BIN equals XDG_BIN_HOME" { + # When $XDG_DATA_HOME/go/bin == $XDG_BIN_HOME the script skips removal + export XDG_BIN_HOME="$XDG_DATA_HOME/go/bin" + mkdir -p "$XDG_DATA_HOME/go/bin" + touch "$XDG_DATA_HOME/go/bin/fzf" + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ -f "$XDG_DATA_HOME/go/bin/fzf" ] +} + +@test "go binaries are removed when GO_BIN differs from XDG_BIN_HOME" { + mkdir -p "$XDG_DATA_HOME/go/bin" + touch "$XDG_DATA_HOME/go/bin/fzf" + # XDG_BIN_HOME is $BATS_TMPDIR/bin which differs from $XDG_DATA_HOME/go/bin + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [ ! -f "$XDG_DATA_HOME/go/bin/fzf" ] +} + +# ── Group 7: Output messages ─────────────────────────────────────────── + +@test "cleanup script prints completion message on success" { + run bash scripts/cleanup-old-version-managers.sh + [ "$status" -eq 0 ] + [[ "$output" == *"Cleanup complete"* ]] +} + +@test "dry-run prints completion message on success" { + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [[ "$output" == *"Cleanup complete"* ]] +} + +@test "cleanup script notes Mason binaries will not be touched" { + run bash scripts/cleanup-old-version-managers.sh --dry-run + [ "$status" -eq 0 ] + [[ "$output" == *"Mason"* ]] +} \ No newline at end of file diff --git a/tests/dfm.bats b/tests/dfm.bats old mode 100755 new mode 100644 index d6c2724..327eaf2 --- a/tests/dfm.bats +++ b/tests/dfm.bats @@ -38,25 +38,38 @@ setup() [ "$status" -eq 0 ] [[ "$output" == *"all"* ]] [[ "$output" == *"apt-packages"* ]] - [[ "$output" == *"cargo"* ]] [[ "$output" == *"cheat-databases"* ]] [[ "$output" == *"composer"* ]] [[ "$output" == *"dnf-packages"* ]] [[ "$output" == *"fonts"* ]] [[ "$output" == *"gh"* ]] [[ "$output" == *"git-crypt"* ]] - [[ "$output" == *"go"* ]] [[ "$output" == *"imagick"* ]] [[ "$output" == *"macos"* ]] - [[ "$output" == *"npm-packages"* ]] + [[ "$output" == *"mise"* ]] + [[ "$output" == *"mise-cleanup"* ]] [[ "$output" == *"ntfy"* ]] - [[ "$output" == *"nvm-latest"* ]] - [[ "$output" == *"nvm"* ]] - [[ "$output" == *"python-packages"* ]] + [[ "$output" == *"python-libs"* ]] [[ "$output" == *"xcode-cli-tools"* ]] [[ "$output" == *"z"* ]] } +@test "dfm install menu does not show removed nvm/cargo/go entries" { + run bash local/bin/dfm install + [ "$status" -eq 0 ] + [[ "$output" != *"nvm-latest"* ]] + [[ "$output" != *"npm-packages"* ]] + [[ "$output" != *"python-packages"* ]] +} + +@test "dfm install menu shows mise entry with description" { + run bash local/bin/dfm install + [ "$status" -eq 0 ] + [[ "$output" == *"mise"* ]] + [[ "$output" == *"mise-cleanup"* ]] + [[ "$output" == *"python-libs"* ]] +} + @test "dfm install with invalid subcommand shows menu" { run bash local/bin/dfm install nonexistent [ "$status" -eq 0 ] @@ -101,9 +114,17 @@ setup() @test "dfm scripts menu lists install scripts" { run bash local/bin/dfm scripts [ "$status" -eq 0 ] - [[ "$output" == *"cargo-packages"* ]] [[ "$output" == *"fonts"* ]] [[ "$output" == *"z"* ]] + [[ "$output" == *"python-packages"* ]] +} + +@test "dfm scripts menu does not list removed cargo and go scripts" { + run bash local/bin/dfm scripts + [ "$status" -eq 0 ] + [[ "$output" != *"cargo-packages"* ]] + [[ "$output" != *"go-packages"* ]] + [[ "$output" != *"npm-packages"* ]] } @test "dfm tests menu shows entries" { @@ -142,4 +163,4 @@ setup() @test "dfm check host with non-matching value exits 1" { run bash local/bin/dfm check host fakehostname [ "$status" -eq 1 ] -} +} \ No newline at end of file diff --git a/tests/install-python-packages.bats b/tests/install-python-packages.bats new file mode 100644 index 0000000..f045bf6 --- /dev/null +++ b/tests/install-python-packages.bats @@ -0,0 +1,157 @@ +#!/usr/bin/env bats + +setup() +{ + export DOTFILES="$PWD" + # Pre-set CURRENT_SHELL so config/shared.sh's x-path-prepend works + # even in environments where `ps` is unavailable. + export CURRENT_SHELL="bash" + export XDG_DATA_HOME="$BATS_TMPDIR/share" + export XDG_BIN_HOME="$BATS_TMPDIR/bin" + export XDG_CONFIG_HOME="$BATS_TMPDIR/config" + export XDG_CACHE_HOME="$BATS_TMPDIR/cache" + export XDG_STATE_HOME="$BATS_TMPDIR/state" + mkdir -p "$XDG_DATA_HOME" "$XDG_BIN_HOME" + + # Fake bin directory for mock commands + export FAKE_BIN="$BATS_TMPDIR/fake-bin" + mkdir -p "$FAKE_BIN" +} + +teardown() +{ + rm -rf "$BATS_TMPDIR/share" "$BATS_TMPDIR/bin" "$BATS_TMPDIR/fake-bin" \ + "$BATS_TMPDIR/config" "$BATS_TMPDIR/cache" "$BATS_TMPDIR/state" +} + +# ── Group 1: uv availability check ──────────────────────────────────── + +@test "script exits 1 when uv is not found" { + # Run with a PATH that does not contain uv + run env PATH="$FAKE_BIN:/usr/bin:/bin" bash scripts/install-python-packages.sh + [ "$status" -eq 1 ] +} + +@test "script prints error message when uv is not found" { + run env PATH="$FAKE_BIN:/usr/bin:/bin" bash scripts/install-python-packages.sh + [ "$status" -eq 1 ] + [[ "$output" == *"uv not found"* ]] +} + +@test "error message directs user to install uv via mise" { + run env PATH="$FAKE_BIN:/usr/bin:/bin" bash scripts/install-python-packages.sh + [ "$status" -eq 1 ] + [[ "$output" == *"mise"* ]] +} + +# ── Group 2: Successful library installation ─────────────────────────── + +@test "script exits 0 when uv is available and installs succeed" { + # Create a mock uv that succeeds for all invocations + cat > "$FAKE_BIN/uv" <<'EOF' +#!/usr/bin/env bash +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] +} + +@test "script calls uv pip install for libtmux" { + local calls_log="$BATS_TMPDIR/uv-calls.log" + cat > "$FAKE_BIN/uv" <> "$calls_log" +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] + grep -q "libtmux" "$calls_log" +} + +@test "script calls uv pip install for pynvim" { + local calls_log="$BATS_TMPDIR/uv-calls.log" + cat > "$FAKE_BIN/uv" <> "$calls_log" +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] + grep -q "pynvim" "$calls_log" +} + +@test "script uses --system flag with uv pip install" { + local calls_log="$BATS_TMPDIR/uv-calls.log" + cat > "$FAKE_BIN/uv" <> "$calls_log" +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] + grep -q -- "--system" "$calls_log" +} + +@test "script uses --upgrade flag with uv pip install" { + local calls_log="$BATS_TMPDIR/uv-calls.log" + cat > "$FAKE_BIN/uv" <> "$calls_log" +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] + grep -q -- "--upgrade" "$calls_log" +} + +@test "script prints success message when all libraries are installed" { + cat > "$FAKE_BIN/uv" <<'EOF' +#!/usr/bin/env bash +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] + [[ "$output" == *"complete"* ]] +} + +# ── Group 3: Failure propagation ────────────────────────────────────── + +@test "script exits non-zero when uv pip install fails" { + cat > "$FAKE_BIN/uv" <<'EOF' +#!/usr/bin/env bash +exit 1 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -ne 0 ] +} + +@test "script does not install tools via uv tool install" { + # This PR removed tool installation; only library (pip) installs remain. + local calls_log="$BATS_TMPDIR/uv-calls.log" + cat > "$FAKE_BIN/uv" <> "$calls_log" +exit 0 +EOF + chmod +x "$FAKE_BIN/uv" + + run env PATH="$FAKE_BIN:$PATH" bash scripts/install-python-packages.sh + [ "$status" -eq 0 ] + # "uv tool install" should NOT appear in calls + run grep "tool install" "$calls_log" + [ "$status" -ne 0 ] +} \ No newline at end of file