diff --git a/.trellis/spec/frontend/component-guidelines.md b/.trellis/spec/frontend/component-guidelines.md index 4239663..44812e9 100644 --- a/.trellis/spec/frontend/component-guidelines.md +++ b/.trellis/spec/frontend/component-guidelines.md @@ -46,6 +46,45 @@ Questions to answer: ## Accessibility +### Progressive disclosure for troubleshooting controls + +Settings pages must not present routine preferences, diagnostic evidence, and +host recovery as peer actions. Keep the common local action directly visible +and place support-only controls in one native `
` disclosure. + +- The collapsed state exposes one common action plus one descriptive summary. +- Diagnostic preview/export remain inside the disclosure. +- Host check/recovery buttons render only when a workspace is authorized. + Before authorization, show the prerequisite as status text instead of + disabled controls. +- Do not show an idle host status such as "not checked". Announce only active + checking, ready, or error results after the user requests them. +- Preserve a light, unframed hierarchy. A divider and chevron are sufficient; + do not turn the advanced region into another card. +- Cover collapsed desktop/mobile geometry and both authorization branches in + tests. + +Wrong: + +```tsx + + + + + +``` + +Correct: + +```tsx + +
+ Diagnostics and recovery + + {workspace ? : } +
+``` + ### Identity icons that reveal a panel action When a dock header icon doubles as the affordance for collapsing that dock: diff --git a/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/check.jsonl b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/check.jsonl new file mode 100644 index 0000000..f07603f --- /dev/null +++ b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/check.jsonl @@ -0,0 +1,2 @@ +{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "Review focused tests, lint, build, and dependency-neutral frontend changes."} +{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Verify accessibility and stable settings control structure."} diff --git a/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/implement.jsonl b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/implement.jsonl new file mode 100644 index 0000000..69d0d9a --- /dev/null +++ b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/implement.jsonl @@ -0,0 +1,2 @@ +{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Preserve accessible disclosure and button conventions in the settings UI."} +{"file": ".trellis/spec/frontend/agent-control-safety.md", "reason": "Keep host recovery capability and authorization boundaries truthful while changing presentation."} diff --git a/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/prd.md b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/prd.md new file mode 100644 index 0000000..8a53e55 --- /dev/null +++ b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/prd.md @@ -0,0 +1,26 @@ +# Simplify local recovery settings UX + +## Goal + +Reduce cognitive load in Settings > Updates & Support by progressively disclosing diagnostics and host recovery actions. + +## Requirements + +- Keep the common UI-reset action directly available in Settings > Updates & Support. +- Move diagnostic preview/export and host check/recovery behind one collapsed advanced disclosure. +- Do not render disabled host action buttons when no workspace is authorized; explain the prerequisite inside the disclosure instead. +- Keep all existing recovery capabilities, redaction behavior, and project-data safety guarantees unchanged. +- Preserve keyboard accessibility, status announcements, and localized copy. + +## Acceptance Criteria + +- [ ] The default recovery section presents one direct action and one advanced disclosure instead of five peer actions. +- [ ] Diagnostic preview and export remain available after expanding the disclosure. +- [ ] Authorized workspaces can still check and recover the host, with current progress/status feedback. +- [ ] Unauthorized workspaces see a concise prerequisite message and no disabled host action buttons. +- [ ] UI reset still clears only the existing interface preference keys and confirms success. +- [ ] Focused tests, localization extraction/compilation, lint, type checking, and the Agent contract validation pass. + +## Notes + +- This is a lightweight presentation and progressive-disclosure change; no recovery protocol or persistence contract changes are intended. diff --git a/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/task.json b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/task.json new file mode 100644 index 0000000..e7c2b3a --- /dev/null +++ b/.trellis/tasks/archive/2026-07/07-24-simplify-local-recovery-settings/task.json @@ -0,0 +1,26 @@ +{ + "id": "simplify-local-recovery-settings", + "name": "simplify-local-recovery-settings", + "title": "Simplify local recovery settings UX", + "description": "Reduce cognitive load in Settings > Updates & Support by progressively disclosing diagnostics and host recovery actions.", + "status": "completed", + "dev_type": null, + "scope": null, + "package": null, + "priority": "P1", + "creator": "tseka", + "assignee": "tseka", + "createdAt": "2026-07-24", + "completedAt": "2026-07-24", + "branch": null, + "base_branch": "fix/simplify-local-recovery-settings", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [], + "notes": "", + "meta": {} +} \ No newline at end of file diff --git a/.trellis/workspace/tseka/index.md b/.trellis/workspace/tseka/index.md index 1eefaf0..25f086c 100644 --- a/.trellis/workspace/tseka/index.md +++ b/.trellis/workspace/tseka/index.md @@ -8,7 +8,7 @@ - **Active File**: `journal-1.md` -- **Total Sessions**: 28 +- **Total Sessions**: 29 - **Last Active**: 2026-07-24 @@ -19,7 +19,7 @@ | File | Lines | Status | |------|-------|--------| -| `journal-1.md` | ~955 | Active | +| `journal-1.md` | ~988 | Active | --- @@ -29,6 +29,7 @@ | # | Date | Title | Commits | Branch | |---|------|-------|---------|--------| +| 29 | 2026-07-24 | Simplify troubleshooting recovery UX | `cb459e9` | `fix/simplify-local-recovery-settings` | | 28 | 2026-07-24 | Release and install Cutout v0.1.7 | `13d4eda` | `chore/archive-release-install-v0-1-7` | | 27 | 2026-07-24 | Fix duplicate preparation projection | `2f84034` | `fix/preparing-run-duplicate-projection` | | 26 | 2026-07-23 | Release and install Cutout v0.1.6 | `ca28859b8a9a25e73fa9fb7c3cc703b4489f2091` | `chore/archive-release-install-v0-1-6` | diff --git a/.trellis/workspace/tseka/journal-1.md b/.trellis/workspace/tseka/journal-1.md index eed6436..17bcc09 100644 --- a/.trellis/workspace/tseka/journal-1.md +++ b/.trellis/workspace/tseka/journal-1.md @@ -953,3 +953,36 @@ Published the single-active-surface preparation fix as the atomic four-platform ### Next Steps - None - task complete + + +## Session 29: Simplify troubleshooting recovery UX + +**Date**: 2026-07-24 +**Task**: Simplify troubleshooting recovery UX +**Branch**: `fix/simplify-local-recovery-settings` + +### Summary + +Reduced Settings recovery cognitive load to one direct UI reset plus a lightweight diagnostics disclosure, hid unauthorized host actions, localized the new hierarchy, added component and desktop/mobile visual coverage, and captured the convention in frontend specs. + +### Main Changes + +- Detailed change bullets were not supplied; see the summary above. + +### Git Commits + +| Hash | Message | +|------|---------| +| `cb459e9` | (see git log) | + +### Testing + +- Validation was not recorded for this session. + +### Status + +[OK] **Completed** + +### Next Steps + +- None - task complete diff --git a/src/components/settings/sections/GeneralSection.recovery.test.ts b/src/components/settings/sections/GeneralSection.recovery.test.ts deleted file mode 100644 index 09adfbe..0000000 --- a/src/components/settings/sections/GeneralSection.recovery.test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { readFileSync } from 'node:fs' -import { join } from 'node:path' -import { describe,expect,it } from 'vitest' - -describe('Local recovery settings entry',()=>{ - const source=readFileSync(join(process.cwd(),'src/components/settings/sections/RecoverySection.tsx'),'utf8') - it('exposes only local UI reset and redacted diagnostic preview/export',()=>{expect(source).toContain('Local recovery');expect(source).toContain('Reset UI state');expect(source).toContain('Preview diagnostics');expect(source).toContain('Export diagnostics');expect(source).toContain('Project data is not deleted.');expect(source).not.toMatch(/remote telemetry|OAuth|cloud sync/i)}) -}) diff --git a/src/components/settings/sections/RecoverySection.test.tsx b/src/components/settings/sections/RecoverySection.test.tsx new file mode 100644 index 0000000..2fa6281 --- /dev/null +++ b/src/components/settings/sections/RecoverySection.test.tsx @@ -0,0 +1,88 @@ +import { createElement } from "react"; +import { renderToStaticMarkup } from "react-dom/server"; +import { setupI18n } from "@lingui/core"; +import { I18nProvider } from "@lingui/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const workspace = vi.hoisted(() => ({ + get: vi.fn<() => { handle: string; label?: string } | undefined>(), +})); + +vi.mock("@/platform/authorized-workspace", () => ({ + getAuthorizedWorkspace: workspace.get, + subscribeAuthorizedWorkspace: vi.fn(() => () => undefined), +})); + +import { RecoverySection } from "./RecoverySection"; + +const i18n = setupI18n(); +i18n.loadAndActivate({ locale: "en", messages: {} }); + +function renderRecoverySection() { + const html = renderToStaticMarkup( + createElement( + I18nProvider, + { i18n }, + createElement(RecoverySection), + ), + ); + const document = new DOMParser().parseFromString(html, "text/html"); + const section = document.querySelector("section"); + const advanced = section?.querySelector("details"); + if (!section || !advanced) { + throw new Error("Recovery disclosure was not rendered"); + } + return { section, advanced }; +} + +function buttonLabels(root: ParentNode) { + return [...root.querySelectorAll("button")].map((button) => + button.textContent?.trim(), + ); +} + +describe("RecoverySection", () => { + beforeEach(() => workspace.get.mockReturnValue(undefined)); + + it("keeps one common action visible and progressively discloses advanced tools", () => { + const { section, advanced } = renderRecoverySection(); + const directButtons = [...section.querySelectorAll("button")].filter( + (button) => !advanced.contains(button), + ); + + expect(directButtons.map((button) => button.textContent?.trim())).toEqual([ + "Reset UI state", + ]); + expect(section.textContent).toContain("Troubleshooting"); + expect(advanced.open).toBe(false); + expect(advanced.querySelector("summary")?.textContent).toContain( + "Diagnostics and recovery", + ); + expect(buttonLabels(advanced)).toEqual([ + "Preview diagnostics", + "Export diagnostics", + ]); + expect(advanced.textContent).toContain( + "Authorize a workspace before using host recovery.", + ); + expect(section.textContent).toContain("Project data is not deleted."); + }); + + it("keeps host actions available after workspace authorization", () => { + workspace.get.mockReturnValue({ + handle: "workspace.opaque", + label: "Authorized workspace", + }); + + const { advanced } = renderRecoverySection(); + + expect(buttonLabels(advanced)).toEqual([ + "Preview diagnostics", + "Export diagnostics", + "Check host", + "Recover host", + ]); + expect(advanced.querySelectorAll("button[disabled]")).toHaveLength(0); + expect(advanced.querySelector('[role="status"]')).toBeNull(); + }); +}); diff --git a/src/components/settings/sections/RecoverySection.tsx b/src/components/settings/sections/RecoverySection.tsx index 1824b05..2813a7e 100644 --- a/src/components/settings/sections/RecoverySection.tsx +++ b/src/components/settings/sections/RecoverySection.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { Download, RotateCcw, Stethoscope } from "lucide-react"; +import { ChevronRight, Download, RotateCcw, Stethoscope } from "lucide-react"; import { Trans, useLingui } from "@lingui/react/macro"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; @@ -18,7 +18,7 @@ import { import { WORKSPACE_NAVIGATION_KEY } from "@/workspace/navigation"; import { PRODUCT_VERSION } from "@/product-version"; -type HostStatus = "unavailable" | "checking" | "ready" | "error"; +type HostStatus = "unavailable" | "idle" | "checking" | "ready" | "error"; export function RecoverySection() { const { t } = useLingui(); @@ -27,19 +27,19 @@ export function RecoverySection() { AuthorizedWorkspace | undefined >(getAuthorizedWorkspace); const [hostStatus, setHostStatus] = useState( - getAuthorizedWorkspace() ? "checking" : "unavailable", + getAuthorizedWorkspace() ? "idle" : "unavailable", ); useEffect( () => subscribeAuthorizedWorkspace((workspace) => { setAuthorizedWorkspace(workspace); - setHostStatus(workspace ? "checking" : "unavailable"); + setHostStatus(workspace ? "idle" : "unavailable"); }), [], ); - const hostStatusText: Record = { + const hostStatusText: Partial> = { unavailable: t({ id: "settings.recovery.host_unauthorized", message: "Authorize a workspace before using host recovery.", @@ -54,6 +54,7 @@ export function RecoverySection() { message: "Host recovery could not be completed.", }), }; + const currentHostStatusText = hostStatusText[hostStatus]; const diagnosticBundle = () => { const generatedAt = new Date().toISOString(); return createDiagnosticBundle({ @@ -100,14 +101,15 @@ export function RecoverySection() { return (

- Local recovery + Troubleshooting

- Reset interface preferences or export a redacted local diagnostic bundle. Project data is not deleted. + Reset interface preferences or export a redacted local diagnostic + bundle. Project data is not deleted.

-
+
- - - -
-

- Host recovery:{" "} - {hostStatusText[hostStatus]} -

- {diagnosticsPreview ? ( -
-          {diagnosticsPreview}
-        
- ) : null} +
+ + + + Diagnostics and recovery + + +
+
+ + +
+ +
+ {authorizedWorkspace ? ( + <> +
+ + +
+ {currentHostStatusText ? ( +

+ {currentHostStatusText} +

+ ) : null} + + ) : ( +

+ {hostStatusText.unavailable} +

+ )} +
+ + {diagnosticsPreview ? ( +
+              {diagnosticsPreview}
+            
+ ) : null} +
+
); } diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index 034856d..dc65c41 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -1051,6 +1051,11 @@ msgstr "Desktop provider is not installed." msgid "settings.recovery.diagnostic_preview_aria" msgstr "Diagnostic bundle preview" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.advanced" +msgstr "Diagnostics and recovery" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.dictation" @@ -1358,11 +1363,6 @@ msgstr "Host is ready." msgid "settings.recovery.host_error" msgstr "Host recovery could not be completed." -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.host_status" -msgstr "Host recovery:" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.host_required" @@ -1544,11 +1544,6 @@ msgstr "Local Library storage is unavailable." msgid "home.local_projects" msgstr "Local projects" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.title" -msgstr "Local recovery" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.local_review" @@ -2583,6 +2578,11 @@ msgstr "Tool-assisted memory enabled" msgid "settings.dimension_asr_description" msgstr "Transcribe spoken audio." +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.title" +msgstr "Troubleshooting" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.tts_adapter_required" diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index 21a09c0..3ffc95d 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -1051,6 +1051,11 @@ msgstr "El proveedor de escritorio no está instalado." msgid "settings.recovery.diagnostic_preview_aria" msgstr "Vista previa del paquete de diagnóstico" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.advanced" +msgstr "Diagnóstico y recuperación" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.dictation" @@ -1358,11 +1363,6 @@ msgstr "El host está listo." msgid "settings.recovery.host_error" msgstr "No se pudo completar la recuperación del host." -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.host_status" -msgstr "Recuperación del host:" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.host_required" @@ -1544,11 +1544,6 @@ msgstr "El almacenamiento de la Biblioteca local no está disponible." msgid "home.local_projects" msgstr "Proyectos locales" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.title" -msgstr "Recuperación local" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.local_review" @@ -2583,6 +2578,11 @@ msgstr "Memoria asistida por herramientas activada" msgid "settings.dimension_asr_description" msgstr "Transcribir audio hablado." +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.title" +msgstr "Solución de problemas" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.tts_adapter_required" diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index c30a0bf..3566907 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -1051,6 +1051,11 @@ msgstr "Le fournisseur de bureau n’est pas installé." msgid "settings.recovery.diagnostic_preview_aria" msgstr "Aperçu du bundle de diagnostic" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.advanced" +msgstr "Diagnostic et récupération" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.dictation" @@ -1358,11 +1363,6 @@ msgstr "L'hôte est prêt." msgid "settings.recovery.host_error" msgstr "La récupération de l'hôte n'a pas pu être terminée." -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.host_status" -msgstr "Récupération de l'hôte :" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.host_required" @@ -1544,11 +1544,6 @@ msgstr "Le stockage de la bibliothèque locale n'est pas disponible." msgid "home.local_projects" msgstr "Projets locaux" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.title" -msgstr "Récupération locale" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.local_review" @@ -2583,6 +2578,11 @@ msgstr "Mémoire assistée par outils activée" msgid "settings.dimension_asr_description" msgstr "Transcrire de l’audio parlé." +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.title" +msgstr "Dépannage" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.tts_adapter_required" diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po index a15943f..9e385a1 100644 --- a/src/locales/ja/messages.po +++ b/src/locales/ja/messages.po @@ -1051,6 +1051,11 @@ msgstr "デスクトッププロバイダーがインストールされていま msgid "settings.recovery.diagnostic_preview_aria" msgstr "診断バンドルのプレビュー" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.advanced" +msgstr "診断と復旧" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.dictation" @@ -1358,11 +1363,6 @@ msgstr "ホストの準備ができました。" msgid "settings.recovery.host_error" msgstr "ホストの復元を完了できませんでした。" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.host_status" -msgstr "ホストの復元:" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.host_required" @@ -1544,11 +1544,6 @@ msgstr "ローカルライブラリのストレージを利用できません。 msgid "home.local_projects" msgstr "ローカルプロジェクト" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.title" -msgstr "ローカル復元" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.local_review" @@ -2583,6 +2578,11 @@ msgstr "ツール支援メモリを有効にしました" msgid "settings.dimension_asr_description" msgstr "音声を文字に書き起こします。" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.title" +msgstr "トラブルシューティング" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.tts_adapter_required" diff --git a/src/locales/zh-CN/messages.po b/src/locales/zh-CN/messages.po index 7272ef2..bad5933 100644 --- a/src/locales/zh-CN/messages.po +++ b/src/locales/zh-CN/messages.po @@ -1051,6 +1051,11 @@ msgstr "未安装桌面提供方。" msgid "settings.recovery.diagnostic_preview_aria" msgstr "诊断包预览" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.advanced" +msgstr "诊断与恢复" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.dictation" @@ -1358,11 +1363,6 @@ msgstr "主机已就绪。" msgid "settings.recovery.host_error" msgstr "无法完成主机恢复。" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.host_status" -msgstr "主机恢复:" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.host_required" @@ -1544,11 +1544,6 @@ msgstr "本地库存储不可用。" msgid "home.local_projects" msgstr "本地项目" -#. js-lingui-explicit-id -#: src/components/settings/sections/RecoverySection.tsx -msgid "settings.recovery.title" -msgstr "本地恢复" - #. js-lingui-explicit-id #: src/components/library/TeamGovernancePanel.tsx msgid "team.local_review" @@ -2583,6 +2578,11 @@ msgstr "已启用工具辅助记忆" msgid "settings.dimension_asr_description" msgstr "转录语音音频。" +#. js-lingui-explicit-id +#: src/components/settings/sections/RecoverySection.tsx +msgid "settings.recovery.title" +msgstr "故障排查" + #. js-lingui-explicit-id #: src/components/settings/sections/SpeechSection.tsx msgid "settings.speech.tts_adapter_required" diff --git a/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings-collapsed.png b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings-collapsed.png new file mode 100644 index 0000000..b6a8542 Binary files /dev/null and b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings-collapsed.png differ diff --git a/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings.png b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings.png index 0157cea..51127bd 100644 Binary files a/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings.png and b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/desktop-chrome/local-recovery-settings.png differ diff --git a/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings-collapsed.png b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings-collapsed.png new file mode 100644 index 0000000..c450f12 Binary files /dev/null and b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings-collapsed.png differ diff --git a/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings.png b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings.png index d68cae2..ba98187 100644 Binary files a/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings.png and b/tests/visual/__screenshots__/local-recovery-settings.spec.ts/mobile-chrome/local-recovery-settings.png differ diff --git a/tests/visual/local-recovery-settings.spec.ts b/tests/visual/local-recovery-settings.spec.ts index 04e7a8a..19ba41e 100644 --- a/tests/visual/local-recovery-settings.spec.ts +++ b/tests/visual/local-recovery-settings.spec.ts @@ -10,7 +10,7 @@ async function openUpdatesAndSupport(page: Page) { await page.getByText('Updates & Support', { exact: true }).click() } -test('Local recovery is truthful, redacted, and never deletes project data', async ({ page }) => { +test('Troubleshooting is truthful, redacted, and never deletes project data', async ({ page }) => { await page.addInitScript(() => { localStorage.setItem('cutout.project.sentinel', JSON.stringify({ id: 'project:keep' })) localStorage.setItem('cutout.workspace-navigation.v2', JSON.stringify({ advanced: true })) @@ -18,11 +18,16 @@ test('Local recovery is truthful, redacted, and never deletes project data', asy ;(globalThis as typeof globalThis & { __SECRET_SENTINEL__?: string }).__SECRET_SENTINEL__ = 'MOX_API_KEY=must-not-appear' }) await openUpdatesAndSupport(page) - const recovery = page.getByText('Local recovery', { exact: true }).locator('..') + const recovery = page.getByText('Troubleshooting', { exact: true }).locator('..') await expect(recovery).toContainText('Project data is not deleted.') + await expect(recovery.getByRole('button')).toHaveCount(1) + const advanced = recovery.locator('details') + await expect(advanced).not.toHaveAttribute('open', '') + await expect(page.getByRole('dialog')).toHaveScreenshot('local-recovery-settings-collapsed.png') + await advanced.getByText('Diagnostics and recovery', { exact: true }).click() await expect(recovery.getByRole('status')).toContainText('Authorize a workspace before using host recovery.') - await expect(page.getByRole('button', { name: 'Check host' })).toBeDisabled() - await expect(page.getByRole('button', { name: 'Recover host' })).toBeDisabled() + await expect(page.getByRole('button', { name: 'Check host' })).toHaveCount(0) + await expect(page.getByRole('button', { name: 'Recover host' })).toHaveCount(0) await page.getByRole('button', { name: 'Preview diagnostics' }).click() const preview = page.getByLabel('Diagnostic bundle preview')