docs: manual web app end-to-end test runbook (P3/T23)

13 sections covering every flow that unit tests can't:

  1. Smoke (mobile header, sidebar, page titles, tab strips)
  2. Account pairing (live QR, sync groups, send-test)
  3. Re-pair / unpair (status flips, no spurious reconnect)
  4. Reminders — single-message one-off (5-step wizard)
  5. Reminders — multi-message stack with media swap
  6. Reminders — recurrence picker (Daily / Weekly / Monthly /
     Yearly + multi-rule, descriptions are sentences not raw cron)
  7. Reminders — edit each section preserves the message stack
     (regression guard for the parts-2..N drop bug)
  8. Reminders list — swipe + lifecycle (no reshuffle on Pause /
     Restart, shelf collapses after action)
  9. Activity — swipe archive / delete + Archived tab + restore
 10. Send-test feedback round trip (Sending… → Sent ✓)
 11. Media upload limits (size caps, HEIC/MOV → document fallback)
 12. PWA install (standalone display, offline shell)
 13. Theme toggle (desktop only)

Captures the policy decisions that aren't immediately obvious from
the code:
  - browser-extension hydration warnings are expected, app code is
    not at fault — Incognito clears them
  - HEIC/MOV uploads are NOT rejected; they fall back to document
    delivery
  - cron rules render as descriptive sentences in the UI
  - status changes don't reorder the reminders list

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
yiekheng 2026-05-10 13:22:04 +08:00
parent 272fbcfa8a
commit d407fc585e

View File

