The recent accent-colour setting only reached part of the desktop. looks.lua still hardcoded the focused-window border and glow to blue, so any hyprctl reload -- or every fresh session, for about a second -- reverted a chosen accent; it now reads accentName the same way it already read colorScheme. The lock screen and terminal stayed blue regardless of the chosen accent despite the setting's own description claiming otherwise; panama-lock and panama-theme-apps now resolve and apply the real accent. AccentPicker built its swatch model from Theme.accents directly instead of the schema's own options list, so the two could drift silently; switched it to read the schema. Its hit target only covered the swatch, not the name label added specifically for colour-vision accessibility -- extended to the whole row. Settings search had no route for the "appearance" group, so searching for the accent or colour scheme landed on Home. ColorScheme's hex-to-Hyprland helper assumed 6-digit colours and would silently corrupt a future translucent one; fixed it to read from the end of the string instead of the start. An accent-only change no longer reruns the full colour-scheme pipeline. The gradient it builds for the focused border now goes through SystemSettings' existing serialiser instead of a second, under-escaped copy of the same logic. The settings-ownership contract test enforced the old rule that ColorScheme must never touch the focused border; updated it to verify the real, intended rule instead of contradicting the code. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
185 lines
8.7 KiB
Bash
Executable File
185 lines
8.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
helper="$repo_dir/config/dot/quickshell/scripts/panama-lock"
|
|
schema="$repo_dir/config/dot/quickshell/config/PreferenceSchema.qml"
|
|
fixture="$(mktemp -d /tmp/panama-lock-helper.XXXXXX)"
|
|
fixture_home="$fixture/home"
|
|
config_home="$fixture/config"
|
|
state_home="$fixture/state"
|
|
test_bin="$fixture/bin"
|
|
settings="$config_home/panama/settings.json"
|
|
generated="$state_home/panama/hyprlock.conf"
|
|
hyprlock_log="$fixture/hyprlock.log"
|
|
theme_helper="$repo_dir/config/dot/quickshell/scripts/panama-theme-apps"
|
|
|
|
fail() {
|
|
printf 'lock screen helper contract: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
cleanup() {
|
|
chmod 700 "$state_home/panama" 2>/dev/null || true
|
|
rm -rf "$fixture"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "$fixture_home/Pictures/Wallpapers" "$config_home/panama" \
|
|
"$config_home/hypr" "$state_home" "$test_bin"
|
|
cp "$repo_dir/config/dot/hypr/hyprlock.conf.template" \
|
|
"$config_home/hypr/hyprlock.conf.template"
|
|
HOME="$fixture_home" XDG_CONFIG_HOME="$config_home" \
|
|
"$theme_helper" dark >/dev/null
|
|
[[ -s "$config_home/hypr/hyprlock.conf" ]] \
|
|
|| fail 'the themed fallback renderer did not create hyprlock.conf'
|
|
|
|
cat >"$test_bin/hyprctl" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
if [[ "${1:-}" == "-j" && "${2:-}" == "monitors" ]]; then
|
|
printf '%s\n' '[{"name":"DP-2"},{"name":"HDMI-A-1"}]'
|
|
exit 0
|
|
fi
|
|
exit 91
|
|
EOF
|
|
chmod +x "$test_bin/hyprctl"
|
|
|
|
cat >"$test_bin/hyprlock" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
printf '%s\n' "$*" >>"$PANAMA_TEST_HYPRLOCK_LOG"
|
|
EOF
|
|
chmod +x "$test_bin/hyprlock"
|
|
|
|
run_helper() {
|
|
HOME="$fixture_home" XDG_CONFIG_HOME="$config_home" XDG_STATE_HOME="$state_home" \
|
|
PATH="$test_bin:$PATH" PANAMA_TEST_HYPRLOCK_LOG="$hyprlock_log" "$helper" "$@"
|
|
}
|
|
|
|
write_settings() {
|
|
printf '%s\n' "$1" >"$settings"
|
|
}
|
|
|
|
assert_schema_entry() {
|
|
local key="$1"
|
|
rg -Fq "key: \"$key\"" "$schema" || fail "schema is missing $key"
|
|
}
|
|
|
|
[[ -x "$helper" ]] || fail 'panama-lock helper is missing or not executable'
|
|
for key in lockBackgroundMode lockBlurLevel lockShowClock lockShowDate lockShowUser lockFadeOnEmpty accentName; do
|
|
assert_schema_entry "$key"
|
|
done
|
|
|
|
write_settings '{}'
|
|
run_helper generate
|
|
[[ -s "$generated" ]] || fail 'default generation did not create a config'
|
|
rg -Fq 'path = screenshot' "$generated" || fail 'default background is not a screenshot'
|
|
rg -Fq 'blur_passes = 3' "$generated" || fail 'default blur pass count is not 3'
|
|
rg -Fq 'blur_size = 8' "$generated" || fail 'default blur size is not 8'
|
|
rg -Fq 'text = cmd[update:1000] date +"%-I:%M"' "$generated" || fail 'default clock is not 12-hour'
|
|
rg -Fq 'text = cmd[update:60000] date +"%A, %B %-d"' "$generated" || fail 'default date is missing'
|
|
rg -Fq 'text = $USER' "$generated" || fail 'default user label is missing'
|
|
rg -Fq 'fade_on_empty = false' "$generated" || fail 'default password field fades when empty'
|
|
jq -e '.generated == true and .fallback == false and .error == "" and (.path | endswith("/panama/hyprlock.conf"))' \
|
|
<<<"$(run_helper status)" >/dev/null || fail 'status did not report the generated config'
|
|
|
|
write_settings '{
|
|
"lockBackgroundMode":"solid",
|
|
"lockBlurLevel":0,
|
|
"lockShowClock":false,
|
|
"lockShowDate":false,
|
|
"lockShowUser":false,
|
|
"lockFadeOnEmpty":true,
|
|
"use24Hour":true,
|
|
"colorScheme":"light"
|
|
}'
|
|
run_helper generate
|
|
rg -Fq 'color = rgba(225, 226, 231, 1.0)' "$generated" || fail 'light solid mode does not match Theme.bg'
|
|
rg -Fq 'inner_color = rgba(208, 213, 227, 0.85)' "$generated" || fail 'light password field does not match the themed fallback'
|
|
rg -Fq 'font_color = rgba(55, 96, 191, 1.0)' "$generated" || fail 'light foreground does not match Theme.fg'
|
|
rg -Fq 'outer_color = rgba(46, 125, 233, 0.9)' "$generated" || fail 'light focus ring does not match Theme.accent'
|
|
rg -Fq 'check_color = rgba(46, 125, 233, 1.0)' "$generated" || fail 'light success colour does not match Theme.accent'
|
|
rg -Fq 'fail_color = rgba(245, 42, 101, 1.0)' "$generated" || fail 'light error colour does not match Theme.red'
|
|
rg -Fq 'foreground="##6172b0"' "$generated" || fail 'light placeholder markup retained the dark muted colour'
|
|
rg -Fq 'foreground="##f52a65"' "$generated" || fail 'light failure markup retained the dark error colour'
|
|
rg -Fq 'blur_passes = 0' "$generated" || fail 'blur level zero did not disable passes'
|
|
rg -Fq 'blur_size = 1' "$generated" || fail 'blur level zero did not use the safe size'
|
|
rg -Fq 'fade_on_empty = true' "$generated" || fail 'fade-on-empty setting was ignored'
|
|
if rg -q '^label \{' "$generated"; then
|
|
fail 'hidden clock, date, and user labels were still generated'
|
|
fi
|
|
|
|
# ── The focus ring follows the chosen accent, not just the scheme ───────────
|
|
# A pinned blue literal only ever proves the DEFAULT accent renders correctly,
|
|
# not that the helper actually reads accentName. Orchid is picked because its
|
|
# hex is nowhere close to blue's in either scheme, so a helper that quietly
|
|
# ignored accentName and kept emitting blue would be caught here.
|
|
write_settings '{"accentName":"orchid","colorScheme":"dark"}'
|
|
run_helper generate
|
|
rg -Fq 'outer_color = rgba(192, 153, 255, 0.9)' "$generated" || fail 'dark orchid accent did not drive the focus ring'
|
|
rg -Fq 'check_color = rgba(192, 153, 255, 1.0)' "$generated" || fail 'dark orchid accent did not drive the success colour'
|
|
|
|
write_settings '{"accentName":"orchid","colorScheme":"light"}'
|
|
run_helper generate
|
|
rg -Fq 'outer_color = rgba(120, 71, 189, 0.9)' "$generated" || fail 'light orchid accent did not drive the focus ring'
|
|
rg -Fq 'check_color = rgba(120, 71, 189, 1.0)' "$generated" || fail 'light orchid accent did not drive the success colour'
|
|
|
|
write_settings '{"accentName":"not-a-real-accent","colorScheme":"dark"}'
|
|
run_helper generate
|
|
rg -Fq 'outer_color = rgba(130, 170, 255, 0.9)' "$generated" || fail 'an unknown accent name did not fall back to blue'
|
|
|
|
write_settings '{
|
|
"lockBackgroundMode":"wallpaper",
|
|
"wallpaperMode":"per-monitor",
|
|
"wallpaperPath":"/images/global.jpg",
|
|
"wallpaperPerMonitor":{"DP-2":"/images/portrait.jpg"}
|
|
}'
|
|
run_helper generate
|
|
[[ "$(rg -c '^background \{' "$generated")" -eq 2 ]] || fail 'wallpaper mode did not create one block per output'
|
|
awk '/^background \{/{block++} block==1 && /monitor = DP-2/{monitor=1} block==1 && /path = \/images\/portrait.jpg/{path=1} END{exit !(monitor && path)}' "$generated" \
|
|
|| fail 'per-monitor wallpaper was not used for DP-2'
|
|
awk '/^background \{/{block++} block==2 && /monitor = HDMI-A-1/{monitor=1} block==2 && /path = \/images\/global.jpg/{path=1} END{exit !(monitor && path)}' "$generated" \
|
|
|| fail 'missing monitor assignment did not fall back to the global wallpaper'
|
|
|
|
write_settings '{"lockBackgroundMode":"screenshot","lockShowClock":true,"lockShowDate":false,"lockShowUser":false,"use24Hour":true}'
|
|
run_helper generate
|
|
rg -Fq 'text = cmd[update:1000] date +"%H:%M"' "$generated" || fail '24-hour clock setting was ignored'
|
|
|
|
write_settings '{"lockBackgroundMode":"nope","lockBlurLevel":99,"lockShowClock":"yes","lockShowDate":0,"lockShowUser":null,"lockFadeOnEmpty":[]}'
|
|
run_helper generate
|
|
rg -Fq 'path = screenshot' "$generated" || fail 'invalid background mode did not use the default'
|
|
rg -Fq 'blur_passes = 3' "$generated" || fail 'invalid blur did not use the default'
|
|
rg -Fq 'text = cmd[update:1000] date +"%-I:%M"' "$generated" || fail 'invalid clock boolean did not use the default'
|
|
rg -Fq 'text = cmd[update:60000] date +"%A, %B %-d"' "$generated" || fail 'invalid date boolean did not use the default'
|
|
rg -Fq 'text = $USER' "$generated" || fail 'invalid user boolean did not use the default'
|
|
rg -Fq 'fade_on_empty = false' "$generated" || fail 'invalid fade boolean did not use the default'
|
|
|
|
write_settings 'not json'
|
|
run_helper generate
|
|
rg -Fq 'path = screenshot' "$generated" || fail 'malformed JSON did not use shipped defaults'
|
|
|
|
before_checksum="$(sha256sum "$generated" | cut -d' ' -f1)"
|
|
chmod 500 "$state_home/panama"
|
|
if run_helper generate >/dev/null 2>&1; then
|
|
fail 'generation unexpectedly succeeded with an unwritable state directory'
|
|
fi
|
|
after_checksum="$(sha256sum "$generated" | cut -d' ' -f1)"
|
|
[[ "$before_checksum" == "$after_checksum" ]] || fail 'failed generation replaced the last valid config'
|
|
chmod 700 "$state_home/panama"
|
|
|
|
: >"$hyprlock_log"
|
|
run_helper run
|
|
[[ "$(tail -1 "$hyprlock_log")" == "-c $generated" ]] || fail 'run did not use the generated config after success'
|
|
|
|
chmod 500 "$state_home/panama"
|
|
run_helper run 2>"$fixture/fallback.stderr"
|
|
chmod 700 "$state_home/panama"
|
|
[[ "$(tail -1 "$hyprlock_log")" == "-c $config_home/hypr/hyprlock.conf" ]] \
|
|
|| fail 'run did not use the tracked fallback after generation failure'
|
|
[[ ! -s "$fixture/fallback.stderr" ]] || fail 'safe fallback leaked an internal filesystem error'
|
|
|
|
printf 'lock screen helper contract: PASS\n'
|