WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1# Human Test Plan: User Theme Preferences
2
3**Feature branch:** `user-theme-preferences`
4**Automated coverage:** 18/18 ACs passing (1266 tests, 0 failures)
5
6---
7
8## Prerequisites
9
10- Development environment running via `devenv shell`
11- Dependencies installed via `pnpm install`
12- `.env` file configured with valid `APPVIEW_URL`
13- Development server started with `pnpm dev`
14- All automated tests passing: `pnpm --filter @atbb/web test`
15- At least two themes registered in the forum's theme policy (one light, one dark)
16- An AT Protocol account available for login (e.g., a test Bluesky account)
17
18---
19
20## Human Verification Required
21
22The following items cannot be validated by automated tests and **must be verified manually**:
23
24| ID | Criterion | Why Manual |
25|----|-----------|------------|
26| HV1 | HTMX live preview swap (AC1.3, AC1.4) | HTMX client-side JS intercepts `<select>` change events and performs DOM replacement. The test harness cannot exercise browser-side JS behavior. |
27| HV2 | Visual swatch correctness (AC6.1) | Automated tests verify swatch HTML and inline styles exist but cannot assess whether rendered colors are visually correct or CSS layout makes them visible. |
28| HV3 | Cookie persistence across sessions (AC2.1, AC3.1, AC3.2) | Integration tests verify Set-Cookie headers and cookie reading logic but cannot verify actual browser cookie storage and persistence across full browser restarts. |
29
30---
31
32## Phase 1: Settings Page Access and Navigation
33
34| Step | Action | Expected |
35|------|--------|----------|
36| 1.1 | Open the forum homepage in a browser while not logged in. Inspect the site header (desktop) and hamburger menu (mobile). | No "Settings" link is visible in either desktop or mobile navigation. "Log in" is visible. |
37| 1.2 | Click "Log in" and authenticate with a valid AT Protocol account. | Redirect to the forum homepage after successful login. |
38| 1.3 | Inspect the site header (desktop viewport, 1024px+). | A "Settings" link with `href="/settings"` is visible in the desktop navigation bar alongside the handle and "Log out" button. |
39| 1.4 | Resize the browser to mobile width (below 768px) and open the hamburger menu. | A "Settings" link is visible in the mobile dropdown navigation. |
40| 1.5 | Click the "Settings" link (either desktop or mobile). | Browser navigates to `/settings`. Page loads with a 200 status. The page title contains "Settings". |
41| 1.6 | Open a private/incognito window and navigate directly to `/settings` without logging in. | Browser is redirected to `/login`. The URL bar shows `/login`. |
42
43---
44
45## Phase 2: Theme Selection Form Rendering
46
47| Step | Action | Expected |
48|------|--------|----------|
49| 2.1 | On `/settings` while authenticated, inspect the form. | Two `<select>` dropdowns are present: one labeled for light theme (`id="lightThemeUri"`) and one for dark theme (`id="darkThemeUri"`). Each lists the available themes from the forum's theme policy. |
50| 2.2 | Open browser DevTools and inspect the `<select>` elements. | Each select has these attributes: `hx-get="/settings/preview"`, `hx-trigger="change"`, `hx-target="#theme-preview"`, `hx-swap="outerHTML"`, `hx-include="this"`. |
51| 2.3 | Verify that a `<div id="theme-preview">` element exists on the page below the selects. | The div is present and initially empty (no swatch content). |
52
53---
54
55## Phase 3: HTMX Live Preview — HV1
56
57| Step | Action | Expected |
58|------|--------|----------|
59| 3.1 | On `/settings`, change the light theme dropdown to a different theme. | Without a full page reload, the `#theme-preview` area updates to show the theme name and five colored swatch squares representing `color-bg`, `color-surface`, `color-primary`, `color-text`, and `color-border`. |
60| 3.2 | Open the browser Network tab (DevTools). Change the light theme dropdown again. | A GET request to `/settings/preview?lightThemeUri=at://...` appears in the network log. Response is 200 with an HTML fragment. No full page navigation occurs. |
61| 3.3 | Change the dark theme dropdown to a different dark theme. | The `#theme-preview` area updates with the dark theme's name and swatches. The network log shows a GET to `/settings/preview?darkThemeUri=at://...`. |
62| 3.4 | Open the browser Console tab. Perform several dropdown changes. | No JavaScript errors appear in the console during any preview interaction. |
63
64---
65
66## Phase 4: Saving Preferences
67
68| Step | Action | Expected |
69|------|--------|----------|
70| 4.1 | Select a specific light theme and a specific dark theme from the dropdowns. Click "Save preferences". | Browser redirects to `/settings?saved=1`. A success banner reading "Preferences saved." is visible. |
71| 4.2 | Open browser DevTools > Application > Cookies. Filter for the current domain. | Two cookies are present: `atbb-light-theme` (AT URI matching the selected light theme) and `atbb-dark-theme` (AT URI matching the selected dark theme). Both have `Path=/`, `Max-Age=31536000` (1 year), and `SameSite=Lax`. |
72| 4.3 | Refresh the `/settings` page. | The light and dark theme dropdowns pre-select the previously saved themes. The `selected` attribute is on the correct `<option>` elements. |
73
74---
75
76## Phase 5: Theme Application on Page Load
77
78| Step | Action | Expected |
79|------|--------|----------|
80| 5.1 | After saving preferences, navigate to the forum homepage (`/`). | The page renders using the selected light theme's color tokens. |
81| 5.2 | Click the color scheme toggle to switch to dark mode. | The page reloads and renders using the selected dark theme's color tokens. An `atbb-color-scheme=dark` cookie is set. |
82| 5.3 | Navigate to several pages (topic list, category view, etc.) while in dark mode. | All pages consistently use the selected dark theme. No flash of the default theme occurs during navigation. |
83
84---
85
86## Phase 6: Visual Swatch Correctness — HV2
87
88| Step | Action | Expected |
89|------|--------|----------|
90| 6.1 | On `/settings`, change the light theme dropdown. | The preview area shows visually distinct colored squares. Each swatch has a visible background color matching the theme's token values. |
91| 6.2 | Hover over each swatch (or inspect via DevTools). | Each swatch has a `title` attribute indicating the token (`color-bg`, `color-primary`, etc.). The inline `style="background:<color>"` matches the token value. |
92| 6.3 | Verify the theme name label above the swatches. | The name is clearly readable and matches the theme selected in the dropdown. |
93| 6.4 | Repeat steps 6.1-6.3 for a dark theme selection. | Dark theme swatches show appropriately dark colors. The theme name is correct. |
94
95---
96
97## Phase 7: Cookie Persistence Across Browser Sessions — HV3
98
99| Step | Action | Expected |
100|------|--------|----------|
101| 7.1 | Save theme preferences on `/settings` with non-default themes. | "Preferences saved." banner appears. |
102| 7.2 | Fully close the browser (all windows, not just the tab). | Browser process exits. |
103| 7.3 | Reopen the browser and navigate to the forum homepage. | The forum renders with the previously selected theme, not the forum default. |
104| 7.4 | Navigate to `/settings`. | The dropdowns show the previously saved selections. |
105| 7.5 | Switch to dark mode via the toggle and close/reopen the browser. | Dark mode with the custom dark theme persists across the browser restart. |
106
107---
108
109## Phase 8: Validation Error Flows
110
111| Step | Action | Expected |
112|------|--------|----------|
113| 8.1 | Using browser DevTools Console, submit a POST to `/settings/appearance` with a `lightThemeUri` not in the available themes. | Browser redirects to `/settings?error=invalid-theme`. No cookies are set or modified. |
114| 8.2 | Submit a POST to `/settings/appearance` with an empty body. | Browser redirects to `/settings?error=invalid`. |
115
116---
117
118## End-to-End: Full Theme Preference Lifecycle
119
120**Purpose:** Validate the complete flow from unauthenticated state through preference selection, persistence, application, and cross-session retention.
121
1221. Open incognito window. Navigate to the forum homepage. Verify default theme is applied.
1232. Navigate to `/settings`. Confirm redirect to `/login`.
1243. Log in with a valid AT Protocol account. Navigate to `/settings`.
1254. Verify the light and dark theme dropdowns are populated and defaults are selected.
1265. Change the light theme dropdown. Verify the preview updates without page reload (HTMX swap).
1276. Change the dark theme dropdown. Verify the preview updates with the dark theme's swatches.
1287. Click Save. Confirm "Preferences saved." banner and `/settings?saved=1` URL.
1298. Navigate to the homepage. Verify the selected light theme is applied.
1309. Toggle to dark mode. Verify the selected dark theme is applied.
13110. Close the browser entirely. Reopen and navigate to the forum. Verify the dark theme persists.
13211. Navigate to `/settings`. Verify both dropdowns still show the previously saved selections.
13312. Log out. Navigate to `/settings`. Confirm redirect to `/login`.
134
135---
136
137## End-to-End: Admin Disables User Choice
138
139**Purpose:** Validate that the `allowUserChoice: false` policy flag gates the entire settings UI and POST endpoint.
140
1411. As a forum administrator, set the theme policy to `allowUserChoice: false`.
1422. Log in as a regular user. Navigate to `/settings`.
1433. Verify the page shows an informational banner: "Theme selection is managed by the forum administrator". Verify no `<select>` dropdowns are present.
1444. Using DevTools, manually POST to `/settings/appearance` with valid theme URIs. Verify the response is 302 to `/settings?error=not-allowed`.
1455. Navigate to the forum homepage. Verify the forum default theme is applied regardless of any previously saved preference cookies.
146
147---
148
149## Traceability
150
151| Acceptance Criterion | Automated Test | Manual Step |
152|----------------------|----------------|-------------|
153| AC1.1: Settings link in nav | `base.test.tsx`: auth visibility + desktop/mobile rendering | Phase 1, steps 1.1–1.4 |
154| AC1.2: Settings page renders selects | `settings.test.tsx`: "renders form with light/dark theme selects" | Phase 2, step 2.1 |
155| AC1.3: Light select triggers preview | `settings.test.tsx`: "renders selects with hx-get attribute" | Phase 3, steps 3.1–3.2 — **HV1** |
156| AC1.4: Dark select triggers preview | `settings.test.tsx`: same hx-* attribute test | Phase 3, step 3.3 — **HV1** |
157| AC1.5: Unauth redirect to /login | `settings.test.tsx`: "redirects unauthenticated users to /login" | Phase 1, step 1.6 |
158| AC2.1: Form sets preference cookies | `settings.test.tsx`: "sets theme cookies and redirects" | Phase 4, steps 4.1–4.2 — **HV3** |
159| AC2.2: "Preferences saved" banner | `settings.test.tsx`: "GET /settings with ?saved=1 shows success banner" | Phase 4, step 4.1 |
160| AC2.3: Saved themes pre-selected | `settings.test.tsx`: "pre-selects current preference cookie" | Phase 4, step 4.3 |
161| AC3.1: Light cookie applied on load | `theme-resolution.test.ts`: unit + integration | Phase 5, step 5.1 — **HV3** |
162| AC3.2: Dark cookie applied on load | `theme-resolution.test.ts`: unit + integration | Phase 5, step 5.2 — **HV3** |
163| AC3.3: Stale cookie falls back | `theme-resolution.test.ts`: unit + integration | Automated only |
164| AC4.1: Reject URI not in policy | `settings.test.tsx`: invalid light/dark theme URI tests | Phase 8, step 8.1 |
165| AC4.2: Reject when allowUserChoice false | `settings.test.tsx`: "rejects when allowUserChoice: false" | E2E: Admin Disables User Choice, step 4 |
166| AC4.3: Reject missing/malformed body | `settings.test.tsx`: three partial-body tests | Phase 8, step 8.2 |
167| AC4.4: Policy fetch failure is safe | `settings.test.tsx`: "rejects when policy fetch fails" | Automated only |
168| AC5.1: Info banner when choice disabled | `settings.test.tsx`: "shows informational banner" | E2E: Admin Disables User Choice, steps 2–3 |
169| AC5.2: Resolution ignores cookie when disabled | `theme-resolution.test.ts`: unit + integration | E2E: Admin Disables User Choice, step 5 |
170| AC6.1: Preview returns swatch fragment | `settings.test.tsx`: valid lightThemeUri/darkThemeUri tests | Phase 6 — **HV2** |
171| AC6.2: Unknown URI returns empty fragment | `settings.test.tsx`: 4 edge-case tests | Automated only |