mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 17:24:45 +00:00
- Replace parentheses with commas for supplementary info - Use commas instead of em-dashes for separators - Update bullet points from - to * in some contexts - Improve version extraction regex with fallback logic
456 lines
13 KiB
Bash
456 lines
13 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
setup_file() {
|
|
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
|
|
export PROJECT_ROOT
|
|
|
|
CURRENT_VERSION="$(grep '^VERSION=' "$PROJECT_ROOT/mole" | head -1 | sed 's/VERSION=\"\\(.*\\)\"/\\1/')"
|
|
export CURRENT_VERSION
|
|
|
|
ORIGINAL_HOME="${HOME:-}"
|
|
export ORIGINAL_HOME
|
|
|
|
HOME="$(mktemp -d "${BATS_TEST_DIRNAME}/tmp-update-manager.XXXXXX")"
|
|
export HOME
|
|
|
|
mkdir -p "${HOME}/.cache/mole"
|
|
}
|
|
|
|
teardown_file() {
|
|
rm -rf "$HOME"
|
|
if [[ -n "${ORIGINAL_HOME:-}" ]]; then
|
|
export HOME="$ORIGINAL_HOME"
|
|
fi
|
|
}
|
|
|
|
setup() {
|
|
BREW_OUTDATED_COUNT=0
|
|
BREW_FORMULA_OUTDATED_COUNT=0
|
|
BREW_CASK_OUTDATED_COUNT=0
|
|
APPSTORE_UPDATE_COUNT=0
|
|
MACOS_UPDATE_AVAILABLE=false
|
|
MOLE_UPDATE_AVAILABLE=false
|
|
|
|
export MOCK_BIN_DIR="$BATS_TMPDIR/mole-mocks-$$"
|
|
mkdir -p "$MOCK_BIN_DIR"
|
|
export PATH="$MOCK_BIN_DIR:$PATH"
|
|
}
|
|
|
|
teardown() {
|
|
rm -rf "$MOCK_BIN_DIR"
|
|
}
|
|
|
|
read_key() {
|
|
echo "ESC"
|
|
return 0
|
|
}
|
|
|
|
@test "ask_for_updates returns 1 when no updates available" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
source "$PROJECT_ROOT/lib/manage/update.sh"
|
|
BREW_OUTDATED_COUNT=0
|
|
APPSTORE_UPDATE_COUNT=0
|
|
MACOS_UPDATE_AVAILABLE=false
|
|
MOLE_UPDATE_AVAILABLE=false
|
|
ask_for_updates
|
|
EOF
|
|
|
|
[ "$status" -eq 1 ]
|
|
}
|
|
|
|
@test "ask_for_updates shows updates and waits for input" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
source "$PROJECT_ROOT/lib/manage/update.sh"
|
|
BREW_OUTDATED_COUNT=5
|
|
BREW_FORMULA_OUTDATED_COUNT=3
|
|
BREW_CASK_OUTDATED_COUNT=2
|
|
APPSTORE_UPDATE_COUNT=1
|
|
MACOS_UPDATE_AVAILABLE=true
|
|
MOLE_UPDATE_AVAILABLE=true
|
|
|
|
read_key() { echo "ESC"; return 0; }
|
|
|
|
ask_for_updates
|
|
EOF
|
|
|
|
[ "$status" -eq 1 ] # ESC cancels
|
|
[[ "$output" == *"Homebrew, 3 formula, 2 cask"* ]]
|
|
[[ "$output" == *"App Store, 1 apps"* ]]
|
|
[[ "$output" == *"macOS system"* ]]
|
|
[[ "$output" == *"Mole"* ]]
|
|
}
|
|
|
|
@test "ask_for_updates accepts Enter when updates exist" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
source "$PROJECT_ROOT/lib/manage/update.sh"
|
|
BREW_OUTDATED_COUNT=2
|
|
BREW_FORMULA_OUTDATED_COUNT=2
|
|
MOLE_UPDATE_AVAILABLE=true
|
|
read_key() { echo "ENTER"; return 0; }
|
|
ask_for_updates
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"AVAILABLE UPDATES"* ]]
|
|
[[ "$output" == *"yes"* ]]
|
|
}
|
|
|
|
@test "format_brew_update_label lists formula and cask counts" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
source "$PROJECT_ROOT/lib/manage/update.sh"
|
|
BREW_OUTDATED_COUNT=5
|
|
BREW_FORMULA_OUTDATED_COUNT=3
|
|
BREW_CASK_OUTDATED_COUNT=2
|
|
format_brew_update_label
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"3 formula"* ]]
|
|
[[ "$output" == *"2 cask"* ]]
|
|
}
|
|
|
|
@test "perform_updates handles Homebrew success and Mole update" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
source "$PROJECT_ROOT/lib/manage/update.sh"
|
|
|
|
BREW_FORMULA_OUTDATED_COUNT=1
|
|
BREW_CASK_OUTDATED_COUNT=0
|
|
MOLE_UPDATE_AVAILABLE=true
|
|
|
|
FAKE_DIR="$HOME/fake-script-dir"
|
|
mkdir -p "$FAKE_DIR/lib/manage"
|
|
cat > "$FAKE_DIR/mole" <<'SCRIPT'
|
|
#!/usr/bin/env bash
|
|
echo "Already on latest version"
|
|
SCRIPT
|
|
chmod +x "$FAKE_DIR/mole"
|
|
SCRIPT_DIR="$FAKE_DIR/lib/manage"
|
|
|
|
brew_has_outdated() { return 0; }
|
|
start_inline_spinner() { :; }
|
|
stop_inline_spinner() { :; }
|
|
reset_brew_cache() { echo "BREW_CACHE_RESET"; }
|
|
reset_mole_cache() { echo "MOLE_CACHE_RESET"; }
|
|
has_sudo_session() { return 1; }
|
|
ensure_sudo_session() { echo "ensure_sudo_session_called"; return 1; }
|
|
|
|
brew() {
|
|
if [[ "$1" == "upgrade" ]]; then
|
|
echo "Upgrading formula"
|
|
return 0
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
get_appstore_update_labels() { return 0; }
|
|
get_macos_update_labels() { return 0; }
|
|
|
|
perform_updates
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Updating Mole"* ]]
|
|
[[ "$output" == *"Mole updated"* ]]
|
|
[[ "$output" == *"MOLE_CACHE_RESET"* ]]
|
|
[[ "$output" == *"All updates completed"* ]]
|
|
}
|
|
|
|
@test "update_via_homebrew reports already on latest version" {
|
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc << 'EOF'
|
|
set -euo pipefail
|
|
MOLE_TEST_BREW_UPDATE_OUTPUT="Updated 0 formulae"
|
|
MOLE_TEST_BREW_UPGRADE_OUTPUT="Warning: mole 1.7.9 already installed"
|
|
MOLE_TEST_BREW_LIST_OUTPUT="mole 1.7.9"
|
|
start_inline_spinner() { :; }
|
|
stop_inline_spinner() { :; }
|
|
brew() {
|
|
case "$1" in
|
|
update) echo "$MOLE_TEST_BREW_UPDATE_OUTPUT";;
|
|
upgrade) echo "$MOLE_TEST_BREW_UPGRADE_OUTPUT";;
|
|
list) if [[ "$2" == "--versions" ]]; then echo "$MOLE_TEST_BREW_LIST_OUTPUT"; fi ;;
|
|
esac
|
|
}
|
|
export -f brew start_inline_spinner stop_inline_spinner
|
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
|
update_via_homebrew "1.7.9"
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Already on latest version"* ]]
|
|
}
|
|
|
|
@test "update_mole skips download when already latest" {
|
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" CURRENT_VERSION="$CURRENT_VERSION" PATH="$HOME/fake-bin:/usr/bin:/bin" TERM="dumb" bash --noprofile --norc << 'EOF'
|
|
set -euo pipefail
|
|
curl() {
|
|
local out=""
|
|
local url=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-o)
|
|
out="$2"
|
|
shift 2
|
|
;;
|
|
http*://*)
|
|
url="$1"
|
|
shift
|
|
;;
|
|
*)
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -n "$out" ]]; then
|
|
echo "Installer executed" > "$out"
|
|
return 0
|
|
fi
|
|
|
|
if [[ "$url" == *"api.github.com"* ]]; then
|
|
echo "{\"tag_name\":\"$CURRENT_VERSION\"}"
|
|
else
|
|
echo "VERSION=\"$CURRENT_VERSION\""
|
|
fi
|
|
}
|
|
export -f curl
|
|
|
|
brew() { exit 1; }
|
|
export -f brew
|
|
|
|
"$PROJECT_ROOT/mole" update
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Already on latest version"* ]]
|
|
}
|
|
|
|
@test "process_install_output shows install.sh success message with version" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
GREEN='\033[0;32m'
|
|
ICON_SUCCESS='✓'
|
|
NC='\033[0m'
|
|
|
|
process_install_output() {
|
|
local output="$1"
|
|
local fallback_version="$2"
|
|
|
|
local filtered_output
|
|
filtered_output=$(printf '%s\n' "$output" | sed '/^$/d')
|
|
if [[ -n "$filtered_output" ]]; then
|
|
printf '%s\n' "$filtered_output"
|
|
fi
|
|
|
|
if ! printf '%s\n' "$output" | grep -Eq "Updated to latest version|Already on latest version"; then
|
|
local new_version
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*-> \([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*version[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(command -v mo > /dev/null 2>&1 && mo --version 2> /dev/null | awk 'NR==1 && NF {print $NF}' || echo "")
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version="$fallback_version"
|
|
fi
|
|
printf '\n%s\n' "${GREEN}${ICON_SUCCESS}${NC} Updated to latest version, ${new_version:-unknown}"
|
|
fi
|
|
}
|
|
|
|
output="Installing Mole...
|
|
◎ Mole installed successfully, version 1.23.1"
|
|
process_install_output "$output" "1.23.0"
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Updated to latest version, 1.23.1"* ]]
|
|
[[ "$output" != *"1.23.0"* ]]
|
|
}
|
|
|
|
@test "process_install_output uses fallback version when install.sh has no success message" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
GREEN='\033[0;32m'
|
|
ICON_SUCCESS='✓'
|
|
NC='\033[0m'
|
|
|
|
process_install_output() {
|
|
local output="$1"
|
|
local fallback_version="$2"
|
|
|
|
local filtered_output
|
|
filtered_output=$(printf '%s\n' "$output" | sed '/^$/d')
|
|
if [[ -n "$filtered_output" ]]; then
|
|
printf '%s\n' "$filtered_output"
|
|
fi
|
|
|
|
if ! printf '%s\n' "$output" | grep -Eq "Updated to latest version|Already on latest version"; then
|
|
local new_version
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*-> \([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*version[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(command -v mo > /dev/null 2>&1 && mo --version 2> /dev/null | awk 'NR==1 && NF {print $NF}' || echo "")
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version="$fallback_version"
|
|
fi
|
|
printf '\n%s\n' "${GREEN}${ICON_SUCCESS}${NC} Updated to latest version, ${new_version:-unknown}"
|
|
fi
|
|
}
|
|
|
|
output="Installing Mole...
|
|
Installation completed"
|
|
process_install_output "$output" "1.23.1"
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Installation completed"* ]]
|
|
[[ "$output" == *"Updated to latest version, 1.23.1"* ]]
|
|
}
|
|
|
|
@test "process_install_output handles empty output with fallback version" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
GREEN='\033[0;32m'
|
|
ICON_SUCCESS='✓'
|
|
NC='\033[0m'
|
|
|
|
process_install_output() {
|
|
local output="$1"
|
|
local fallback_version="$2"
|
|
|
|
local filtered_output
|
|
filtered_output=$(printf '%s\n' "$output" | sed '/^$/d')
|
|
if [[ -n "$filtered_output" ]]; then
|
|
printf '%s\n' "$filtered_output"
|
|
fi
|
|
|
|
if ! printf '%s\n' "$output" | grep -Eq "Updated to latest version|Already on latest version"; then
|
|
local new_version
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*-> \([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*version[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(command -v mo > /dev/null 2>&1 && mo --version 2> /dev/null | awk 'NR==1 && NF {print $NF}' || echo "")
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version="$fallback_version"
|
|
fi
|
|
printf '\n%s\n' "${GREEN}${ICON_SUCCESS}${NC} Updated to latest version, ${new_version:-unknown}"
|
|
fi
|
|
}
|
|
|
|
output=""
|
|
process_install_output "$output" "1.23.1"
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Updated to latest version, 1.23.1"* ]]
|
|
}
|
|
|
|
@test "process_install_output does not extract wrong parentheses content" {
|
|
run bash --noprofile --norc <<'EOF'
|
|
set -euo pipefail
|
|
GREEN='\033[0;32m'
|
|
ICON_SUCCESS='✓'
|
|
NC='\033[0m'
|
|
|
|
process_install_output() {
|
|
local output="$1"
|
|
local fallback_version="$2"
|
|
|
|
local filtered_output
|
|
filtered_output=$(printf '%s\n' "$output" | sed '/^$/d')
|
|
if [[ -n "$filtered_output" ]]; then
|
|
printf '%s\n' "$filtered_output"
|
|
fi
|
|
|
|
if ! printf '%s\n' "$output" | grep -Eq "Updated to latest version|Already on latest version"; then
|
|
local new_version
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*-> \([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(printf '%s\n' "$output" | sed -n 's/.*version[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*/\1/p' | head -1)
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version=$(command -v mo > /dev/null 2>&1 && mo --version 2> /dev/null | awk 'NR==1 && NF {print $NF}' || echo "")
|
|
fi
|
|
if [[ -z "$new_version" ]]; then
|
|
new_version="$fallback_version"
|
|
fi
|
|
printf '\n%s\n' "${GREEN}${ICON_SUCCESS}${NC} Updated to latest version, ${new_version:-unknown}"
|
|
fi
|
|
}
|
|
|
|
output="Downloading (progress: 100%)
|
|
Done"
|
|
process_install_output "$output" "1.23.1"
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"Downloading (progress: 100%)"* ]]
|
|
[[ "$output" == *"Updated to latest version, 1.23.1"* ]]
|
|
[[ "$output" != *"progress: 100%"* ]] || [[ "$output" == *"Downloading (progress: 100%)"* ]]
|
|
}
|
|
|
|
@test "update_mole with --force reinstalls even when on latest version" {
|
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" CURRENT_VERSION="$CURRENT_VERSION" PATH="$HOME/fake-bin:/usr/bin:/bin" TERM="dumb" bash --noprofile --norc << 'EOF'
|
|
set -euo pipefail
|
|
curl() {
|
|
local out=""
|
|
local url=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-o)
|
|
out="$2"
|
|
shift 2
|
|
;;
|
|
http*://*)
|
|
url="$1"
|
|
shift
|
|
;;
|
|
*)
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -n "$out" ]]; then
|
|
cat > "$out" << 'INSTALLER'
|
|
#!/usr/bin/env bash
|
|
echo "Mole installed successfully, version $CURRENT_VERSION"
|
|
INSTALLER
|
|
return 0
|
|
fi
|
|
|
|
if [[ "$url" == *"api.github.com"* ]]; then
|
|
echo "{\"tag_name\":\"$CURRENT_VERSION\"}"
|
|
else
|
|
echo "VERSION=\"$CURRENT_VERSION\""
|
|
fi
|
|
}
|
|
export -f curl
|
|
|
|
brew() { exit 1; }
|
|
export -f brew
|
|
|
|
"$PROJECT_ROOT/mole" update --force
|
|
EOF
|
|
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" != *"Already on latest version"* ]]
|
|
[[ "$output" == *"Downloading"* ]] || [[ "$output" == *"Installing"* ]] || [[ "$output" == *"Updated"* ]]
|
|
}
|