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
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

Human Test Plan: User Theme Preferences#

Feature branch: user-theme-preferences Automated coverage: 18/18 ACs passing (1266 tests, 0 failures)


Prerequisites#

  • Development environment running via devenv shell
  • Dependencies installed via pnpm install
  • .env file configured with valid APPVIEW_URL
  • Development server started with pnpm dev
  • All automated tests passing: pnpm --filter @atbb/web test
  • At least two themes registered in the forum's theme policy (one light, one dark)
  • An AT Protocol account available for login (e.g., a test Bluesky account)

Human Verification Required#

The following items cannot be validated by automated tests and must be verified manually:

ID Criterion Why Manual
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.
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.
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.

Phase 1: Settings Page Access and Navigation#

Step Action Expected
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.
1.2 Click "Log in" and authenticate with a valid AT Protocol account. Redirect to the forum homepage after successful login.
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.
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.
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".
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.

Phase 2: Theme Selection Form Rendering#

Step Action Expected
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.
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".
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).

Phase 3: HTMX Live Preview — HV1#

Step Action Expected
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.
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.
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://....
3.4 Open the browser Console tab. Perform several dropdown changes. No JavaScript errors appear in the console during any preview interaction.

Phase 4: Saving Preferences#

Step Action Expected
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.
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.
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.

Phase 5: Theme Application on Page Load#

Step Action Expected
5.1 After saving preferences, navigate to the forum homepage (/). The page renders using the selected light theme's color tokens.
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.
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.

Phase 6: Visual Swatch Correctness — HV2#

Step Action Expected
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.
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.
6.3 Verify the theme name label above the swatches. The name is clearly readable and matches the theme selected in the dropdown.
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.

Step Action Expected
7.1 Save theme preferences on /settings with non-default themes. "Preferences saved." banner appears.
7.2 Fully close the browser (all windows, not just the tab). Browser process exits.
7.3 Reopen the browser and navigate to the forum homepage. The forum renders with the previously selected theme, not the forum default.
7.4 Navigate to /settings. The dropdowns show the previously saved selections.
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.

Phase 8: Validation Error Flows#

Step Action Expected
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.
8.2 Submit a POST to /settings/appearance with an empty body. Browser redirects to /settings?error=invalid.

End-to-End: Full Theme Preference Lifecycle#

Purpose: Validate the complete flow from unauthenticated state through preference selection, persistence, application, and cross-session retention.

  1. Open incognito window. Navigate to the forum homepage. Verify default theme is applied.
  2. Navigate to /settings. Confirm redirect to /login.
  3. Log in with a valid AT Protocol account. Navigate to /settings.
  4. Verify the light and dark theme dropdowns are populated and defaults are selected.
  5. Change the light theme dropdown. Verify the preview updates without page reload (HTMX swap).
  6. Change the dark theme dropdown. Verify the preview updates with the dark theme's swatches.
  7. Click Save. Confirm "Preferences saved." banner and /settings?saved=1 URL.
  8. Navigate to the homepage. Verify the selected light theme is applied.
  9. Toggle to dark mode. Verify the selected dark theme is applied.
  10. Close the browser entirely. Reopen and navigate to the forum. Verify the dark theme persists.
  11. Navigate to /settings. Verify both dropdowns still show the previously saved selections.
  12. Log out. Navigate to /settings. Confirm redirect to /login.

End-to-End: Admin Disables User Choice#

Purpose: Validate that the allowUserChoice: false policy flag gates the entire settings UI and POST endpoint.

  1. As a forum administrator, set the theme policy to allowUserChoice: false.
  2. Log in as a regular user. Navigate to /settings.
  3. Verify the page shows an informational banner: "Theme selection is managed by the forum administrator". Verify no <select> dropdowns are present.
  4. Using DevTools, manually POST to /settings/appearance with valid theme URIs. Verify the response is 302 to /settings?error=not-allowed.
  5. Navigate to the forum homepage. Verify the forum default theme is applied regardless of any previously saved preference cookies.

Traceability#

Acceptance Criterion Automated Test Manual Step
AC1.1: Settings link in nav base.test.tsx: auth visibility + desktop/mobile rendering Phase 1, steps 1.1–1.4
AC1.2: Settings page renders selects settings.test.tsx: "renders form with light/dark theme selects" Phase 2, step 2.1
AC1.3: Light select triggers preview settings.test.tsx: "renders selects with hx-get attribute" Phase 3, steps 3.1–3.2 — HV1
AC1.4: Dark select triggers preview settings.test.tsx: same hx-* attribute test Phase 3, step 3.3 — HV1
AC1.5: Unauth redirect to /login settings.test.tsx: "redirects unauthenticated users to /login" Phase 1, step 1.6
AC2.1: Form sets preference cookies settings.test.tsx: "sets theme cookies and redirects" Phase 4, steps 4.1–4.2 — HV3
AC2.2: "Preferences saved" banner settings.test.tsx: "GET /settings with ?saved=1 shows success banner" Phase 4, step 4.1
AC2.3: Saved themes pre-selected settings.test.tsx: "pre-selects current preference cookie" Phase 4, step 4.3
AC3.1: Light cookie applied on load theme-resolution.test.ts: unit + integration Phase 5, step 5.1 — HV3
AC3.2: Dark cookie applied on load theme-resolution.test.ts: unit + integration Phase 5, step 5.2 — HV3
AC3.3: Stale cookie falls back theme-resolution.test.ts: unit + integration Automated only
AC4.1: Reject URI not in policy settings.test.tsx: invalid light/dark theme URI tests Phase 8, step 8.1
AC4.2: Reject when allowUserChoice false settings.test.tsx: "rejects when allowUserChoice: false" E2E: Admin Disables User Choice, step 4
AC4.3: Reject missing/malformed body settings.test.tsx: three partial-body tests Phase 8, step 8.2
AC4.4: Policy fetch failure is safe settings.test.tsx: "rejects when policy fetch fails" Automated only
AC5.1: Info banner when choice disabled settings.test.tsx: "shows informational banner" E2E: Admin Disables User Choice, steps 2–3
AC5.2: Resolution ignores cookie when disabled theme-resolution.test.ts: unit + integration E2E: Admin Disables User Choice, step 5
AC6.1: Preview returns swatch fragment settings.test.tsx: valid lightThemeUri/darkThemeUri tests Phase 6 — HV2
AC6.2: Unknown URI returns empty fragment settings.test.tsx: 4 edge-case tests Automated only