@ -0,0 +1,185 @@
# Manual test: Web app end-to-end
Run after every major web change. Captures the daily-ops flows that
unit tests can't verify (live Baileys QR, WhatsApp delivery, swipe
gestures on a real touch device).
## Prerequisites
- `scripts/dev.sh up` is running. The bot, web, postgres, and tools
containers are all healthy.
- Browser open on the host, ideally on a phone for the swipe tests.
LAN URL is `http://<host-ip>:9000` (e.g. `192.168.0.253:9000`); the
reverse-proxy URL is `https://wabot.04080616.xyz`.
- A WhatsApp test phone with at least one group you can fire test
messages into.
## 1. Smoke
1. Visit `/` — dashboard renders with three stat cards (Accounts
connected, Active reminders, Recent runs). No console errors
beyond the known browser-extension hydration warning ("Encountered
a script tag while rendering"). The "Recent runs" card description
reads "3 most recent runs" and links to `/activity`.
2. Mobile header on the phone shows the `cm` brand pill (left), the
current page title in the centre, and a hamburger menu (right).
Tap the menu → a right-side drawer opens with the five nav items.
Tapping any item closes the drawer and routes to the page.
3. Click `cm` brand pill → navigates to dashboard. Same on the
desktop sidebar header (`cm WhatsApp Bot`).
4. Status tab strips on `/reminders` (4 tabs) span the row evenly;
on `/activity` (6 tabs incl. Archived) the strip scrolls
horizontally on narrow widths.
## 2. Account pairing (live QR)
1. `/accounts` → "New Account" → form → enter "Web Test 1" → "Add
Account". Redirects to `/accounts/<id>` with status `Unpaired`.
2. Tap the "Pair WhatsApp" card. Redirects to
`/accounts/<id>/pairing`. Within ~5 s a QR appears below
"Waiting for scan…".
3. Scan with WhatsApp on the test phone (Linked Devices →
Link a Device).
4. After scan, status flips to "✅ Connected as +60xxx" and the page
auto-redirects to the account detail. Phone number visible.
5. Hit "Sync Groups" — group rows appear.
6. Tap a group → opens the group detail. Type "Test from web" →
Send Test. Toast shows "Sending…", then "Sent ✓". The phone's
WhatsApp shows the message in the group within ~5 s.
## 3. Re-pair / unpair
1. From the account detail, tap "Re-pair WhatsApp" → re-routes to
`/pairing` with a fresh QR. Cancel by going back.
2. Tap "Unpair" → confirm dialog. Confirm. Status flips to
`Unpaired` immediately (no flicker through `Disconnected`). Bot
logs show no spurious 5-second reconnect.
3. Re-pair the same account by scanning again — old session files
cleared, fresh handshake.
## 4. Reminders — single message, one-off
1. `/reminders` → "New Reminder".
2. Step 1 (Account): pick the test account.
3. Step 2 (Message): type "Hello world" in a single text block.
Continue.
4. Step 3 (When): pick "now + 2 minutes" (a date+time, no repeat).
5. Step 4 (Groups): pick the test group.
6. Step 5 (Review): all sections show correct values. Tap "Schedule
Reminder".
7. Within ~2.5 minutes the reminder fires. WhatsApp shows "Hello
world" in the group.
8. Reload `/reminders/<id>` — status `ended`, run history has one
row with `Success`.
## 5. Reminders — multi-message stack with media swap
1. `/reminders/new` → step 2.
2. Add a text block "Block 1". "+ Add file" → upload a JPEG image.
Caption "img caption". "+ Add text" "Block 3 PS".
3. Continue through When / Groups / Review. Review pane shows three
message parts in order with the JPEG filename rendered.
4. Schedule. Bot fires three messages in sequence with a ~1.5 s
gap. WhatsApp shows them in order.
## 6. Reminders — recurrence picker (cron-backed)
1. `/reminders/new` → step 3 (When). Switch the recurrence picker
from "No Repeats" to "Daily" → set time 09:00 → continue.
Description on the review pane reads "Every day at 09:00", NOT
raw cron text.
2. Edit recurrence to Weekly Mon, Wed, Fri 17:30. Review reads
"Every week on Mon, Wed, Fri at 17:30".
3. Edit recurrence to Monthly with multiple days (1, 15) at 09:00.
Review reads "Every month on days 1, 15 at 09:00".
4. Edit recurrence to Yearly with months Jan, Apr at day 1 at 09:00.
Review reads "Every year in Jan, Apr on day 1 at 09:00".
5. Add a SECOND recurrence row alongside the first. Review summary
joins both with " · ".
6. Schedule (set first fire close to now). Verify both rules fire.
## 7. Reminders — edit each section preserves the message stack
1. Create a reminder with a 3-message stack. Schedule for the
future.
2. From `/reminders/<id>`, click the Account section → switch to
another connected account → Save. The reminder's message list
on the detail page still shows all 3 parts. (Regression guard
for the previous bug where editing the account dropped parts
2..N.)
3. Same exercise on the Message section: open, swap the JPEG for
a different image (file picker on the media block), Save.
Reminder still has 3 parts; the second part now points at the
new media.
4. Same on When (change time) and Groups (toggle a group).
## 8. Reminders list — swipe + lifecycle
1. `/reminders` (mobile). Swipe a row LEFT → red "Delete" shelf
appears on the right.
2. Swipe the same row RIGHT → amber "Pause" or "Restart" shelf on
the left (depending on current status).
3. Tap "Pause" on an active row. The row stays in the same list
position (no reshuffle) and its status pill flips to "Paused".
The shelf collapses immediately (no leftover open state).
4. Swipe right again → "Restart". Tap. Status flips back to active,
row position unchanged, shelf closed.
5. Swipe left → "Delete". Confirm. Row removed, run history
preserved on `/activity`.
## 9. Activity — swipe to archive / delete
1. `/activity`. Swipe a row LEFT → red "Delete" shelf.
2. Swipe RIGHT on a non-archived row → amber "Archive" shelf. Tap.
Row disappears from the All / Success / Partial / Failed /
Skipped tabs.
3. Switch to the "Archived" tab → archived row is here. Swipe
RIGHT → "Restore". Tap. Row leaves Archived, returns to All.
4. "Clear history" button at the top hard-deletes everything and
is hidden when on the Archived tab.
## 10. Send-test feedback round trip
1. Group detail → type a quick message → Send Test.
2. Toast "Sending…" appears. Within ~5 s it changes to "Sent ✓".
3. Phone's WhatsApp shows the message in the group.
## 11. Media upload limits
1. `/reminders/new` step 2, upload a 4 MB JPEG → accepted, file
shows in the media block.
2. Upload a 6 MB JPEG → "Image too large (6.0 MB > 5.0 MB limit on
WhatsApp)".
3. Upload a HEIC photo (e.g. straight off an iPhone) → accepted,
delivered as a document on WhatsApp instead of inline image.
Recipient sees a downloadable .heic file.
4. Upload a `.mov` (QuickTime) → accepted, delivered as a document.
5. Upload a 110 MB document (PDF) → rejected: "Document too large
(110.0 MB > 100.0 MB limit on WhatsApp)".
## 12. PWA install
1. Phone Chrome → menu → "Install App" / "Add to Home Screen".
2. Open from the home screen. The header chrome (URL bar, tabs)
is gone — fullscreen standalone display.
3. Brand icon shows the placeholder dark `cm` square.
4. Force the phone offline (airplane mode) → relaunch the PWA.
Cached navigation shell loads (white-on-dark spinner / shell);
network-dependent pages show the offline shell instead of a
browser error page.
## 13. Theme toggle
1. Desktop sidebar footer → click the theme button → page swaps
between light / dark / system.
2. Mobile drawer no longer contains the theme toggle (intentional
— it lives only in the desktop sidebar now).
## Sign-off
- [ ] All sections passed
- [ ] No console errors beyond the known browser-extension
"Encountered a script tag" hydration noise (Incognito with
extensions disabled is clean)
- [ ] Bot logs show no unexpected ERROR / WARN entries during the run
- [ ] Tester / date / build SHA recorded