#!/usr/bin/env bats setup_file() { PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)" export PROJECT_ROOT ORIGINAL_HOME="${HOME:-}" export ORIGINAL_HOME HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-clean-caches.XXXXXX")" export HOME mkdir -p "$HOME" mkdir -p "$HOME/.cache/mole" mkdir -p "$HOME/Library/Caches" mkdir -p "$HOME/Library/Logs" } teardown_file() { rm -rf "$HOME" if [[ -n "${ORIGINAL_HOME:-}" ]]; then export HOME="$ORIGINAL_HOME" fi } setup() { source "$PROJECT_ROOT/lib/core/common.sh" source "$PROJECT_ROOT/lib/clean/caches.sh" # Mock run_with_timeout to skip timeout overhead in tests # shellcheck disable=SC2329 run_with_timeout() { shift # Remove timeout argument "$@" } export -f run_with_timeout rm -f "$HOME/.cache/mole/permissions_granted" } @test "check_tcc_permissions skips in non-interactive mode" { run bash -c "source '$PROJECT_ROOT/lib/core/common.sh'; source '$PROJECT_ROOT/lib/clean/caches.sh'; check_tcc_permissions" < /dev/null [ "$status" -eq 0 ] [[ ! -f "$HOME/.cache/mole/permissions_granted" ]] } @test "check_tcc_permissions skips when permissions already granted" { mkdir -p "$HOME/.cache/mole" touch "$HOME/.cache/mole/permissions_granted" run bash -c "source '$PROJECT_ROOT/lib/core/common.sh'; source '$PROJECT_ROOT/lib/clean/caches.sh'; [[ -t 1 ]] || true; check_tcc_permissions" [ "$status" -eq 0 ] } @test "check_tcc_permissions validates protected directories" { [[ -d "$HOME/Library/Caches" ]] [[ -d "$HOME/Library/Logs" ]] [[ -d "$HOME/.cache/mole" ]] run bash -c "source '$PROJECT_ROOT/lib/core/common.sh'; source '$PROJECT_ROOT/lib/clean/caches.sh'; check_tcc_permissions < /dev/null" [ "$status" -eq 0 ] } @test "clean_service_worker_cache returns early when path doesn't exist" { run bash -c "source '$PROJECT_ROOT/lib/core/common.sh'; source '$PROJECT_ROOT/lib/clean/caches.sh'; clean_service_worker_cache 'TestBrowser' '/nonexistent/path'" [ "$status" -eq 0 ] } @test "clean_service_worker_cache handles empty cache directory" { local test_cache="$HOME/test_sw_cache" mkdir -p "$test_cache" run bash -c " run_with_timeout() { shift; \"\$@\"; } export -f run_with_timeout source '$PROJECT_ROOT/lib/core/common.sh' source '$PROJECT_ROOT/lib/clean/caches.sh' clean_service_worker_cache 'TestBrowser' '$test_cache' " [ "$status" -eq 0 ] rm -rf "$test_cache" } @test "clean_service_worker_cache protects specified domains" { local test_cache="$HOME/test_sw_cache" mkdir -p "$test_cache/abc123_https_capcut.com_0" mkdir -p "$test_cache/def456_https_example.com_0" run bash -c " run_with_timeout() { local timeout=\"\$1\" shift if [[ \"\$1\" == \"get_path_size_kb\" ]]; then echo 0 return 0 fi if [[ \"\$1\" == \"sh\" ]]; then printf '%s\n' \ '$test_cache/abc123_https_capcut.com_0' \ '$test_cache/def456_https_example.com_0' return 0 fi \"\$@\" } export -f run_with_timeout export DRY_RUN=true export PROTECTED_SW_DOMAINS=(capcut.com photopea.com) source '$PROJECT_ROOT/lib/core/common.sh' source '$PROJECT_ROOT/lib/clean/caches.sh' clean_service_worker_cache 'TestBrowser' '$test_cache' " [ "$status" -eq 0 ] [[ -d "$test_cache/abc123_https_capcut.com_0" ]] rm -rf "$test_cache" } @test "clean_project_caches completes without errors" { mkdir -p "$HOME/Projects/test-app/.next/cache" mkdir -p "$HOME/Projects/python-app/__pycache__" touch "$HOME/Projects/test-app/package.json" touch "$HOME/Projects/python-app/pyproject.toml" touch "$HOME/Projects/test-app/.next/cache/test.cache" touch "$HOME/Projects/python-app/__pycache__/module.pyc" run bash -c " export DRY_RUN=true source '$PROJECT_ROOT/lib/core/common.sh' source '$PROJECT_ROOT/lib/clean/caches.sh' clean_project_caches " [ "$status" -eq 0 ] rm -rf "$HOME/Projects" } @test "clean_project_caches scans configured roots instead of HOME" { mkdir -p "$HOME/.config/mole" mkdir -p "$HOME/CustomProjects/app/.next/cache" touch "$HOME/CustomProjects/app/package.json" local fake_bin fake_bin="$(mktemp -d "$HOME/find-bin.XXXXXX")" local find_log="$HOME/find.log" cat > "$fake_bin/find" <> "$find_log" root="" prev="" for arg in "\$@"; do if [[ "\$prev" == "-P" ]]; then root="\$arg" break fi prev="\$arg" done if [[ "\$root" == "$HOME/CustomProjects" ]]; then printf '%s\n' "$HOME/CustomProjects/app/.next" fi EOF chmod +x "$fake_bin/find" run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" PATH="$fake_bin:$PATH" bash --noprofile --norc <<'EOF' set -euo pipefail printf '%s\n' "$HOME/CustomProjects" > "$HOME/.config/mole/purge_paths" source "$PROJECT_ROOT/lib/core/common.sh" source "$PROJECT_ROOT/lib/clean/caches.sh" run_with_timeout() { shift; "$@"; } safe_clean() { echo "$2|$1"; } clean_project_caches EOF [ "$status" -eq 0 ] [[ "$output" == *"Next.js build cache"* ]] grep -q -- "-P $HOME/CustomProjects " "$find_log" ! grep -q -- "-P $HOME " "$find_log" rm -rf "$HOME/CustomProjects" "$HOME/.config/mole" "$fake_bin" "$find_log" } @test "clean_project_caches auto-detects top-level project containers" { mkdir -p "$HOME/go/src/demo/.next/cache" touch "$HOME/go/src/demo/go.mod" touch "$HOME/go/src/demo/.next/cache/test.cache" run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF' set -euo pipefail source "$PROJECT_ROOT/lib/core/common.sh" source "$PROJECT_ROOT/lib/clean/caches.sh" safe_clean() { echo "$2|$1"; } clean_project_caches EOF [ "$status" -eq 0 ] [[ "$output" == *"Next.js build cache|$HOME/go/src/demo/.next/cache/test.cache"* ]] rm -rf "$HOME/go" } @test "clean_project_caches auto-detects nested GOPATH-style project containers" { mkdir -p "$HOME/go/src/github.com/example/demo/.next/cache" touch "$HOME/go/src/github.com/example/demo/go.mod" touch "$HOME/go/src/github.com/example/demo/.next/cache/test.cache" run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF' set -euo pipefail source "$PROJECT_ROOT/lib/core/common.sh" source "$PROJECT_ROOT/lib/clean/caches.sh" safe_clean() { echo "$2|$1"; } clean_project_caches EOF [ "$status" -eq 0 ] [[ "$output" == *"Next.js build cache|$HOME/go/src/github.com/example/demo/.next/cache/test.cache"* ]] rm -rf "$HOME/go" } @test "clean_project_caches skips stalled root scans" { mkdir -p "$HOME/.config/mole" mkdir -p "$HOME/SlowProjects/app" printf '%s\n' "$HOME/SlowProjects" > "$HOME/.config/mole/purge_paths" local fake_bin fake_bin="$(mktemp -d "$HOME/find-timeout.XXXXXX")" cat > "$fake_bin/find" <