diff --git a/config/dot/quickshell/services/HomeAssistant.qml b/config/dot/quickshell/services/HomeAssistant.qml index 4a21782..f7e0eea 100644 --- a/config/dot/quickshell/services/HomeAssistant.qml +++ b/config/dot/quickshell/services/HomeAssistant.qml @@ -168,6 +168,8 @@ Singleton { } function enqueueAction(action: var): void { + if (root.fixtureTransitionDraining) + return; if (!action || (action.kind !== "toggle" && action.kind !== "brightness")) return; if (typeof action.entityId !== "string" || action.entityId === "" || root.isBusy(action.entityId)) diff --git a/config/dot/quickshell/shell.qml b/config/dot/quickshell/shell.qml index 2e3f175..e17c1ed 100644 --- a/config/dot/quickshell/shell.qml +++ b/config/dot/quickshell/shell.qml @@ -276,6 +276,9 @@ ShellRoot { entityErrors: HomeAssistant.entityErrors, actionProcessRunning: HomeAssistant.actionProcessRunning, actionStreamFinished: HomeAssistant.actionStreamFinished, + fixtureTransitionDraining: HomeAssistant.fixtureTransitionDraining, + queuedActionCount: HomeAssistant.actionQueue.length, + actionActive: HomeAssistant.activeAction !== null, lastError: HomeAssistant.lastError }); } diff --git a/tests/quickshell/control-center-services-contract.sh b/tests/quickshell/control-center-services-contract.sh index 8355574..9e108d4 100755 --- a/tests/quickshell/control-center-services-contract.sh +++ b/tests/quickshell/control-center-services-contract.sh @@ -3,10 +3,30 @@ set -euo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -config_path="$repo_dir/config/dot/quickshell" state_home="$(mktemp -d /tmp/panama-control-center-state.XXXXXX)" +source_config_path="$repo_dir/config/dot/quickshell" +config_path="$state_home/quickshell" +helper_log="$state_home/home-helper.log" shell_log="$state_home/quickshell.log" +: >"$helper_log" +cp -a "$source_config_path" "$config_path" +cat >"$config_path/scripts/panama-home-assistant" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +printf '%s\n' "$*" >>"$PANAMA_HOME_HELPER_LOG" +case "${1:-}" in + catalog) + printf '%s\n' '{"ok":false,"error":"test-helper"}' + ;; + toggle|brightness) + printf '%s\n' '{"ok":true}' + ;; +esac +EOF +chmod +x "$config_path/scripts/panama-home-assistant" + fail() { printf 'Control Center services contract: %s\n' "$1" >&2 exit 1 @@ -14,6 +34,7 @@ fail() { qs_for_test() { QS_CONFIG_PATH="$config_path" XDG_STATE_HOME="$state_home" \ + PANAMA_HOME_HELPER_LOG="$helper_log" \ qs -p "$config_path" "$@" } @@ -220,12 +241,39 @@ wait_for_home_status ' qs_for_test ipc call home-assistant fixture process-no-output >/dev/null qs_for_test ipc call home-assistant fixture process-slow-actions >/dev/null qs_for_test ipc call home-assistant brightness light.fixture_desk 57 >/dev/null -wait_for_home_status ' - .phase == "ready" and +jq -e ' + .fixture == true and + .fixtureTransitionDraining == true and .busy == false and .busyEntityIds == [] and .pendingBrightness == {} and .entityErrors == {} and + .queuedActionCount == 0 and + .actionActive == false and + .actionProcessRunning == false and + (.entities[] | + select(.id == "light.fixture_desk") | + .active == true and .brightnessPct == 24) +' <<<"$(qs_for_test ipc call home-assistant status)" >/dev/null \ + || fail 'nested fixture transition accepted an action during its drain' +wait_for_home_status ' + .fixture == true and + .fixtureTransitionDraining == false and + .busy == false and + .queuedActionCount == 0 and + .actionActive == false and + .actionProcessRunning == false +' 'nested fixture transition did not install the latest stable fixture' +qs_for_test ipc call home-assistant brightness light.fixture_desk 57 >/dev/null +wait_for_home_status ' + .phase == "ready" and + .fixtureTransitionDraining == false and + .busy == false and + .busyEntityIds == [] and + .pendingBrightness == {} and + .entityErrors == {} and + .queuedActionCount == 0 and + .actionActive == false and (.entities[] | select(.id == "light.fixture_living") | .active == false and .brightnessPct == 36) and @@ -234,6 +282,45 @@ wait_for_home_status ' .active == true and .brightnessPct == 57) ' 'nested fixture transitions released the drain or corrupted the latest action' +qs_for_test ipc call home-assistant fixture process-delayed-exit >/dev/null +qs_for_test ipc call home-assistant brightness light.fixture_living 88 >/dev/null +wait_for_home_status ' + .fixture == true and + .busyEntityIds == ["light.fixture_living"] and + .pendingBrightness["light.fixture_living"] == 88 and + .actionProcessRunning == false and + .actionStreamFinished == true +' 'reset-to-live setup did not reach its process drain window' +qs_for_test ipc call home-assistant reset >/dev/null +qs_for_test ipc call home-assistant toggle light.fixture_hall >/dev/null +qs_for_test ipc call home-assistant brightness light.fixture_living 63 >/dev/null +jq -e ' + .fixture == true and + .fixtureTransitionDraining == true and + .busy == false and + .busyEntityIds == [] and + .pendingBrightness == {} and + .entityErrors == {} and + .queuedActionCount == 0 and + .actionActive == false and + .actionProcessRunning == false +' <<<"$(qs_for_test ipc call home-assistant status)" >/dev/null \ + || fail 'reset-to-live drain accepted an action from the old fixture' +wait_for_home_status ' + .fixture == false and + .fixtureTransitionDraining == false and + .busy == false and + .busyEntityIds == [] and + .pendingBrightness == {} and + .entityErrors == {} and + .queuedActionCount == 0 and + .actionActive == false and + .actionProcessRunning == false +' 'reset-to-live left stale fixture action state or started a replacement process' +if rg '^(toggle|brightness)( |$)' "$helper_log" >&2; then + fail 'reset-to-live issued a stale fixture action to the live helper' +fi + qs_for_test ipc call home-assistant fixture missing-selected >/dev/null jq -e ' .fixture == true and