1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-11 08:19:18 +00:00

feat: Add browser version cleanup tests, enhance shell completion with new tests, and introduce core command definitions.

This commit is contained in:
Tw93
2026-01-02 09:55:42 +08:00
parent 9a055ece6c
commit 88f434f01a
6 changed files with 692 additions and 77 deletions

View File

@@ -0,0 +1,289 @@
#!/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-browser-cleanup.XXXXXX")"
export HOME
mkdir -p "$HOME"
}
teardown_file() {
rm -rf "$HOME"
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
export HOME="$ORIGINAL_HOME"
fi
}
@test "clean_chrome_old_versions skips when Chrome is running" {
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/user.sh"
# Mock pgrep to simulate Chrome running
pgrep() { return 0; }
export -f pgrep
clean_chrome_old_versions
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"Google Chrome running"* ]]
[[ "$output" == *"old versions cleanup skipped"* ]]
}
@test "clean_chrome_old_versions removes old versions but keeps current" {
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=true bash --noprofile --norc <<'EOF'
set -euo pipefail
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
# Mock pgrep to simulate Chrome not running
pgrep() { return 1; }
export -f pgrep
# Create mock Chrome directory structure
CHROME_APP="$HOME/Applications/Google Chrome.app"
VERSIONS_DIR="$CHROME_APP/Contents/Frameworks/Google Chrome Framework.framework/Versions"
mkdir -p "$VERSIONS_DIR"/{128.0.0.0,129.0.0.0,130.0.0.0}
# Create Current symlink pointing to 130.0.0.0
ln -s "130.0.0.0" "$VERSIONS_DIR/Current"
# Mock functions
is_path_whitelisted() { return 1; }
get_path_size_kb() { echo "10240"; }
bytes_to_human() { echo "10M"; }
note_activity() { :; }
export -f is_path_whitelisted get_path_size_kb bytes_to_human note_activity
# Initialize counters
files_cleaned=0
total_size_cleaned=0
total_items=0
clean_chrome_old_versions
# Verify output mentions old versions cleanup
echo "Cleaned: $files_cleaned items"
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"Chrome old versions"* ]]
[[ "$output" == *"dry"* ]]
[[ "$output" == *"Cleaned: 2 items"* ]]
}
@test "clean_chrome_old_versions respects whitelist" {
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=true bash --noprofile --norc <<'EOF'
set -euo pipefail
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
# Mock pgrep to simulate Chrome not running
pgrep() { return 1; }
export -f pgrep
# Create mock Chrome directory structure
CHROME_APP="$HOME/Applications/Google Chrome.app"
VERSIONS_DIR="$CHROME_APP/Contents/Frameworks/Google Chrome Framework.framework/Versions"
mkdir -p "$VERSIONS_DIR"/{128.0.0.0,129.0.0.0,130.0.0.0}
# Create Current symlink pointing to 130.0.0.0
ln -s "130.0.0.0" "$VERSIONS_DIR/Current"
# Mock is_path_whitelisted to protect version 128.0.0.0
is_path_whitelisted() {
[[ "$1" == *"128.0.0.0"* ]] && return 0
return 1
}
get_path_size_kb() { echo "10240"; }
bytes_to_human() { echo "10M"; }
note_activity() { :; }
export -f is_path_whitelisted get_path_size_kb bytes_to_human note_activity
# Initialize counters
files_cleaned=0
total_size_cleaned=0
total_items=0
clean_chrome_old_versions
# Should only clean 129.0.0.0 (not 128.0.0.0 which is whitelisted)
echo "Cleaned: $files_cleaned items"
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"Cleaned: 1 items"* ]]
}
@test "clean_chrome_old_versions DRY_RUN mode does not delete files" {
# Create test directory
CHROME_APP="$HOME/Applications/Google Chrome.app"
VERSIONS_DIR="$CHROME_APP/Contents/Frameworks/Google Chrome Framework.framework/Versions"
mkdir -p "$VERSIONS_DIR"/{128.0.0.0,130.0.0.0}
# Remove Current if it exists as a directory, then create symlink
rm -rf "$VERSIONS_DIR/Current"
ln -s "130.0.0.0" "$VERSIONS_DIR/Current"
# Create a marker file in old version
touch "$VERSIONS_DIR/128.0.0.0/marker.txt"
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=true bash --noprofile --norc <<'EOF'
set -euo pipefail
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
pgrep() { return 1; }
is_path_whitelisted() { return 1; }
get_path_size_kb() { echo "10240"; }
bytes_to_human() { echo "10M"; }
note_activity() { :; }
export -f pgrep is_path_whitelisted get_path_size_kb bytes_to_human note_activity
files_cleaned=0
total_size_cleaned=0
total_items=0
clean_chrome_old_versions
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"dry"* ]]
# Verify marker file still exists (not deleted in dry run)
[ -f "$VERSIONS_DIR/128.0.0.0/marker.txt" ]
}
@test "clean_chrome_old_versions handles missing Current symlink gracefully" {
# Use a fresh temp directory for this test
TEST_HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-test5.XXXXXX")"
run env HOME="$TEST_HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
set -euo pipefail
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
pgrep() { return 1; }
is_path_whitelisted() { return 1; }
get_path_size_kb() { echo "10240"; }
bytes_to_human() { echo "10M"; }
note_activity() { :; }
export -f pgrep is_path_whitelisted get_path_size_kb bytes_to_human note_activity
# Initialize counters to prevent unbound variable errors
files_cleaned=0
total_size_cleaned=0
total_items=0
# Create Chrome app without Current symlink
CHROME_APP="$HOME/Applications/Google Chrome.app"
VERSIONS_DIR="$CHROME_APP/Contents/Frameworks/Google Chrome Framework.framework/Versions"
mkdir -p "$VERSIONS_DIR"/{128.0.0.0,129.0.0.0}
# No Current symlink created
clean_chrome_old_versions
EOF
rm -rf "$TEST_HOME"
[ "$status" -eq 0 ]
# Should exit gracefully with no output
}
@test "clean_edge_old_versions skips when Edge is running" {
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/user.sh"
# Mock pgrep to simulate Edge running
pgrep() { return 0; }
export -f pgrep
clean_edge_old_versions
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"Microsoft Edge running"* ]]
[[ "$output" == *"old versions cleanup skipped"* ]]
}
@test "clean_edge_old_versions removes old versions but keeps current" {
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=true bash --noprofile --norc <<'EOF'
set -euo pipefail
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
pgrep() { return 1; }
export -f pgrep
# Create mock Edge directory structure
EDGE_APP="$HOME/Applications/Microsoft Edge.app"
VERSIONS_DIR="$EDGE_APP/Contents/Frameworks/Microsoft Edge Framework.framework/Versions"
mkdir -p "$VERSIONS_DIR"/{120.0.0.0,121.0.0.0,122.0.0.0}
# Create Current symlink pointing to 122.0.0.0
ln -s "122.0.0.0" "$VERSIONS_DIR/Current"
is_path_whitelisted() { return 1; }
get_path_size_kb() { echo "10240"; }
bytes_to_human() { echo "10M"; }
note_activity() { :; }
export -f is_path_whitelisted get_path_size_kb bytes_to_human note_activity
files_cleaned=0
total_size_cleaned=0
total_items=0
clean_edge_old_versions
echo "Cleaned: $files_cleaned items"
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"Edge old versions"* ]]
[[ "$output" == *"dry"* ]]
[[ "$output" == *"Cleaned: 2 items"* ]]
}
@test "clean_edge_old_versions handles no old versions gracefully" {
# Use a fresh temp directory for this test
TEST_HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-test8.XXXXXX")"
run env HOME="$TEST_HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
set -euo pipefail
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
pgrep() { return 1; }
is_path_whitelisted() { return 1; }
get_path_size_kb() { echo "10240"; }
bytes_to_human() { echo "10M"; }
note_activity() { :; }
export -f pgrep is_path_whitelisted get_path_size_kb bytes_to_human note_activity
# Initialize counters
files_cleaned=0
total_size_cleaned=0
total_items=0
# Create Edge with only current version
EDGE_APP="$HOME/Applications/Microsoft Edge.app"
VERSIONS_DIR="$EDGE_APP/Contents/Frameworks/Microsoft Edge Framework.framework/Versions"
mkdir -p "$VERSIONS_DIR/122.0.0.0"
ln -s "122.0.0.0" "$VERSIONS_DIR/Current"
clean_edge_old_versions
EOF
rm -rf "$TEST_HOME"
[ "$status" -eq 0 ]
# Should exit gracefully with no cleanup output
[[ "$output" != *"Edge old versions"* ]]
}

