- Conversations in a versioned IndexedDB store (freezmo-chat v1, zod validated with the same schema backup/sync use, capped at 100 x 300). Settled turns persist (question always; answer when produced, partial stops included); ?c=<id> keeps reloads on the conversation via history.replaceState (no router round-trip mid-chat). - History UI: desktop column, phone sheet (spring, backdrop, Escape), auto titles from the first question, inline rename, delete with an Undo toast, diacritic-folding search over titles and message text. Scope and model are remembered per conversation; history is readable offline. - Assistant actions: Turn into flashcards (New deck with the answer as notes, landing on the options step - deck seed gained step) and Save to notes (appends to the single scoped deck, trimmed at 40k). - Chats travel in the backup export (preview counts them) and in the encrypted sync payload; still never the key. - Motion from lib/motion.ts: message fade-up, sheet springs for the model/context/history sheets, 150ms composer height transition, all skipped under reduced motion. - Tests: chat suite 63 -> 89 checks (history, reload, rename/search/ delete/undo, actions, export, two-device sync round-trip, offline, desktop panel). Full set: 12/12 suites, 513 checks. SW -> freezmo-v33. Also: tests/model-compare.mjs benchmark (diagnostic) for deciding the default text model on numbers; defaults unchanged.
55 lines
3.7 KiB
Markdown
55 lines
3.7 KiB
Markdown
# Browser suites
|
||
|
||
End-to-end checks for Freezmo, driven by Playwright against a **running
|
||
production build**. Everything lives in this repo (nothing in `/tmp`), so a
|
||
reboot cannot wipe the harness.
|
||
|
||
## Requirements
|
||
|
||
- The app is running on `http://127.0.0.1:3207` (`systemctl --user start freezmo`).
|
||
- A Chromium build. The suites auto-detect the newest Playwright Chromium in
|
||
`~/.cache/ms-playwright/`; override with `CHROME=/path/to/chrome`.
|
||
- `npm install` (dev deps: `playwright-core`, `axe-core`).
|
||
|
||
## Running
|
||
|
||
```bash
|
||
npm run build && systemctl --user restart freezmo # fresh build first
|
||
npm run test:e2e # every suite, in order
|
||
npm run test:e2e -- phase1 # only suites whose name contains "phase1"
|
||
```
|
||
|
||
Each suite prints `PASS`/`FAIL` lines and exits non-zero on failure; the runner
|
||
prints a per-suite summary at the end.
|
||
|
||
## Suites
|
||
|
||
| Suite | Covers |
|
||
| --- | --- |
|
||
| `regression.mjs` | Library, deck card + menu, study feed to results, homework entry, desktop shell + settings/health panel. |
|
||
| `bubbles-test.mjs` | Ice-scene bubbles: stacking/layout contract, keyframes only transform+opacity, rise/sway/scale/fade phases, per-breakpoint counts (5/3/2), phone pacing, reduced motion, tab-hidden parking. |
|
||
| `mobile-test.mjs` | Five-tab bar at 360/390 × EN/CS × dark/light × reduced motion (labels, targets, no hamburger/drawer), the library ⋯ sheet (Import JSON / New folder), the settings sheet (touch targets, key flow, drag-to-close, backdrop), axe contrast audits. |
|
||
| `wizard-test.mjs` | Deck 3-step flow and homework flow, flat action bar, in-page mode switch, the loading lock, abort-on-leave. |
|
||
| `native-test.mjs` | Manifest/PWA head, offline banner + disabled generate, share target GET + POST, Back-gesture layers, undo toast, tab re-tap, haptics, draft restore. |
|
||
| `i18n-test.mjs` | EN/CS dictionary parity, locale switch, Czech desktop shell, Czech phone tab labels and plurals. |
|
||
| `freeze-loading-test.mjs` | The generation loading screen appears immediately, hides the action bar, Cancel returns with the notice. |
|
||
| `review-test.mjs` | Smart Review loading feedback under a stalled request, the session end-to-end, mistakes, and the health-probe cache. |
|
||
| `phase1-test.mjs` | Backup export/import, persistence row, nudge, encrypted sync (enable/join/push/delete + API validation), usage-limit handling (client + a stub Ollama). |
|
||
| `phase2-test.mjs` | Answer history + SRS from a real study run, review/mistakes, stats, exam mode, push reminders hidden without VAPID and validated with it. |
|
||
| `phase3-test.mjs` | Check my work (API + phone/desktop UI), follow-ups, guide step explain, turn-into-a-study-deck. |
|
||
| `chat-test.mjs` | Chat: streaming API (validation, allowlist, context travel, history window, thinking separation, usage-limit mapping), attachment extraction, entry points, streaming/stop, markdown + KaTeX, model/scope pickers, edit/regenerate, offline, reduced motion, plus history (IDB persistence, reload, rename/search/delete/undo, scope+model memory), assistant actions, the export payload and a two-device sync round-trip. |
|
||
|
||
## Extra instances
|
||
|
||
`phase1`, `phase2` and `phase3` start their own `next start` instance with a
|
||
stub Ollama (or VAPID keys) on a spare port (3208/3209). Each suite checks the
|
||
port is free first and kills the whole process group on exit, so ports do not
|
||
leak between suites. Scratch data for the VAPID test lives in `tests/.tmp/`
|
||
(gitignored).
|
||
|
||
## Diagnostics (not part of the run)
|
||
|
||
`node tests/bubble-perf.mjs [label]` measures the ice-scene frame cost with a
|
||
CDP performance trace (rAF frame timing, long tasks, main-thread busy time,
|
||
style recalcs) on a 4× throttled phone profile and a 2× desktop profile. It
|
||
always exits 0; the numbers are for tuning the bubble count/speed.
|