From 9d430a307969ec657e75b5d704683349491cca99 Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Tue, 18 Aug 2026 00:36:12 -0400 Subject: [PATCH] Finish Home and Phone settings cohesion --- .../dot/quickshell/config/HomePreferences.qml | 8 + .../quickshell/home-preferences-harness.qml | 1 + .../modules/settings/HomePhonePage.qml | 456 ++++++++---------- ...26-08-18-settings-home-phone-completion.md | 103 ++++ .../home-phone-settings-contract.sh | 8 +- tests/quickshell/home-preferences-contract.sh | 27 ++ 6 files changed, 358 insertions(+), 245 deletions(-) create mode 100644 docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md diff --git a/config/dot/quickshell/config/HomePreferences.qml b/config/dot/quickshell/config/HomePreferences.qml index fba3f10..4aa4650 100644 --- a/config/dot/quickshell/config/HomePreferences.qml +++ b/config/dot/quickshell/config/HomePreferences.qml @@ -82,6 +82,14 @@ Singleton { values.initialized = true; } + function resetHomeDefaults(): void { + persistTimer.stop(); + values.favorites = []; + values.initialized = false; + root.saveError = ""; + preferencesFile.writeAdapter(); + } + function isSelected(entityId: string): bool { for (var index = 0; index < values.favorites.length; index++) { if (values.favorites[index].id === entityId) { diff --git a/config/dot/quickshell/home-preferences-harness.qml b/config/dot/quickshell/home-preferences-harness.qml index eefbe15..be9ad63 100644 --- a/config/dot/quickshell/home-preferences-harness.qml +++ b/config/dot/quickshell/home-preferences-harness.qml @@ -13,6 +13,7 @@ ShellRoot { function alias(id: string, value: string): void { HomePreferences.setAlias(id, value); } function move(id: string, index: int): void { HomePreferences.move(id, index); } function remove(id: string): void { HomePreferences.remove(id); } + function reset(): void { HomePreferences.resetHomeDefaults(); } function status(): string { return JSON.stringify({ initialized: HomePreferences.initialized, diff --git a/config/dot/quickshell/modules/settings/HomePhonePage.qml b/config/dot/quickshell/modules/settings/HomePhonePage.qml index a88eac4..eae1bc3 100644 --- a/config/dot/quickshell/modules/settings/HomePhonePage.qml +++ b/config/dot/quickshell/modules/settings/HomePhonePage.qml @@ -2,9 +2,11 @@ import QtQuick import qs.config import qs.services -Item { +SettingsPage { id: root objectName: "home-phone-page" + title: "Home & Phone" + lede: "Choose what appears in Control Center and keep phone continuity close at hand." property string lightQuery: searchInput.text.trim().toLowerCase() @@ -41,274 +43,242 @@ Item { return "Home Assistant is unavailable"; } - Flickable { - anchors.fill: parent - clip: true - contentWidth: width - contentHeight: content.implicitHeight + 64 - boundsBehavior: Flickable.StopAtBounds + SettingsCard { + title: "Home Assistant" + subtitle: root.homeStatus() - Column { - id: content - width: parent.width - 68 - x: 34 - y: 30 - spacing: 16 + SettingRow { + label: "Light catalog" + detail: "Panama reads light state through the Home Assistant helper." + divider: false + controlWidth: 176 + + Row { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: 8 + + SettingsButton { + id: refreshButton + text: "Refresh" + activeFocusOnTab: true + border.width: activeFocus ? 2 : 1 + border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08) + onClicked: HomeAssistant.refresh() + Keys.onReturnPressed: HomeAssistant.refresh() + Keys.onSpacePressed: HomeAssistant.refresh() + } + + SettingsButton { + id: openHomeButton + text: "Open" + activeFocusOnTab: true + border.width: activeFocus ? 2 : 1 + border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08) + onClicked: HomeAssistant.open() + Keys.onReturnPressed: HomeAssistant.open() + Keys.onSpacePressed: HomeAssistant.open() + } + } + } + } + + SettingsCard { + title: "Control Center lights" + subtitle: HomeAssistant.selectedEntities.length === 0 + ? "Select the lights that belong on your shelf." + : `${Math.min(4, HomeAssistant.selectedEntities.length)} in Control Center · ${HomeAssistant.selectedEntities.length} selected` + + Text { + width: parent.width + visible: HomeAssistant.selectedEntities.length === 0 + text: "Choose lights below to build your Control Center shelf." + color: Theme.fgDim + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSize + wrapMode: Text.WordWrap + topPadding: 3 + bottomPadding: 13 + } + + GridView { + id: favoritesGrid + width: parent.width + height: Math.ceil(count / 2) * cellHeight + visible: count > 0 + interactive: false + clip: false + cellWidth: width / 2 + cellHeight: 116 + model: HomeAssistant.selectedEntities + + delegate: HomeFavoriteCard { + required property var modelData + width: GridView.view.cellWidth - 6 + height: 108 + favorite: ({ + id: modelData.id, + alias: modelData.name === modelData.sourceName ? "" : modelData.name + }) + sourceName: modelData.sourceName + featured: index < 4 + onAliasCommitted: (id, alias) => HomePreferences.setAlias(id, alias) + onMoveRequested: (id, targetIndex) => HomePreferences.move(id, targetIndex) + onRemoveRequested: id => HomePreferences.remove(id) + } + } + + Rectangle { + width: parent.width + height: 46 + visible: HomePreferences.saveError !== "" + radius: 9 + color: Theme.alpha(Theme.warn, 0.09) + border.width: 1 + border.color: Theme.alpha(Theme.warn, 0.24) Text { - text: "Home & Phone" - color: Theme.fg + anchors.left: parent.left + anchors.leftMargin: 12 + anchors.right: retryButton.left + anchors.rightMargin: 12 + anchors.verticalCenter: parent.verticalCenter + text: HomePreferences.saveError + color: Theme.warn font.family: Theme.fontFamily - font.pixelSize: 27 - font.weight: Font.DemiBold + font.pixelSize: Theme.fontSizeSmall + elide: Text.ElideRight } + SettingsButton { + id: retryButton + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.verticalCenter: parent.verticalCenter + text: "Retry" + activeFocusOnTab: true + border.width: activeFocus ? 2 : 1 + border.color: activeFocus ? Theme.warn : Theme.alpha(Theme.fg, 0.08) + onClicked: HomePreferences.retrySave() + Keys.onReturnPressed: HomePreferences.retrySave() + Keys.onSpacePressed: HomePreferences.retrySave() + } + } + } + + SettingsCard { + title: "Available lights" + subtitle: "Search the Home Assistant catalog by source name or entity ID." + + Rectangle { + width: parent.width + height: 38 + radius: 10 + color: Theme.alpha(Theme.fg, searchInput.activeFocus ? 0.08 : 0.05) + border.width: searchInput.activeFocus ? 2 : 1 + border.color: searchInput.activeFocus + ? Theme.alpha(Theme.accent, 0.72) + : Theme.alpha(Theme.fg, 0.065) + Text { - text: "Choose what appears in Control Center and keep phone continuity close at hand." + anchors.left: parent.left + anchors.leftMargin: 11 + anchors.verticalCenter: parent.verticalCenter + text: "\u{F0349}" color: Theme.fgDim + font.family: Theme.fontMono + font.pixelSize: 14 + } + + TextInput { + id: searchInput + anchors.left: parent.left + anchors.leftMargin: 36 + anchors.right: parent.right + anchors.rightMargin: 11 + anchors.verticalCenter: parent.verticalCenter + activeFocusOnTab: true + color: Theme.fg + selectionColor: Theme.accent + selectedTextColor: Theme.bgDark font.family: Theme.fontFamily font.pixelSize: Theme.fontSize - bottomPadding: 6 - } - - SettingsCard { - title: "Home Assistant" - subtitle: root.homeStatus() - - SettingRow { - label: "Light catalog" - detail: "Panama reads light state through the Home Assistant helper." - divider: false - controlWidth: 176 - - Row { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: 8 - - SettingsButton { - id: refreshButton - text: "Refresh" - activeFocusOnTab: true - border.width: activeFocus ? 2 : 1 - border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08) - onClicked: HomeAssistant.refresh() - Keys.onReturnPressed: HomeAssistant.refresh() - Keys.onSpacePressed: HomeAssistant.refresh() - } - - SettingsButton { - id: openHomeButton - text: "Open" - activeFocusOnTab: true - border.width: activeFocus ? 2 : 1 - border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08) - onClicked: HomeAssistant.open() - Keys.onReturnPressed: HomeAssistant.open() - Keys.onSpacePressed: HomeAssistant.open() - } - } - } - } - - SettingsCard { - title: "Control Center lights" - subtitle: HomeAssistant.selectedEntities.length === 0 - ? "Select the lights that belong on your shelf." - : `${Math.min(4, HomeAssistant.selectedEntities.length)} in Control Center · ${HomeAssistant.selectedEntities.length} selected` + clip: true Text { - width: parent.width - visible: HomeAssistant.selectedEntities.length === 0 - text: "Choose lights below to build your Control Center shelf." - color: Theme.fgDim - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSize - wrapMode: Text.WordWrap - topPadding: 3 - bottomPadding: 13 - } - - GridView { - id: favoritesGrid - width: parent.width - height: Math.ceil(count / 2) * cellHeight - visible: count > 0 - interactive: false - clip: false - cellWidth: width / 2 - cellHeight: 116 - model: HomeAssistant.selectedEntities - - delegate: HomeFavoriteCard { - required property var modelData - width: GridView.view.cellWidth - 6 - height: 108 - favorite: ({ - id: modelData.id, - alias: modelData.name === modelData.sourceName ? "" : modelData.name - }) - sourceName: modelData.sourceName - featured: index < 4 - onAliasCommitted: (id, alias) => HomePreferences.setAlias(id, alias) - onMoveRequested: (id, targetIndex) => HomePreferences.move(id, targetIndex) - onRemoveRequested: id => HomePreferences.remove(id) - } - } - - Rectangle { - width: parent.width - height: 46 - visible: HomePreferences.saveError !== "" - radius: 9 - color: Theme.alpha(Theme.warn, 0.09) - border.width: 1 - border.color: Theme.alpha(Theme.warn, 0.24) - - Text { - anchors.left: parent.left - anchors.leftMargin: 12 - anchors.right: retryButton.left - anchors.rightMargin: 12 - anchors.verticalCenter: parent.verticalCenter - text: HomePreferences.saveError - color: Theme.warn - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeSmall - elide: Text.ElideRight - } - - SettingsButton { - id: retryButton - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.verticalCenter: parent.verticalCenter - text: "Retry" - activeFocusOnTab: true - border.width: activeFocus ? 2 : 1 - border.color: activeFocus ? Theme.warn : Theme.alpha(Theme.fg, 0.08) - onClicked: HomePreferences.retrySave() - Keys.onReturnPressed: HomePreferences.retrySave() - Keys.onSpacePressed: HomePreferences.retrySave() - } + anchors.fill: parent + visible: searchInput.text === "" && !searchInput.activeFocus + text: "Search available lights" + color: Theme.fgMuted + font: searchInput.font + verticalAlignment: Text.AlignVCenter } } + } - SettingsCard { - title: "Available lights" - subtitle: "Search the Home Assistant catalog by source name or entity ID." + Column { + width: parent.width + visible: root.availableLights.length > 0 - Rectangle { + Repeater { + model: root.availableLights + + AvailableLightRow { + required property var modelData width: parent.width - height: 38 - radius: 10 - color: Theme.alpha(Theme.fg, searchInput.activeFocus ? 0.08 : 0.05) - border.width: searchInput.activeFocus ? 2 : 1 - border.color: searchInput.activeFocus - ? Theme.alpha(Theme.accent, 0.72) - : Theme.alpha(Theme.fg, 0.065) - - Text { - anchors.left: parent.left - anchors.leftMargin: 11 - anchors.verticalCenter: parent.verticalCenter - text: "\u{F0349}" - color: Theme.fgDim - font.family: Theme.fontMono - font.pixelSize: 14 - } - - TextInput { - id: searchInput - anchors.left: parent.left - anchors.leftMargin: 36 - anchors.right: parent.right - anchors.rightMargin: 11 - anchors.verticalCenter: parent.verticalCenter - activeFocusOnTab: true - color: Theme.fg - selectionColor: Theme.accent - selectedTextColor: Theme.bgDark - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSize - clip: true - - Text { - anchors.fill: parent - visible: searchInput.text === "" && !searchInput.activeFocus - text: "Search available lights" - color: Theme.fgMuted - font: searchInput.font - verticalAlignment: Text.AlignVCenter - } - } + entity: modelData + onAddRequested: id => HomePreferences.add(id) } + } + } - Column { - width: parent.width - visible: root.availableLights.length > 0 + Text { + width: parent.width + visible: root.availableLights.length === 0 + text: root.availableEmptyText + color: Theme.fgDim + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSize + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + topPadding: 18 + bottomPadding: 10 + } + } - Repeater { - model: root.availableLights + SettingsCard { + title: "Phone continuity" + subtitle: "Keep the Messages handoff independent from phone connectivity." - AvailableLightRow { - required property var modelData - width: parent.width - entity: modelData - onAddRequested: id => HomePreferences.add(id) - } - } - } + SettingRow { + label: "Messages" + detail: "Opens BlueBubbles" + divider: false + controlWidth: 204 + + Row { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: 12 Text { - width: parent.width - visible: root.availableLights.length === 0 - text: root.availableEmptyText - color: Theme.fgDim + anchors.verticalCenter: parent.verticalCenter + text: SystemSettings.bluebubblesAvailable ? "Installed" : "Unavailable" + color: SystemSettings.bluebubblesAvailable ? Theme.ok : Theme.fgMuted font.family: Theme.fontFamily - font.pixelSize: Theme.fontSize - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - topPadding: 18 - bottomPadding: 10 + font.pixelSize: Theme.fontSizeSmall } - } - SettingsCard { - title: "Phone continuity" - subtitle: "Keep the Messages handoff independent from phone connectivity." - - SettingRow { - label: "Messages" - detail: "Opens BlueBubbles" - divider: false - controlWidth: 204 - - Row { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: 12 - - Text { - anchors.verticalCenter: parent.verticalCenter - text: SystemSettings.bluebubblesAvailable ? "Installed" : "Unavailable" - color: SystemSettings.bluebubblesAvailable ? Theme.ok : Theme.fgMuted - font.family: Theme.fontFamily - font.pixelSize: Theme.fontSizeSmall - } - - SettingsButton { - id: openBlueBubblesButton - text: "Open" - enabled: SystemSettings.bluebubblesAvailable - activeFocusOnTab: enabled - border.width: activeFocus ? 2 : 1 - border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08) - onClicked: SystemSettings.openApplication("bluebubbles") - Keys.onReturnPressed: if (enabled) SystemSettings.openApplication("bluebubbles") - Keys.onSpacePressed: if (enabled) SystemSettings.openApplication("bluebubbles") - } - } + SettingsButton { + id: openBlueBubblesButton + text: "Open" + enabled: SystemSettings.bluebubblesAvailable + activeFocusOnTab: enabled + border.width: activeFocus ? 2 : 1 + border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08) + onClicked: SystemSettings.openApplication("bluebubbles") + Keys.onReturnPressed: if (enabled) SystemSettings.openApplication("bluebubbles") + Keys.onSpacePressed: if (enabled) SystemSettings.openApplication("bluebubbles") } } } diff --git a/docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md b/docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md new file mode 100644 index 0000000..f92c052 --- /dev/null +++ b/docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md @@ -0,0 +1,103 @@ +# Settings Home & Phone Completion Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Finish the Home & Phone Settings page on Panama's shared Settings vocabulary and give the global reset path a named, durable Home preference API. + +**Architecture:** `HomePhonePage` adopts `SettingsPage` for the shared scrolling/title/lede scaffold while retaining its specialized catalog, reorder, alias, and phone controls. `HomePreferences.resetHomeDefaults()` becomes the sole Home-store reset boundary: it returns the store to fresh-install state and writes immediately so `SystemSettings.restoreDefaults()` can call it without mutating aliases. + +**Tech Stack:** Quickshell 0.3 QML, QtQuick, Bash contract tests, Hyprland. + +**Spec:** `docs/superpowers/specs/2026-08-17-panama-cohesion-design.md` + +## Global Constraints + +- Do not touch `SystemSettings.qml`, `PreferenceSchema.qml`, keybinds, or Claude's shared row implementations in this branch. +- Preserve ordered Home favorites, aliases, first-four Control Center badges, search, drag and keyboard reorder, retry state, Home Assistant status copy, and BlueBubbles availability behavior. +- Automated tests must not toggle or dim a real light and must not launch BlueBubbles. +- New behavior follows red-green TDD; fixture and state directories remain isolated from the live desktop. +- No mock phase and no new visual direction: this is cohesion work against the already-approved design. + +--- + +### Task 1: Shared Home & Phone page and named reset boundary + +**Files:** +- Modify: `config/dot/quickshell/config/HomePreferences.qml` +- Modify: `config/dot/quickshell/home-preferences-harness.qml` +- Modify: `config/dot/quickshell/modules/settings/HomePhonePage.qml` +- Modify only if required for shared vocabulary compatibility: `config/dot/quickshell/modules/settings/HomeFavoriteCard.qml` +- Modify only if required for shared vocabulary compatibility: `config/dot/quickshell/modules/settings/AvailableLightRow.qml` +- Modify: `tests/quickshell/home-preferences-contract.sh` +- Modify: `tests/quickshell/home-phone-settings-contract.sh` + +**Interfaces:** +- Consumes: `SettingsPage { title; lede; default content }`, existing `SettingsCard`, `SettingRow`, `ActionRow`, `TextRow`, `HomeAssistant`, `SystemSettings.bluebubblesAvailable`, and writable `HomePreferences` adapter state. +- Produces: `HomePreferences.resetHomeDefaults(): void`, which sets `favorites` to `[]`, sets `initialized` to `false`, clears stale save error state, and invokes `preferencesFile.writeAdapter()` immediately after stopping the debounce timer. + +- [ ] **Step 1: Write failing contracts** + +Add `reset()` to the isolated `home-pref-test` IPC harness. Extend `home-preferences-contract.sh` to seed aliases/order, invoke reset, and require both IPC state and `panama-home.json` to become exactly `{"initialized":false,"favorites":[]}` without waiting for the 180 ms debounce interval. Extend `home-phone-settings-contract.sh` to require `SettingsPage {`, `title: "Home & Phone"`, and the existing lede through `lede:`, while rejecting the copied root `Flickable` scaffold. + +- [ ] **Step 2: Run contracts to verify RED** + +```bash +tests/quickshell/home-preferences-contract.sh +tests/quickshell/home-phone-settings-contract.sh +``` + +Expected: the preference contract fails because `reset` is missing; the page contract fails because the page still owns a copied `Flickable` scaffold. + +- [ ] **Step 3: Implement the reset API and shared page scaffold** + +Implement this public boundary in `HomePreferences.qml`: + +```qml +function resetHomeDefaults(): void { + persistTimer.stop(); + values.favorites = []; + values.initialized = false; + root.saveError = ""; + preferencesFile.writeAdapter(); +} +``` + +Replace the `HomePhonePage` root `Item` plus nested `Flickable`/title/lede scaffold with: + +```qml +SettingsPage { + id: root + objectName: "home-phone-page" + title: "Home & Phone" + lede: "Choose what appears in Control Center and keep phone continuity close at hand." + // Existing SettingsCard content remains in order. +} +``` + +Use shared `ActionRow` or `TextRow` only where their single-action/read-only contracts preserve all current status and accessibility behavior. Keep specialized rows when the shared primitive would lose information. + +- [ ] **Step 4: Run focused contracts to GREEN** + +```bash +tests/quickshell/home-preferences-contract.sh +tests/quickshell/home-phone-settings-contract.sh +tests/quickshell/settings-pages-contract.sh +tests/quickshell/settings-rows-contract.sh +tests/quickshell/settings-commit-reset-contract.sh +``` + +Expected: every command exits 0; no test launches BlueBubbles or changes a real Home Assistant entity. + +- [ ] **Step 5: Commit** + +```bash +git add config/dot/quickshell/config/HomePreferences.qml \ + config/dot/quickshell/home-preferences-harness.qml \ + config/dot/quickshell/modules/settings/HomePhonePage.qml \ + config/dot/quickshell/modules/settings/HomeFavoriteCard.qml \ + config/dot/quickshell/modules/settings/AvailableLightRow.qml \ + tests/quickshell/home-preferences-contract.sh \ + tests/quickshell/home-phone-settings-contract.sh \ + docs/superpowers/plans/2026-08-18-settings-home-phone-completion.md +git commit -m "Finish Home and Phone settings cohesion" +``` diff --git a/tests/quickshell/home-phone-settings-contract.sh b/tests/quickshell/home-phone-settings-contract.sh index 2513dbe..c9bd64d 100755 --- a/tests/quickshell/home-phone-settings-contract.sh +++ b/tests/quickshell/home-phone-settings-contract.sh @@ -80,8 +80,12 @@ system_settings="$repo_dir/config/dot/quickshell/services/SystemSettings.qml" [[ -f "$home_page" ]] || fail 'HomePhonePage.qml is missing' [[ -f "$favorite_card" ]] || fail 'HomeFavoriteCard.qml is missing' [[ -f "$available_row" ]] || fail 'AvailableLightRow.qml is missing' -assert_contains 'text: "Home & Phone"' "$home_page" -assert_contains 'text: "Choose what appears in Control Center and keep phone continuity close at hand."' "$home_page" +assert_contains 'SettingsPage {' "$home_page" +assert_contains 'title: "Home & Phone"' "$home_page" +assert_contains 'lede: "Choose what appears in Control Center and keep phone continuity close at hand."' "$home_page" +if rg -q '^\s*Flickable \{' "$home_page"; then + fail 'HomePhonePage.qml still owns a copied Flickable scaffold' +fi assert_contains 'Connected · ' "$home_page" assert_contains 'Last update unavailable · showing saved controls' "$home_page" assert_contains 'Authentication required' "$home_page" diff --git a/tests/quickshell/home-preferences-contract.sh b/tests/quickshell/home-preferences-contract.sh index 4eeedc7..3f12f16 100755 --- a/tests/quickshell/home-preferences-contract.sh +++ b/tests/quickshell/home-preferences-contract.sh @@ -83,6 +83,21 @@ wait_for_file_content() { fail 'preferences file did not contain the complete atomic update' } +wait_for_reset_file_content() { + local expected='{"initialized":false,"favorites":[]}' + local state_file="" + + for _ in $(seq 1 18); do + state_file="$(find "$state_home" -name panama-home.json -print -quit)" + if [[ -n "$state_file" ]] \ + && jq -e --argjson expected "$expected" '. == $expected' "$state_file" >/dev/null; then + return + fi + sleep 0.01 + done + fail 'reset did not persist the default Home state before the debounce interval' +} + # A leading JSON whitespace prevents qs from expanding the array into IPC # positional arguments; JSON.parse() intentionally accepts that whitespace. initial_ids=' ["light.kitchen","light.hall","light.desk"]' @@ -90,6 +105,7 @@ expected='{"initialized":true,"favorites":[{"id":"light.desk","alias":""},{"id": expected_file='{"initialized":true,"favorites":[{"id":"light.desk","alias":""},{"id":"light.kitchen","alias":"Island"}]}' empty_expected='{"initialized":true,"favorites":[],"saveError":""}' empty_file='{"initialized":true,"favorites":[]}' +reset_expected='{"initialized":false,"favorites":[],"saveError":""}' start_harness qs_for_harness ipc call home-pref-test initialize "$initial_ids" >/dev/null @@ -99,9 +115,20 @@ qs_for_harness ipc call home-pref-test remove light.hall >/dev/null wait_for_status "$expected" wait_for_file_content "$expected_file" +qs_for_harness ipc call home-pref-test reset >/dev/null +wait_for_status "$reset_expected" +wait_for_reset_file_content + stop_harness start_harness +wait_for_status "$reset_expected" + +qs_for_harness ipc call home-pref-test initialize "$initial_ids" >/dev/null +qs_for_harness ipc call home-pref-test alias light.kitchen ' Island ' >/dev/null +qs_for_harness ipc call home-pref-test move light.desk 0 >/dev/null +qs_for_harness ipc call home-pref-test remove light.hall >/dev/null wait_for_status "$expected" +wait_for_file_content "$expected_file" qs_for_harness ipc call home-pref-test remove light.desk >/dev/null qs_for_harness ipc call home-pref-test remove light.kitchen >/dev/null