157
tests/completion.bats Executable file
View File

@@ -0,0 +1,157 @@
#!/usr/bin/env bats
setup_file() {
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
export PROJECT_ROOT
ORIGINAL_HOME="${HOME:-}"
export ORIGINAL_HOME
ORIGINAL_PATH="${PATH:-}"
export ORIGINAL_PATH
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-completion-home.XXXXXX")"
export HOME
mkdir -p "$HOME"
PATH="$PROJECT_ROOT:$PATH"
export PATH
}
teardown_file() {
rm -rf "$HOME"
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
export HOME="$ORIGINAL_HOME"
fi
if [[ -n "${ORIGINAL_PATH:-}" ]]; then
export PATH="$ORIGINAL_PATH"
fi
}
setup() {
rm -rf "$HOME/.config"
rm -rf "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile"
mkdir -p "$HOME"
}
@test "completion script exists and is executable" {
[ -f "$PROJECT_ROOT/bin/completion.sh" ]
[ -x "$PROJECT_ROOT/bin/completion.sh" ]
}
@test "completion script has valid bash syntax" {
run bash -n "$PROJECT_ROOT/bin/completion.sh"
[ "$status" -eq 0 ]
}
@test "completion --help shows usage" {
run "$PROJECT_ROOT/bin/completion.sh" --help
[ "$status" -ne 0 ]
[[ "$output" == *"Usage: mole completion"* ]]
[[ "$output" == *"Auto-install"* ]]
}
@test "completion bash generates valid bash script" {
run "$PROJECT_ROOT/bin/completion.sh" bash
[ "$status" -eq 0 ]
[[ "$output" == *"_mole_completions"* ]]
[[ "$output" == *"complete -F _mole_completions mole mo"* ]]
}
@test "completion bash script includes all commands" {
run "$PROJECT_ROOT/bin/completion.sh" bash
[ "$status" -eq 0 ]
[[ "$output" == *"optimize"* ]]
[[ "$output" == *"clean"* ]]
[[ "$output" == *"uninstall"* ]]
[[ "$output" == *"analyze"* ]]
[[ "$output" == *"status"* ]]
[[ "$output" == *"purge"* ]]
[[ "$output" == *"touchid"* ]]
[[ "$output" == *"completion"* ]]
}
@test "completion bash script supports mo command" {
run "$PROJECT_ROOT/bin/completion.sh" bash
[ "$status" -eq 0 ]
[[ "$output" == *"complete -F _mole_completions mole mo"* ]]
}
@test "completion bash can be loaded in bash" {
run bash -c "eval \"\$(\"$PROJECT_ROOT/bin/completion.sh\" bash)\" && complete -p mole"
[ "$status" -eq 0 ]
[[ "$output" == *"_mole_completions"* ]]
}
@test "completion zsh generates valid zsh script" {
run "$PROJECT_ROOT/bin/completion.sh" zsh
[ "$status" -eq 0 ]
[[ "$output" == *"#compdef mole mo"* ]]
[[ "$output" == *"_mole()"* ]]
}
@test "completion zsh includes command descriptions" {
run "$PROJECT_ROOT/bin/completion.sh" zsh
[ "$status" -eq 0 ]
[[ "$output" == *"optimize:Free up disk space"* ]]
[[ "$output" == *"clean:Remove apps completely"* ]]
}
@test "completion fish generates valid fish script" {
run "$PROJECT_ROOT/bin/completion.sh" fish
[ "$status" -eq 0 ]
[[ "$output" == *"complete -c mole"* ]]
[[ "$output" == *"complete -c mo"* ]]
}
@test "completion fish includes both mole and mo commands" {
output="$("$PROJECT_ROOT/bin/completion.sh" fish)"
mole_count=$(echo "$output" | grep -c "complete -c mole")
mo_count=$(echo "$output" | grep -c "complete -c mo")
[ "$mole_count" -gt 0 ]
[ "$mo_count" -gt 0 ]
}
@test "completion auto-install detects zsh" {
export SHELL=/bin/zsh
# Simulate auto-install (no interaction)
run bash -c "echo 'y' | \"$PROJECT_ROOT/bin/completion.sh\""
if [[ "$output" == *"Already configured"* ]]; then
skip "Already configured from previous test"
fi
[ -f "$HOME/.zshrc" ] || skip "Auto-install didn't create .zshrc"
run grep -E "mole[[:space:]]+completion" "$HOME/.zshrc"
[ "$status" -eq 0 ]
}
@test "completion auto-install detects already installed" {
export SHELL=/bin/zsh
mkdir -p "$HOME"
echo 'eval "$(mole completion zsh)"' > "$HOME/.zshrc"
run "$PROJECT_ROOT/bin/completion.sh"
[ "$status" -eq 0 ]
[[ "$output" == *"updated"* ]]
}
@test "completion script handles invalid shell argument" {
run "$PROJECT_ROOT/bin/completion.sh" invalid-shell
[ "$status" -ne 0 ]
}
@test "completion subcommand supports bash/zsh/fish" {
run "$PROJECT_ROOT/bin/completion.sh" bash
[ "$status" -eq 0 ]
run "$PROJECT_ROOT/bin/completion.sh" zsh
[ "$status" -eq 0 ]
run "$PROJECT_ROOT/bin/completion.sh" fish
[ "$status" -eq 0 ]
}