From 1a93a788fab6b21c834d654a87ef3b417bdfbf56 Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Tue, 18 Aug 2026 15:09:50 -0400 Subject: [PATCH] Verify settings search routing --- tests/quickshell/search-routing-contract.sh | 100 ++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 tests/quickshell/search-routing-contract.sh diff --git a/tests/quickshell/search-routing-contract.sh b/tests/quickshell/search-routing-contract.sh new file mode 100755 index 0000000..c49605f --- /dev/null +++ b/tests/quickshell/search-routing-contract.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +# A search result must open the page that actually contains the setting. +# +# Every schema group routes to one page in services/SettingsSearch.qml, and the +# ownership rule in modules/settings/README.md derives a setting's owner from +# that route. Nothing checked the two agreed, and two groups had drifted: +# +# weather routed to Appearance while every weather control lived on Home, so +# searching "temperature unit" opened a page without it. +# +# vitals routed to Appearance, but the refresh interval sat on Home while the +# toggles it governs sat on Appearance -- one concept, two pages, which is +# precisely what the ownership rule forbids. +# +# Neither is visible from the code: each page is coherent on its own, and only +# following a search result reveals the mismatch. +# +# Groups whose settings are driven by bespoke UI rather than schema-bound rows +# are skipped, because there is nothing to locate. + +set -uo pipefail + +repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +schema="$repo_dir/config/dot/quickshell/config/PreferenceSchema.qml" +search="$repo_dir/config/dot/quickshell/services/SettingsSearch.qml" +pages_dir="$repo_dir/config/dot/quickshell/modules/settings" + +fail() { + printf 'search routing contract: %s\n' "$1" >&2 + exit 1 +} + +routes="$(grep -oE '"[a-zA-Z]+": "[a-z-]+"' "$search" | tr -d '"' | tr ':' ' ')" +[[ -n "$routes" ]] || fail 'no group routes found -- this contract is not reading SettingsSearch correctly' + +# page id -> Page component file, as SettingsShell maps them. +page_file() { + case "$1" in + home) printf 'HomePage.qml' ;; + appearance) printf 'AppearancePage.qml' ;; + displays) printf 'DisplaysPage.qml' ;; + connectivity) printf 'ConnectivityPage.qml' ;; + home-phone) printf 'HomePhonePage.qml' ;; + desktop) printf 'DesktopPage.qml' ;; + sound) printf 'SoundPage.qml' ;; + notifications) printf 'NotificationsPage.qml' ;; + screen-intelligence) printf 'ScreenIntelligencePage.qml' ;; + shortcuts) printf 'ShortcutsPage.qml' ;; + mouse) printf 'MousePage.qml' ;; + privacy) printf 'PrivacyPage.qml' ;; + region) printf 'RegionPage.qml' ;; + accounts) printf 'OnlineAccountsPage.qml' ;; + accessibility) printf 'AccessibilityPage.qml' ;; + power) printf 'PowerPage.qml' ;; + datetime) printf 'DateTimePage.qml' ;; + applications) printf 'ApplicationsPage.qml' ;; + services) printf 'HealthPage.qml' ;; + about) printf 'AboutPage.qml' ;; + *) printf '' ;; + esac +} + +violations=0 +checked=0 + +while read -r group page; do + [[ -n "$group" && -n "$page" ]] || continue + + target="$(page_file "$page")" + [[ -n "$target" ]] || fail "group \"$group\" routes to \"$page\", which is not a known page" + [[ -r "$pages_dir/$target" ]] || fail "group \"$group\" routes to \"$page\" but $target does not exist" + + # Keys belonging to this group. + keys="$(awk -v g="\"$group\"" ' + /key: "/ { match($0, /key: "[a-zA-Z]+"/); k = substr($0, RSTART+6, RLENGTH-7) } + $0 ~ "group: " g { if (k != "") print k; k = "" } + ' "$schema" | sort -u)" + + while read -r key; do + [[ -n "$key" ]] || continue + + # Only settings rendered as schema-bound rows can be located at all. + homes="$(grep -rl "setting: \"$key\"" "$pages_dir"/*Page.qml 2>/dev/null | xargs -n1 basename 2>/dev/null || true)" + [[ -n "$homes" ]] || continue + + checked=$((checked + 1)) + grep -qx "$target" <<<"$homes" && continue + + printf ' %s (group "%s") routes to %s but appears only on: %s\n' \ + "$key" "$group" "$page" "$(tr '\n' ' ' <<<"$homes")" >&2 + violations=$((violations + 1)) + done <<<"$keys" +done <<<"$routes" + +if (( violations > 0 )); then + fail "$violations setting(s) route to a page that does not contain them, so searching for them opens the wrong page" +fi + +printf 'search routing contract: PASS (%d routed settings)\n' "$checked"