Merge branch 'omacom:quattro' into omarchycn

This commit is contained in:
ZacharyZhang-NY authored and GitHub committed 2026-10-07 14:35:21 -04:00
commit 37207f1911
43 files changed
+1162 -158

No files matched your search

@@ -0,0 +1,46 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
migration="$ROOT/migrations/1791376887.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
home="$test_tmp/home"
config_dir="$home/.config"
mkdir -p "$config_dir" "$test_tmp/targets"
printf '%s\n' '--enable-features=TouchpadOverscrollHistoryNavigation' >"$config_dir/chromium-flags.conf"
printf '%s\n' '--enable-features=' >"$config_dir/chrome-flags.conf"
printf '%s' '--ozone-platform=wayland' >"$config_dir/microsoft-edge-stable-flags.conf"
printf '%s\n' '--enable-features=BraveFeature' >"$test_tmp/targets/brave-flags.conf"
ln -s "$test_tmp/targets/brave-flags.conf" "$config_dir/brave-flags.conf"
run_migration() {
HOME="$home" bash -euo pipefail "$migration" >/dev/null
}
run_migration
run_migration
grep -Fxq -- '--enable-features=TouchpadOverscrollHistoryNavigation,OverlayScrollbar' "$config_dir/chromium-flags.conf" ||
fail "the migration preserves existing Chromium features"
overlay_count=$(grep -o 'OverlayScrollbar' "$config_dir/chromium-flags.conf" | wc -l)
(( overlay_count == 1 )) || fail "the migration does not duplicate the Chromium feature"
pass "the migration preserves existing features and can run twice"
[[ $(cat "$config_dir/chrome-flags.conf") == '--enable-features=OverlayScrollbar' ]] ||
fail "the migration fills an empty feature list"
[[ $(cat "$config_dir/microsoft-edge-stable-flags.conf") == $'--ozone-platform=wayland\n--enable-features=OverlayScrollbar' ]] ||
fail "the migration adds a feature list with a missing trailing newline"
pass "the migration handles empty and missing feature lists"
[[ -L $config_dir/brave-flags.conf ]] || fail "the migration preserves symlinked browser flags"
grep -Fxq -- '--enable-features=BraveFeature,OverlayScrollbar' "$config_dir/brave-flags.conf" ||
fail "the migration updates the target of symlinked browser flags"
pass "the migration follows symlinked browser flags"
[[ ! -e $config_dir/brave-origin-flags.conf ]] || fail "the migration leaves missing browser flags absent"
pass "the migration skips missing browser flags"
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
mkdir -p "$test_tmp/bin" "$test_tmp/home/.local/share/applications"
for helper in omarchy-pkg-add omarchy-pkg-drop update-desktop-database; do
cat > "$test_tmp/bin/$helper" <<'SH'
#!/bin/bash
printf '%s %s\n' "${0##*/}" "$*" >> "$TEST_LOG"
SH
chmod +x "$test_tmp/bin/$helper"
done
launcher="$test_tmp/home/.local/share/applications/Disk Usage.desktop"
printf '[Desktop Entry]\nExec=dua i /\n' > "$launcher"
for (( attempt = 0; attempt < 2; attempt++ )); do
env HOME="$test_tmp/home" OMARCHY_PATH="$ROOT" TEST_LOG="$test_tmp/log" PATH="$test_tmp/bin:$PATH" \
bash -euo pipefail "$ROOT/migrations/1791345484.sh"
[[ ! -e $launcher ]] || fail "the migration removes the old Disk Usage launcher"
done
pass "the Disktree migration removes the old launcher and can run twice"
expected="omarchy-pkg-add disktree-bin
omarchy-pkg-drop dua-cli
update-desktop-database $test_tmp/home/.local/share/applications"
[[ $(cat "$test_tmp/log") == "$expected"$'\n'"$expected" ]] || fail "the migration installs Disktree before removing dua and refreshing launchers"
pass "the migration installs Disktree before removing dua and refreshing launchers"
rm -r "$test_tmp/home/.local/share/applications"
env HOME="$test_tmp/home" OMARCHY_PATH="$ROOT" TEST_LOG="$test_tmp/log" PATH="$test_tmp/bin:$PATH" \
bash -euo pipefail "$ROOT/migrations/1791345484.sh"
[[ ! -d $test_tmp/home/.local/share/applications ]] || fail "the migration relies on the packaged Disktree launcher"
pass "the migration relies on the packaged Disktree launcher when no local launchers exist"
@@ -52,7 +52,9 @@ case "$name" in
;;
mv)
[[ ${TEST_PUBLISH_FAIL:-0} != 1 ]] || exit 1
[[ ${TEST_REQUIRE_EXISTING_TARGET:-0} != 1 || -f ${@: -1} ]] || exit 1
/usr/bin/mv "$@"
[[ ${TEST_KILL_AFTER_PUBLISH:-0} != 1 ]] || /usr/bin/kill -KILL "$PPID"
[[ ${TEST_POST_PUBLISH_FAIL:-0} != 1 ]] || : >"$TEST_GRANT_ROOT/run/omarchy-sudo-passwordless-package-removing"
;;
systemd-run)
@@ -69,7 +71,15 @@ case "$name" in
sudo)
if [[ ${1:-} == -h ]]; then echo 'usage: sudo [-N] command'; exit 0; fi
if [[ ${1:-} == -k ]]; then exit 0; fi
if [[ ${1:-} == -N ]]; then shift; fi
if [[ ${1:-} == -n && ${3:-} == -l ]]; then
[[ ${TEST_POLICY_FAILURE:-0} != 1 ]] || exit 1
default_policy=' Options: authenticate'
[[ ${TEST_STATUS:-3} == 3 ]] || default_policy=' Options: !authenticate'
printf '%s\n' "${TEST_POLICY:-$default_policy}"
exit 0
fi
if [[ ${1:-} == -n ]]; then shift; fi
if [[ ${1:-} == -N || ${1:-} == -kn ]]; then shift; fi
if [[ ${1:-} == -- ]]; then shift; fi
if [[ ${TEST_MIGRATION:-0} == 1 ]]; then
[[ ${TEST_NO_SUDO:-0} != 1 ]] || exit 1
@@ -78,7 +88,14 @@ case "$name" in
[[ ${2:-} != __status ]] || exit "${TEST_STATUS:-3}"
fi
;;
gum) exit 1 ;;
gum)
if [[ $1 == choose ]]; then
[[ ${TEST_CHOICE_CANCEL:-0} != 1 ]] || exit 130
printf '%s\n' "${TEST_CHOICE:-15 minutes}"
else
exit "${TEST_CONFIRM_STATUS:-1}"
fi
;;
*) exit 99 ;;
esac
STUB
@@ -120,6 +137,6 @@ assert_status() {
(( actual == expected )) || fail "expected status $expected, got $actual from $*"
}
reset_grant() {
rm -f "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-1000" "$test_tmp/run/omarchy-sudo-passwordless-package-removing"
rm -f "$test_tmp/etc/sudoers.d/99-omarchy-permanent-nopasswd-1000" "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-1000" "$test_tmp/run/omarchy-sudo-passwordless-package-removing"
: >"$test_tmp/commands"
}
+1 -1
View File
@@ -147,7 +147,7 @@ assert(
)
assert(
/OverlayWindow \{\s*id: panel\s*shown: root\.opened\s*shownKeyboardFocus: root\.imagesLoaded \? WlrKeyboardFocus\.Exclusive : WlrKeyboardFocus\.None/.test(imagePickerQml),
'image picker parks on OverlayWindow and takes the keyboard once images load'
'image picker uses OverlayWindow and takes the keyboard once images load'
)
assert(
/model: visibleImages/.test(imagePickerQml) &&
+212 -1
View File
@@ -32,7 +32,7 @@ for status in 1 2 3; do
else
(( result != 0 )) && ! grep -q '^gum ' "$test_tmp/commands" || fail "inspection errors must not offer enablement"
fi
grep -q '^sudo -N -- .* __status ' "$test_tmp/commands" || fail "status must not publish reusable authorization"
grep -q '^sudo -n -N -l -l -- .* __status ' "$test_tmp/commands" || fail "status must inspect policy without authentication"
[[ $(tail -1 "$test_tmp/commands") == 'sudo -k' ]] || fail "public exit must revoke its authorization"
done
pass "public status distinguishes inactive from errors and revokes authorization on exit"
@@ -164,3 +164,214 @@ cp "$ROOT/default/libalpm/hooks/05-omarchy-passwordless-revoke.hook" "$test_tmp/
[[ ! -e $(rule_file 1000) ]]
)
pass "trailing-dollar accounts publish valid native policy and alias-shaped names never publish"
reset_grant
(
source "$library"
valid_duration permanent
! valid_duration forever || fail "invalid duration was accepted"
enable_locked 1000 permanent
read_grant 1000
[[ $GRANT_NAME == audituser && -z $GRANT_DEADLINE ]]
[[ $(stat -c '%a' "$(rule_file 1000 permanent)") == 440 ]]
/usr/sbin/visudo -cf "$(rule_file 1000 permanent)" >/dev/null
! grep -q '^systemd-run ' "$test_tmp/commands" || fail "permanent grant started a timer"
TEST_EXPIRED=1 status_locked 1000
TEST_EXPIRED=1 expire_locked 1000
cleanup_all_locked
/usr/bin/systemd-tmpfiles --root="$test_tmp" --remove --boot --inline 'r! /etc/sudoers.d/99-omarchy-nopasswd-*'
[[ -f $(rule_file 1000 permanent) ]]
cleanup_uid_locked 1000
assert_status 3 status_locked 1000
)
pass "permanent access has no timer, survives expiry and temporary cleanup, and can be disabled"
reset_grant
(
source "$library"
enable_locked 1000 15
enable_locked 1000 permanent
[[ ! -e $(rule_file 1000) && -e $(rule_file 1000 permanent) ]]
TEST_EXPIRED=1 expire_locked 1000
[[ -e $(rule_file 1000 permanent) ]]
enable_locked 1000 60
[[ -e $(rule_file 1000) && ! -e $(rule_file 1000 permanent) ]]
TEST_EXPIRED=1 expire_locked 1000
assert_status 3 status_locked 1000
TEST_PUBLISH_FAIL=1 assert_status 1 enable_locked 1000 permanent
[[ ! -e $(rule_file 1000 permanent) ]]
)
pass "switching duration replaces the prior policy and old callbacks preserve permanent access"
reset_grant
(
source "$library"
permanent=$(rule_file 1000 permanent)
printf 'audituser ALL=(ALL) NOPASSWD: /usr/bin/true\n' >"$permanent"
assert_status 2 status_locked 1000
assert_status 1 enable_locked 1000 permanent
assert_status 1 cleanup_uid_locked 1000
[[ -e $permanent ]]
rm "$permanent"
enable_locked 1000 permanent
TEST_BAD_PATH="$permanent" assert_status 2 status_locked 1000
)
pass "permanent policy rejects unsafe ownership and preserves administrator edits"
for choice in '15 minutes' '1 Hour' '1 Day' Permanently; do
case "$choice" in
'15 minutes') expected=15 ;;
'1 Hour') expected=60 ;;
'1 Day') expected=1440 ;;
Permanently) expected=permanent ;;
esac
: >"$test_tmp/commands"
TEST_CHOICE="$choice" TEST_CONFIRM_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" >"$test_tmp/public.log" 2>&1
grep -q '^gum choose .*15 minutes 1 Hour 1 Day Permanently$' "$test_tmp/commands"
grep -q "^sudo -N -- .* __enable .* $expected$" "$test_tmp/commands"
[[ $(tail -1 "$test_tmp/commands") == 'sudo -k' ]]
if [[ $expected == permanent ]]; then
grep -q 'remain enabled across reboots until you disable it' "$test_tmp/public.log"
! grep -q 'automatically disable' "$test_tmp/public.log" || fail "permanent grant claims automatic expiry"
fi
done
pass "each duration choice dispatches its exact grant duration with permanent-specific copy"
: >"$test_tmp/commands"
assert_status 130 env TEST_CHOICE_CANCEL=1 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" >"$test_tmp/public.log" 2>&1
! grep -q '__enable\|^gum confirm ' "$test_tmp/commands" || fail "cancelled picker continued enablement"
[[ $(tail -1 "$test_tmp/commands") == 'sudo -k' ]]
: >"$test_tmp/commands"
TEST_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" >"$test_tmp/public.log" 2>&1
! grep -q '^gum ' "$test_tmp/commands" || fail "disabling access offered a picker"
grep -q '__disable ' "$test_tmp/commands"
pass "cancelling the picker grants nothing and active access still toggles off"
for confirm_status in 0 1; do
: >"$test_tmp/commands"
TEST_STATUS=0 TEST_CONFIRM_STATUS=$confirm_status /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" permanent >"$test_tmp/public.log" 2>&1
grep -q '^gum confirm Enable passwordless sudo permanently?' "$test_tmp/commands"
if (( confirm_status == 0 )); then
grep -q '__enable .* permanent$' "$test_tmp/commands"
else
! grep -q '__enable ' "$test_tmp/commands" || fail "declining permanent access still enabled it"
fi
done
pass "changing active access to permanent always requires confirmation"
reset_grant
(
source "$library"
enable_locked 1000 15
TEST_REQUIRE_EXISTING_TARGET=1 enable_locked 1000 60
cleanup_uid_locked 1000
enable_locked 01000 permanent
status_locked 1000
[[ -e $(rule_file 1000 permanent) ]]
[[ ! -e $test_tmp/etc/sudoers.d/99-omarchy-permanent-nopasswd-01000 ]]
cleanup_uid_locked 1000
assert_status 3 status_locked 01000
)
pass "renewal replaces the existing rule atomically and zero-padded UIDs share one policy"
for policy in ' Options: !authenticate' ' Options: authenticate'; do
: >"$test_tmp/commands"
expected=1
[[ $policy != *'!authenticate'* ]] || expected=0
assert_status "$expected" env TEST_POLICY="$policy" /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --active
[[ $(wc -l <"$test_tmp/commands") == 1 ]]
grep -q '^sudo -n -N -l -l -- .* __status ' "$test_tmp/commands"
done
assert_status 1 env TEST_POLICY_FAILURE=1 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --active
pass "menu probe reads policy tags without executing a privileged action or changing the timestamp"
for status in 0 3; do
: >"$test_tmp/commands"
TEST_STATUS=$status /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --disable >"$test_tmp/public.log" 2>&1
! grep -q '^gum\|__enable ' "$test_tmp/commands" || fail "explicit disable offered enablement"
if (( status == 0 )); then
grep -q '__disable ' "$test_tmp/commands"
fi
done
pass "explicit disable never enables access even when a displayed grant has expired"
: >"$test_tmp/commands"
TEST_STATUS=3 TEST_CHOICE='15 minutes' TEST_CONFIRM_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" >"$test_tmp/public.log" 2>&1
[[ $(grep -c '^sudo -N -- ' "$test_tmp/commands") == 1 ]] || fail "enable must authenticate exactly one sudo call"
grep -q '^sudo -N -- .* __enable .* 15$' "$test_tmp/commands"
! grep -q '^sudo -n -N -- .* __status ' "$test_tmp/commands" || fail "inactive flow attempted root status"
[[ $(tail -1 "$test_tmp/commands") == 'sudo -k' ]]
pass "enabling from inactive policy has exactly one password-capable sudo invocation"
: >"$test_tmp/commands"
TEST_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --disable >"$test_tmp/public.log" 2>&1
grep -q '^sudo -n -N -- .* __disable ' "$test_tmp/commands" || fail "disable must refuse interactive authentication"
! grep -q '^sudo -N -- ' "$test_tmp/commands" || fail "disable attempted an interactive sudo command"
pass "disabling active access is fully noninteractive"
for duration in permanent 15; do
reset_grant
(
source "$library"
if [[ $duration == permanent ]]; then
enable_locked 1000 15
else
enable_locked 1000 permanent
fi
assert_status 137 env TEST_KILL_AFTER_PUBLISH=1 TEST_EUID=0 SUDO_UID=1000 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" __enable 1000 "$duration"
[[ -f $(rule_file 1000) && -f $(rule_file 1000 permanent) ]]
status_locked 1000
TEST_EXPIRED=1 expire_locked 1000
[[ -f $(rule_file 1000 permanent) ]]
cleanup_uid_locked 1000
assert_status 3 status_locked 1000
)
done
pass "SIGKILL during either duration switch leaves access inspectable and revocable without expiring permanent policy"
reset_grant
(
source "$library"
enable_locked 1000 permanent
timed=$(rule_file 1000)
printf 'otheruser ALL=(ALL) NOTAFTER=99991231235959Z NOPASSWD: ALL\n' >"$timed"
assert_status 2 read_grant 1000
assert_status 1 enable_locked 1000 15
printf 'audituser ALL=(ALL) NOTAFTER=99991231235959Z NOPASSWD: ALL\n' >"$timed"
TEST_BAD_PATH="$timed" assert_status 2 read_grant 1000
rm "$timed"
ln -s "$(rule_file 1000 permanent)" "$timed"
assert_status 2 read_grant 1000
rm "$timed"
printf 'audituser ALL=(ALL) NOTAFTER=99991231235959Z NOPASSWD: ALL\n' >"$timed"
enable_locked 1000 15
[[ -f $timed && ! -e $(rule_file 1000 permanent) ]]
)
pass "paired policy recovery rejects mismatched or unsafe rules and allows a complete duration change"
: >"$test_tmp/commands"
TEST_POLICY_FAILURE=1 TEST_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --disable >"$test_tmp/public.log" 2>&1
grep -q '^sudo -n -N -- .* __disable ' "$test_tmp/commands"
! grep -q '^gum\|^sudo -N -- ' "$test_tmp/commands" || fail "listpw=always disable prompted"
TEST_POLICY_FAILURE=1 TEST_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --active
assert_status 1 env TEST_POLICY_FAILURE=1 TEST_STATUS=1 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --active
: >"$test_tmp/commands"
TEST_POLICY_FAILURE=1 TEST_STATUS=1 TEST_CONFIRM_STATUS=0 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" 15 >"$test_tmp/public.log" 2>&1
[[ $(grep -c '^sudo -N -- ' "$test_tmp/commands") == 1 ]] || fail "listing failure must leave one enable authentication"
grep -q '^sudo -N -- .* __enable .* 15$' "$test_tmp/commands"
: >"$test_tmp/commands"
assert_status 1 env TEST_POLICY_FAILURE=1 TEST_STATUS=2 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" 15 >"$test_tmp/public.log" 2>&1
! grep -q '^gum\|__enable ' "$test_tmp/commands" || fail "unsafe grant was offered enablement"
pass "password-required listings do not block enabling, disabling, or active detection"
: >"$test_tmp/commands"
TEST_POLICY_FAILURE=1 TEST_STATUS=2 /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" --active
grep -q '^sudo -kn -- .* __status ' "$test_tmp/commands" || fail "fallback probe must ignore cached credentials"
(
source "$library"
with_root_lock() { return 1; }
verify_sudo_caller() { return 0; }
assert_status 2 root_dispatch __status 1000
)
pass "status lock failures remain inspection errors and an authenticated unsafe grant keeps its warning"
+120 -23
View File
@@ -9,31 +9,122 @@ const fs = require('fs')
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8')
const overlay = read('shell/Ui/OverlayWindow.qml')
// Closed, the surface parks 1x1, input-less and without keyboard below
// windows: off the overlay layer, so it never blocks direct scanout.
// Closing must unmap, not leave a surface on an output that may disappear.
assert(
overlay.includes('visible: true') &&
overlay.includes('anchors { top: true; left: true; bottom: shown; right: shown }') &&
overlay.includes('implicitWidth: 1') &&
overlay.includes('implicitHeight: 1') &&
overlay.includes('mask: shown ? null : emptyRegion') &&
overlay.includes('WlrLayershell.layer: shown ? shownLayer : WlrLayer.Bottom') &&
overlay.includes('WlrLayershell.keyboardFocus: shown ? shownKeyboardFocus : WlrKeyboardFocus.None'),
'overlay window parks a 1x1 input-less surface below windows while hidden'
overlay.includes('visible: shown && !!targetScreen && !!targetMonitor') &&
overlay.includes('anchors { top: true; left: true; bottom: true; right: true }') &&
!overlay.includes('implicitWidth: 1') && !overlay.includes('WlrLayer.Bottom'),
'closed overlays unmap instead of parking a surface'
)
// Content stays hidden until the surface has grown, so no frame drawn at 1x1
// is stretched across the screen.
const readyExpression = /readonly property bool contentReady: ([^\n]*(?:\n &&[^\n]*)*)/.exec(overlay)[1]
const ready = new Function('shown', 'backingWindowVisible', 'width', 'height', 'targetScreen', 'targetMonitor', 'devicePixelRatio', `return ${readyExpression}`)
const screen = { name: 'eDP-1', width: 1200, height: 750 }
const monitor = { name: 'eDP-1', scale: 1.6 }
for (const scale of [2, 1, 1.6]) {
assertEqual(ready(true, true, 1200, 750, screen, monitor, scale), scale === 1.6,
`opening frames at ${scale}x wait for the monitor's 1.6x scale`)
}
for (const scale of [1, 1.25, 1.5, 2]) {
assert(ready(true, true, 1200, 750, screen, { scale }, scale),
`overlay reveals at the correct ${scale}x scale`)
}
assert(ready(true, true, 1200, 750, screen, { scale: 1.333333 }, 160 / 120),
'scale comparison tolerates compositor floating point rounding')
assert(!ready(true, true, 500, 500, screen, monitor, 1.6),
'initial window geometry never stretches content across the screen')
assert(!ready(true, false, 1200, 750, screen, monitor, 1.6),
'content waits for a mapped backing window')
assert(!ready(false, true, 1200, 750, screen, monitor, 1.6),
'closed content stays transparent even at the correct scale')
assert(!ready(true, true, 1200, 750, null, monitor, 1.6) &&
!ready(true, true, 1200, 750, screen, null, 1.6),
'content waits for a connected screen and its monitor information')
assert(
/target: window\.contentItem\s*property: "visible"\s*value: window\.shown && window\.width > 1 && window\.height > 1/.test(overlay),
'overlay window draws nothing until the surface has grown'
/target: window\.contentItem\s*property: "opacity"\s*value: window\.contentRevealed \? 1 : 0/.test(overlay),
'transparent opening frames preserve immediate keyboard handling'
)
assert(
/onShownChanged: if \(shown\) targetScreen = focusedScreen\(\) \|\| targetScreen/.test(overlay) &&
overlay.includes('screen: targetScreen'),
'overlay window follows the focused monitor each time it is shown'
)
const revealBody = /onContentReadyChanged: \{([\s\S]*?)\n \}/.exec(overlay)[1]
const reveal = new Function('window', 'Qt', `with (window) { ${revealBody} }`)
const reveals = []
const revealQt = { callLater(callback) { reveals.push(callback) } }
const content = { contentReady: true, contentRevealed: false }
reveal(content, revealQt)
assert(!content.contentRevealed, 'scale and resize notifications finish before content reveals')
reveals.shift()()
assert(content.contentRevealed, 'settled content reveals on the next event-loop turn')
content.contentReady = false
reveal(content, revealQt)
assert(!content.contentRevealed, 'losing readiness immediately hides content')
content.contentReady = true
reveal(content, revealQt)
content.contentReady = false
reveal(content, revealQt)
reveals.shift()()
assert(!content.contentRevealed, 'a close or screen loss cancels a pending reveal')
const focusedScreenBody = /function focusedScreen\(\) \{([\s\S]*?)\n \}/.exec(overlay)[1]
const focusedScreen = new Function('Hyprland', 'Quickshell', focusedScreenBody)
const external = { name: 'DP-1', width: 1920, height: 1080 }
assertEqual(focusedScreen({ focusedMonitor: { name: 'DP-1' } }, { screens: [screen, external] }), external,
'overlay selects the focused output')
assertEqual(focusedScreen({ focusedMonitor: { name: 'DP-1' } }, { screens: [screen] }), screen,
'disconnecting the focused output falls back to a connected screen')
assertEqual(focusedScreen({ focusedMonitor: null }, { screens: [] }), null,
'no outputs leaves the overlay unmapped')
const shownHandler = /onShownChanged: \{([\s\S]*?)\n \}/.exec(overlay)[1]
let refreshed = 0
const Hyprland = { refreshMonitors() { refreshed++ } }
const changeShown = new Function('shown', 'focusedScreen', 'Hyprland', `let targetScreen = null; ${shownHandler}; return targetScreen`)
assertEqual(changeShown(false, () => external, Hyprland), null, 'closing drops the previous screen reference')
assertEqual(refreshed, 0, 'closing does not refresh monitor data')
assertEqual(changeShown(true, () => screen, Hyprland), screen, 'reopening selects a current screen')
assertEqual(refreshed, 1, 'opening refreshes monitor scales after a live change while closed')
const scaleHandler = /onDevicePixelRatioChanged: ([^\n]+)/.exec(overlay)[1]
const changeScale = new Function('shown', 'Hyprland', scaleHandler)
changeScale(false, Hyprland)
assertEqual(refreshed, 1, 'scale changes on hidden windows do not refresh monitor data')
const changedScreen = { name: 'eDP-1', width: 960, height: 600 }
assert(!ready(true, true, 960, 600, changedScreen, monitor, 2),
'a stale monitor scale keeps content transparent after a live scale change')
Hyprland.refreshMonitors = () => { refreshed++; monitor.scale = 2 }
changeScale(true, Hyprland)
assertEqual(refreshed, 2, 'a showing window refreshes monitor scales when Qt receives a live change')
assert(ready(true, true, 960, 600, changedScreen, monitor, 2),
'fresh monitor data lets content reveal at the new scale')
const screensChangedBody = /function onScreensChanged\(\) \{([\s\S]*?)\n \}/.exec(overlay)[1]
const screensChanged = new Function('window', 'Quickshell', 'Qt', screensChangedBody)
const pending = []
const Qt = { callLater(callback) { pending.push(callback) } }
const window = { shown: true, targetScreen: external, focusedScreen: () => screen }
screensChanged(window, { screens: [screen] }, Qt)
assertEqual(window.targetScreen, null, 'screen removal unmaps before Qt finishes destroying the old window')
pending.shift()()
assertEqual(window.targetScreen, screen, 'a showing overlay moves off a disconnected screen')
window.targetScreen = screen
window.focusedScreen = () => external
screensChanged(window, { screens: [screen, external] }, Qt)
assertEqual(window.targetScreen, screen, 'connecting another screen does not move a showing overlay')
window.shown = false
window.targetScreen = null
screensChanged(window, { screens: [screen, external] }, Qt)
assertEqual(window.targetScreen, null, 'screen changes leave a closed overlay unmapped')
window.shown = true
window.targetScreen = external
screensChanged(window, { screens: [screen] }, Qt)
window.shown = false
pending.shift()()
assertEqual(window.targetScreen, null, 'closing before a deferred remap prevents a stale reopen')
window.shown = true
window.targetScreen = external
screensChanged(window, { screens: [screen] }, Qt)
window.targetScreen = screen
window.focusedScreen = () => external
pending.shift()()
assertEqual(window.targetScreen, screen, 'a deferred remap preserves the screen chosen by a newer open')
const overlays = {
'shell/plugins/menu/Menu.qml': 'shown: root.opened && root.rowsLoaded',
@@ -48,11 +139,11 @@ for (const [file, shown] of Object.entries(overlays)) {
const qml = read(file)
assert(
qml.includes('OverlayWindow {') && qml.includes(shown) && !/PanelWindow \{\s*(id: panel\s*)?visible: root\.opened/.test(qml),
`${file} keeps its surface through OverlayWindow`
`${file} uses the shared overlay scale and lifecycle handling`
)
}
// Window visibility never changes now, so close-time resets key off shown.
// Layout resets on a requested close, independent of mapping readiness.
const menuQml = read('shell/plugins/menu/Menu.qml')
assert(
menuQml.includes('onShownChanged: if (!shown) { cardTop = -1; maxRowsHeight = -1 }') &&
@@ -60,9 +151,15 @@ assert(
!/onVisibleChanged: if \(!visible\) \{ cardTop/.test(menuQml),
'the menu unfreezes its layout when the overlay hides'
)
const screenHandler = /onTargetScreenChanged: \{([^\n]*)\}/.exec(menuQml)[1]
const changeScreen = new Function('panel', `with (panel) { ${screenHandler} }`)
const menuPanel = { shown: true, cardTop: 945, maxRowsHeight: 510 }
changeScreen(menuPanel)
assertEqual(menuPanel.cardTop, -1, 'moving an open menu off a disconnected output unfreezes its old top edge')
assertEqual(menuPanel.maxRowsHeight, -1, 'moving an open menu drops the old output row-height limit')
assert(menuPanel.shown, 'resetting the layout keeps the menu open')
// A kept surface grows from its parked 1x1 when shown, which Hyprland animates
// as a slide in from the corner unless its layer rule turns animation off.
// Fullscreen overlays open without an additional compositor animation.
const shellRules = read('default/hypr/apps/omarchy-shell.lua')
const noAnim = /namespace = "\^\(([^)]*)\)\$" \}, no_anim = true/.exec(shellRules)
assert(noAnim, 'the shell overlays share one no-animation layer rule')
@@ -0,0 +1,36 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
run_node_test <<'JS'
const fs = require('fs')
const read = name => fs.readFileSync(path.join(root, name), 'utf8')
const indicator = read('shell/plugins/bar/indicators/PasswordlessSudo.qml')
const widget = read('shell/plugins/bar/widgets/Indicators.qml')
const manifest = JSON.parse(read('shell/plugins/bar/widgets/Indicators.manifest.json'))
assert(widget.match(/defaultIndicatorEntries: \[ "PasswordlessSudo", "Dictation"/), 'passwordless sudo is included in the default indicator tray')
assert(manifest.barWidget.schema.find(field => field.key === 'items').options.some(option => option.value === 'PasswordlessSudo'), 'passwordless sudo is configurable alongside Night Light')
assert(indicator.includes('useActiveColor: true') && indicator.includes('activeColor: Color.urgent'), 'active passwordless sudo uses the theme danger color')
assertEqual(indicator.match(/activeText: "([^"]+)"/)[1], indicator.match(/inactiveText: "([^"]+)"/)[1], 'sudo keeps the same icon in both states')
assert(!widget.includes('sudoHorizontal') && !widget.includes('sudoVertical'), 'sudo participates in the normal indicator blocks')
assert(!indicator.includes('visible:'), 'sudo uses the shared indicator visibility and hover behavior')
assert(indicator.includes('command: ["omarchy-sudo-passwordless", "--active"]'), 'indicator uses the noninteractive grant probe')
assert(indicator.includes('root.granted = exitCode === 0 && exitStatus === 0'), 'failed or interrupted probes do not claim an active grant')
assert(indicator.includes('interval: 5000') && indicator.includes('onTriggered: root.refresh()'), 'indicator refreshes after activation, revocation, and expiry')
assert(indicator.includes('command: ["omarchy-sudo-passwordless", "--disable"]'), 'active indicator revokes access through a background process')
assert(indicator.includes('if (root.granted) disableProc.running = true'), 'active click bypasses the terminal launcher')
assert(indicator.includes('root.indicatorHost.refresh()'), 'disabling access refreshes all indicator instances immediately')
const press = new Function('root', 'disableProc', indicator.match(/onPressed: function\(\) \{([\s\S]*?)\n \}/)[1])
const launched = []
const button = { granted: true, bar: { run: command => launched.push(command) } }
const revoke = { running: false }
press(button, revoke)
assert(revoke.running && launched.length === 0, 'clicking active sudo starts background revocation without a terminal')
button.granted = false
press(button, revoke)
assert(launched.length === 0, 'repeat clicks during revocation cannot open the enable flow')
revoke.running = false
press(button, revoke)
assertDeepEqual(launched, ['omarchy-launch-floating-terminal-with-presentation omarchy-sudo-passwordless'], 'inactive click still opens interactive setup')
JS
+25 -3
View File
@@ -23,7 +23,7 @@ SH
}
run_orphan_checker() {
HOME="$test_home" PATH="$stub_bin:$PATH" "$ROOT/bin/omarchy-update-orphan-pkgs"
HOME="$test_home" PATH="$stub_bin:$ROOT/bin:$PATH" "$ROOT/bin/omarchy-update-orphan-pkgs" "$@"
}
write_stub pacman 'if [[ $1 == "-Qtdq" ]]; then printf "old-lib\nunused-tool\n"; exit 0; fi; exit 1'
@@ -35,7 +35,29 @@ grep -q '^ old-lib$' "$test_tmp/noninteractive.out" || fail "orphan checker lis
grep -q 'Re-run omarchy-update-orphan-pkgs in a terminal' "$test_tmp/noninteractive.out" || fail "orphan checker does not remove packages non-interactively"
pass "orphan checker only reports orphans non-interactively"
export REMOVAL_LOG="$test_tmp/removal.log"
write_stub pacman 'case $1 in
-Qtdq|-Qq) printf "old-lib\nunused-tool\n" ;;
-Rns) printf "%s\n" "$@" >"$REMOVAL_LOG" ;;
*) exit 1 ;;
esac'
write_stub sudo '"$@"'
run_orphan_checker -y >"$test_tmp/approved.out" 2>"$test_tmp/approved.err"
diff <(printf '%s\n' -Rns --noconfirm old-lib unused-tool) "$REMOVAL_LOG" ||
fail "approved cleanup removes the orphan packages without pacman confirmation"
pass "approved cleanup removes orphans without Omarchy or pacman confirmation"
write_stub sudo 'exit 42'
if run_orphan_checker -y >"$test_tmp/failure.out" 2>"$test_tmp/failure.err"; then
fail "approved cleanup reports removal failures"
fi
pass "approved cleanup reports removal failures"
rm -f "$REMOVAL_LOG"
write_stub pacman 'if [[ $1 == "-Qtdq" ]]; then exit 0; fi; exit 1'
run_orphan_checker >"$test_tmp/none.out" 2>"$test_tmp/none.err"
[[ ! -s $test_tmp/none.out ]] || fail "orphan checker stays quiet when no orphans exist"
for mode in "" -y; do
run_orphan_checker $mode >"$test_tmp/none.out" 2>"$test_tmp/none.err"
[[ ! -s $test_tmp/none.out ]] || fail "orphan checker stays quiet when no orphans exist"
done
[[ ! -e $REMOVAL_LOG ]] || fail "orphan checker does not remove packages when no orphans exist"
pass "orphan checker stays quiet without orphans"
+7
View File
@@ -35,6 +35,9 @@ for step in "${steps[@]}"; do
cat >"$stub_bin/$step" <<'STUB'
#!/bin/bash
printf '%s unattended=%s\n' "${0##*/}" "${OMARCHY_UPDATE_UNATTENDED:-}" >>"$STEP_LOG"
if [[ ${0##*/} == "omarchy-update-orphan-pkgs" ]]; then
printf '%s\n' "$@" >"$STEP_LOG.orphan-args"
fi
[[ ${FAILING_STEP:-} != "${0##*/}" ]] || exit 1
STUB
chmod +x "$stub_bin/$step"
@@ -84,6 +87,8 @@ run_update -y || fail "an update where everything works reports a failure"
diff <(expected_steps) <(steps_run) >"$test_tmp/order" ||
fail "an update where everything works does not run every step in order" "$(cat "$test_tmp/order")"
pass "an update where every step works runs all of them, in order"
[[ $(cat "$test_tmp/steps.orphan-args") == "-y" ]] || fail "an unattended update approves orphan removal"
pass "an unattended update approves orphan removal"
grep -q '^omarchy-update-system-pkgs unattended=1$' "$test_tmp/steps" ||
fail "-y does not mark the update unattended"
@@ -93,6 +98,8 @@ diff <(expected_steps confirmed) <(steps_run) >"$test_tmp/order" ||
grep -q '^omarchy-update-system-pkgs unattended=$' "$test_tmp/steps" ||
fail "an update a person confirmed is treated as unattended"
pass "-y is what marks an update unattended, not the update itself"
[[ $(cat "$test_tmp/steps.orphan-args") == "-y" ]] || fail "a confirmed update approves orphan removal"
pass "a confirmed update approves orphan removal"
# Migrations ship with the packages the upgrade installs and are written against
# them. Running them against what is still on disk is the failure this ordering
+127
View File
@@ -0,0 +1,127 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
leaf="$ROOT/install/hardware/dell-xps13-ptl-speaker-firmware.sh"
migration="$ROOT/migrations/1791265613.sh"
grep -q 'run_logged .*hardware/dell-xps13-ptl-speaker-firmware.sh' "$ROOT/install/hardware/all.sh" ||
fail "hardware setup installs the Panther Lake XPS 13 firmware"
pass "hardware setup installs the Panther Lake XPS 13 firmware"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
mkdir -p "$test_tmp/bin"
cat >"$test_tmp/bin/omarchy-hw-match" <<'SH'
#!/bin/bash
[[ $TEST_PRODUCT_NAME == *"$1"* ]]
SH
cat >"$test_tmp/bin/omarchy-hw-intel-ptl" <<'SH'
#!/bin/bash
[[ $TEST_INTEL_PTL == "1" ]]
SH
cat >"$test_tmp/bin/sudo" <<'SH'
#!/bin/bash
if [[ $1 == "pacman" ]]; then
exec "$@"
fi
printf 'Unexpected privileged command: %s\n' "$*" >&2
exit 1
SH
cat >"$test_tmp/bin/pacman" <<'SH'
#!/bin/bash
if [[ $1 == "-Q" ]]; then
if [[ ${@: -1} == "linux-firmware-cirrus-dx13260" ]]; then
[[ -e $TEST_ALIAS_FILE ]] || exit 1
printf 'linux-firmware-cirrus-dx13260 20260810-1\n'
else
[[ -s $TEST_VERSION_FILE ]] || exit 1
printf 'linux-firmware-cirrus %s\n' "$(<"$TEST_VERSION_FILE")"
fi
else
printf 'pacman %s\n' "$*" >>"$TEST_LOG"
[[ $* == "-S --noconfirm --needed -- linux-firmware-cirrus-dx13260" ]] || exit 1
[[ ${TEST_INSTALL_FAILURE:-0} == "0" ]] || exit 1
touch "$TEST_ALIAS_FILE"
fi
SH
cat >"$test_tmp/bin/omarchy-state" <<'SH'
#!/bin/bash
printf 'state %s\n' "$*" >>"$TEST_LOG"
SH
chmod +x "$test_tmp/bin/"*
export PATH="$test_tmp/bin:$ROOT/bin:$PATH"
export TEST_LOG="$test_tmp/calls" TEST_VERSION_FILE="$test_tmp/version" TEST_ALIAS_FILE="$test_tmp/alias-installed"
export TEST_PRODUCT_NAME="XPS 13 DX13260" TEST_INTEL_PTL=1
install_call="pacman -S --noconfirm --needed -- linux-firmware-cirrus-dx13260"
export OMARCHY_PATH="$ROOT"
reset_fixture() {
: >"$TEST_LOG"
printf '%s' "$1" >"$TEST_VERSION_FILE"
rm -f "$TEST_ALIAS_FILE"
}
run_leaf() {
bash -eE -c 'source "$1"' bash "$leaf"
}
run_migration() {
bash -euo pipefail "$migration" >/dev/null
}
for model in "XPS 9350" "XPS 13 DX13261"; do
reset_fixture "20260810-2"
TEST_PRODUCT_NAME="$model" run_leaf
TEST_PRODUCT_NAME="$model" run_migration
[[ ! -s $TEST_LOG ]] || fail "other models receive no firmware repair"
done
reset_fixture "20260810-2"
TEST_INTEL_PTL=0 run_leaf
TEST_INTEL_PTL=0 run_migration
[[ ! -s $TEST_LOG ]] || fail "the Wildcat Lake variant receives no firmware repair"
pass "other models and the Wildcat Lake variant receive no firmware repair"
for version in "" "20260810-2" "20260810-3" "20260810-4" "20260910-2" "20260916-1" "1:20260810-2"; do
reset_fixture "$version"
run_leaf || fail "the alias package is installed during hardware setup"
[[ $(<"$TEST_LOG") == "$install_call" && $(<"$TEST_VERSION_FILE") == "$version" && -e $TEST_ALIAS_FILE ]] ||
fail "hardware setup installs the separate aliases without replacing stock firmware"
done
pass "hardware setup installs the package identity without replacing any stock firmware"
pass "hardware setup leaves reboot bookkeeping to the migration"
reset_fixture "20260810-2"
touch "$TEST_ALIAS_FILE"
run_leaf
[[ ! -s $TEST_LOG ]] || fail "installed aliases are idempotent on stock firmware"
pass "installed aliases are idempotent on stock firmware"
run_migration
[[ $(<"$TEST_LOG") == "state set reboot-required" ]] ||
fail "the migration requests a reboot even if hardware setup already installed the aliases"
pass "the migration requests a reboot even if hardware setup already installed the aliases"
reset_fixture "20260810-2"
if TEST_INSTALL_FAILURE=1 run_migration; then
fail "a failed firmware installation fails the migration"
fi
[[ $(<"$TEST_LOG") == "$install_call" && $(<"$TEST_VERSION_FILE") == "20260810-2" ]] ||
fail "a failed installation leaves the migration retryable without claiming success"
pass "a failed firmware installation fails the migration and remains retryable"
: >"$TEST_LOG"
run_migration
[[ $(<"$TEST_LOG") == "$install_call"$'\nstate set reboot-required' ]] ||
fail "retrying the migration installs the firmware and requests a reboot"
pass "retrying the migration installs the firmware and requests a reboot"
: >"$TEST_LOG"
run_migration
[[ $(<"$TEST_LOG") == "state set reboot-required" ]] ||
fail "a second user before reboot is prompted without reinstalling"
pass "a second user before reboot is prompted without reinstalling"