Sweeps every remaining "FIXED ⚠️ UNTESTED" item from LOTUS_BUGS.md and LOTUS_TODO.md into the testing guide, grouped by environment (mobile, theming, calls, media/perf, accessibility/screen-reader, desktop/Tauri, features) so each category can be verified in one pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
18 KiB
Lotus Chat — Manual Testing Guide
Generated: June 2026
Scope: Everything landed on the lotus branch since the v4.12.3 merge that I (Claude) could not verify statically and that needs a human in a real environment to confirm. Work through it top-to-bottom; the highest-risk / hardest-to-reproduce items are first.
How to report back: For each numbered check, tell me PASS / FAIL (or partial). On any FAIL, include: what you saw vs. expected, the browser/OS (and whether web LXC 106 or the desktop/Tauri build), the theme you were on, and any browser console errors (F12 → Console). Screenshots help for anything visual.
Environment notes
- You push from your own machine; these commits are local on
lotusuntil you do. - Test the web build (LXC 106 /
code.lotusguild.org) first; re-run the call + poll sections on the desktop (Tauri) build too, since CSP and the EC iframe behave differently there. - Several call features need a second participant (second account on another device/browser, or a colleague). Items that need this are marked 👥 2 people.
- A couple of call items need a third room/call in parallel — marked 👥👥.
Commits covered
| Commit | Area |
|---|---|
caf6318a |
Poll vote buttons → folds tokens (N4) |
c67aed01 |
In-call incoming-call banner (#4b) |
4a875884 |
Selectable ringtone (#4a) |
0394fce9 |
EC iframe load watchdog + recovery UI; avatar decorations on call tiles (#3) |
d2946c00 |
Upload retry/backoff, presence-on-unload, typed m.direct |
b7e1f89c |
Timeline/composer/emoji perf memoization |
c0f98672 |
Upstream Element Call 0.20.1 merge (regression sweep) |
A. Calls — new ringtone + notification work (highest priority)
A1. Ringtone selection — preview in Settings
Steps
- Open Settings → General, scroll to the Calls section.
- Find the new Ringtone dropdown (just above Ringtone Volume).
- Select each option in turn: Classic, Chime, Soft, Retro, Silent.
Expected
- Selecting Classic plays the existing
call.oggclip (cut off after a few seconds). - Chime / Soft / Retro each play a short, distinct synthesized preview.
- Silent plays nothing.
- Changing Ringtone Volume then re-selecting a ringtone previews at the new volume.
- No console errors.
⚠️ Known browser limitation: the synthesized tones use WebAudio. If a preview is ever silent, click anywhere on the page once (a "user gesture") and retry — browsers suspend audio until the page has been interacted with. The Settings preview is after a click so it should always sound; this note matters more for A3.
A2. Ringtone selection persists
- Set Ringtone to Retro, reload the app.
- Expected: the dropdown still shows Retro (setting persisted).
- Bonus: in devtools, set
localStorage.settingsto a bogusringtoneIdand reload → it should fall back to Classic, not break.
A3. Incoming call uses the selected ringtone — 👥 2 people
Setup: Account A (you) and Account B in a DM or a private (invite-only) group room.
- As A, pick a non-silent ringtone (e.g. Chime).
- From B, start a call in that DM/room. Do not answer on A.
Expected on A
- The full-screen Incoming Call dialog appears (caller name, room avatar, Answer / Reject).
- The selected ringtone loops until you answer/reject/ignore (at the set volume).
- Answer → joins the call. Reject (DM) / Ignore (group) → dialog dismisses and ring stops.
- Set ringtone to Silent and repeat → dialog still appears, no sound.
A4. In-call banner for a second incoming call — 👥👥 (the trickiest one)
Setup: You (A) already in a call in Room 1. Account B can call you in a different Room 2 (a DM or private group you share). Ideally a third account C, or B leaves Room 1's call first.
- While A is actively in Room 1's call, trigger an incoming call to A from Room 2.
Expected on A
- No full-screen takeover. Instead a compact banner appears in the top-right corner with the caller's avatar, room name, "Incoming voice/video call", and Answer / Reject (or Ignore) buttons.
- It plays a single soft ping, not a looping ring (so it doesn't talk over your active call).
- The banner does not cover your active call's controls/PiP in a way that blocks them.
- Answer → switches you into Room 2's call. Reject/Ignore → banner disappears.
- The banner auto-dismisses if the caller hangs up / the call times out.
Also verify the no-op case: while in Room 1's call, if a notification for Room 1 itself arrives, nothing should pop up (no banner, no dialog).
A5. Camera focus during screenshare (#1) — 👥 2 people
Setup: You (A) and B in a call; B (or another participant) sharing their screen, and at least one person with camera on.
- As A, open the participant glance (the stacked avatars / member list for the call) and click a participant who has their camera on.
- In the menu, click "Focus camera".
Expected
- The view switches to spotlight and pins that person's camera tile, overriding the auto-spotlighted screenshare.
- It stays on that camera (doesn't immediately snap back to the screenshare).
- If you pick someone with their camera off, it should at worst just toggle spotlight (graceful fallback), not error.
A6. Avatar decorations on call tiles (#3) — 👥 2 people
Setup: A participant in the call has an avatar decoration set (Settings → Profile decoration).
- Join a call with that participant.
- Look at our participant roster / prescreen tiles (not the avatars rendered inside the Element Call video grid — those are EC's and out of scope).
Expected: the decoration ring/overlay renders around that participant's avatar on the call tile, the same way it does in member lists.
A7. EC iframe load watchdog + recovery UI (#EC)
This guards against a permanently-stuck "Loading…" call.
- Normal case: join a call → it should connect within a few seconds as usual (the watchdog stays invisible).
- Failure case (best-effort to reproduce): throttle your network hard (devtools → Network → Offline) right as you click join, or block the Element Call origin, so the iframe can't finish loading.
Expected
- On a genuine failure/timeout (~25s), instead of an endless spinner you get a visible error overlay with Retry / Leave buttons.
- Retry attempts to reload the call; Leave exits cleanly.
- Normal joins must not trigger the error overlay (no false positives) — this is the important part to confirm.
B. Polls (N4) — render correctly on non-TDS themes
This was the actual bug: poll buttons used undefined CSS variables, so on the default (non-Lotus-Terminal) themes they rendered with invisible borders / no selected state.
B1. Poll renders on a default theme
- Switch to a default Cinny theme (Settings → Appearance — not Lotus Terminal / TDS). Test both a dark and a light theme.
- In any room, create a poll (composer → poll button): a single-choice poll with 3 options.
Expected
- Each option is a clearly bordered button with visible rounded corners.
- A radio circle indicator is visible on the left of each option.
- Text, and (after votes) the percentage, are legible.
B2. Voting + selected/progress state
- Vote on an option. Expected
- The selected option shows a filled accent border + filled radio, and an accent progress-bar fill grows behind it proportional to the vote %.
- The percentage and total vote count update.
- Click again / pick another option → selection moves correctly (single-choice replaces; the bar redraws).
B3. Multiple-choice poll
- Create a poll allowing multiple selections. Expected
- Indicators are square checkboxes (not circles); selected ones show a ✓ that's legible against the filled box.
- You can select several options; each shows its own progress fill.
B4. Lotus Terminal theme regression
- Switch to Lotus Terminal / TDS theme and re-open a poll. Expected: still looks correct (the fix uses theme tokens, so the TDS accent should now drive it) — no worse than before.
C. Robustness / background behavior
C1. Presence updates on tab close
- Open the app, then close the tab (or quit the browser).
- From another session/device, check your presence shortly after.
Expected: you go offline/away reliably (the unload now uses
fetch({keepalive})). Previously this could be missed.
C2. Upload retry on flaky network (best-effort)
- In devtools → Network, set a throttle that drops/slows requests, or toggle Offline briefly during a file upload. Expected
- A transient failure retries (up to 3×, with backoff) and the upload can still succeed once the network recovers.
- A genuine, permanent rejection (e.g. file too large / 4xx) still fails fast with the usual error — it should not spin retrying.
C3. General timeline/composer perf (no functional regression)
The memoization changes are invisible if correct. Just confirm nothing broke:
- Open a busy room; scrolling, jump-to-latest, mark-as-read all still work.
- Composer: send a message, upload a file, share a location, pick an emoji and a sticker — all still work.
D. Element Call 0.20.1 merge — regression sweep (👥 2 people)
The upstream bump changed EC's internals and DOM selectors; our call controls drive that iframe, so sweep them. In a live call with 2 people, confirm each of our control-bar buttons works:
- Mic mute/unmute (icon + actual audio)
- Camera on/off
- Deafen / Sound toggle (your deafen key too)
- Screenshare start/stop (and the "Share your screen?" confirm)
- Screenshare audio mute toggle
- Fullscreen toggle
- ⋮ More menu → Spotlight/Grid, Reactions, Settings each open the right EC panel
- End call leaves cleanly
- PTT (push-to-talk) if enabled: hold key = transmit, release = mute; releasing on blur works
- AFK auto-mute if enabled: goes muted after the timeout
- PiP (picture-in-picture) mini window: drag, resize, fullscreen button, return-to-call; the "You muted" / "All muted" badges show on the right person
- Denoise (if ML noise suppression enabled): call audio still flows, no silence
If any control does nothing, that usually means an EC DOM selector changed — capture the console and tell me which button.
Backlog of previously-fixed-but-unverified items
Sections A–D above are this session's work. Everything below was fixed in earlier waves and is still flagged ⚠️ UNTESTED in
LOTUS_BUGS.md/LOTUS_TODO.md. They're grouped by what kind of environment you need (mobile, desktop, screen reader, etc.) so you can knock out a whole category at once. None of these are urgent the way A–D are; do them as you have the right device handy.
E. Mobile / responsive (needs a real phone, or devtools device emulation)
E1. Composer toolbar touch targets (#7)
On a phone, open a room and the composer toolbar. Tap each button (attach, format, sticker, emoji, GIF, location, poll, schedule, send). Expected: every button is comfortably tappable (≥44×44px), no mis-taps hitting the wrong icon.
E2. Room Settings — no horizontal overflow (#8)
On a narrow phone screen, open Room Settings. Expected: the settings nav panel fills the full width; no horizontal scrollbar / sideways scrolling anywhere in the panel.
E3. Modals go fullscreen on mobile (#9)
On a phone, open several dialogs: Leave Room, Create Room, Create Space, Invite User, Report (room/user/message), Edit History, Forward Message, Remind Me, Schedule Message, Device Verification, Poll Creator. Expected: each opens fullscreen (no floating box, no rounded corners / max-width margins). On desktop the same modals should still be the normal centered boxes.
E4. Composer not hidden by the keyboard (#10) — iOS Safari especially
On a phone (priority: iOS Safari), tap into the composer so the on-screen keyboard appears. Expected: the composer input stays visible above the keyboard; the layout shrinks rather than the composer sliding under the keyboard.
E5. Mobile "Saved Messages" access (Mobile Bookmarks)
On a phone, inside a room, open the room header ··· More Options menu. Expected: a "Saved Messages" item is present; tapping it opens the bookmarks panel. (This was the only in-room access point missing on mobile.)
F. Visual / theming
F1. Animated chat background — no flicker (#2)
Settings → set an animated chat background (e.g. anim-rain / anim-aurora / anim-stars). Watch the message text and composer while it animates. Expected: smooth animation, no flickering / shimmering on message text or the composer, especially after scrolling. Note your GPU/browser if you see artifacts.
F2. Background vs. Seasonal theme are mutually exclusive (#6)
In Settings → Appearance:
- Pick a chat background → confirm any seasonal theme auto-switches off.
- Pick a seasonal theme → confirm the chat background auto-clears to none.
- (Edge) If you have old data with both set, after reload only one should visibly apply (no double-overlay clutter).
G. Calls — additional unverified (👥 2 people)
G1. PiP mute badges point at the right person (#12)
In a call with at least one other person, pop out the Picture-in-Picture mini window.
- You mute your own mic → a "You"/muted badge appears bottom-left (your status).
- A remote participant (or all of them) mutes → an "All muted" badge appears top-right (clearly about other people). Expected: the bottom-left badge is never triggered by someone else muting — that was the original bug (it looked like your own mic was muted when it wasn't).
G2. Full-screen camera broadcasts
- In a camera-only call (no screenshare), confirm the Fullscreen button is available (previously only showed during screenshare).
- Use MemberGlance → Focus camera to full-screen/spotlight a specific person's camera. (Overlaps A5; if you've done A5 you can skip.)
H. Media / performance (needs a room with many images)
H1. Lazy image decryption (P5-5 / MediaGallery)
Open a room / media gallery with many images (ideally encrypted). Scroll down through them. Expected: images decrypt/load as they approach the viewport, not all at once on open; scrolling stays smooth and memory doesn't balloon. Off-screen images shouldn't all decode up front.
H2. Thumbnail framing (P5-6)
Look at tall portrait images in the timeline and in the media gallery. Expected: thumbnails are framed center-top (so faces/subjects at the top aren't cropped out); no awkward stretching. Opening the full-size viewer still shows the whole image (contain, not cropped).
I. Accessibility (needs a screen reader: VoiceOver / NVDA / TalkBack)
With a screen reader on, navigate message hover-actions and content and confirm each control announces a meaningful label (not "button" / blank):
- Reaction buttons announce the emoji + count (e.g. "thumbsup reaction, 3 people").
- Edit history button announces "View edit history".
- Thread indicator announces "View thread".
- Reply (jump to original) announces "Jump to original message".
J. Desktop / Tauri build only
J1. Proactive update notifications (P5-40)
In the desktop (Tauri) build, with an update available, launch the app (and/or leave it running ~12h). Expected: an in-app toast/badge alerts you that an update is available, without manually checking Settings. (Needs an actual newer release to point at.)
J2. DTLN noise suppression sanity
In Settings → Calls, enable ML noise suppression with the DTLN model, then join a call. Expected: your mic audio still flows (no silence/robotic dropouts) and background noise is reduced. Confirmed working earlier but flagged for a final real-call check; verify on both web and desktop.
K. Features — end-to-end unverified
K1. Remind Me Later
On a message, ··· → Remind Me, pick a short preset (the 20-min one, or wait one out). Expected: when due, a Lotus toast fires linking to that message; the reminder then clears itself. Survives a reload while pending (stored in account data).
K2. Advanced search filters (P4-9)
In message search: use the sender picker (instead of typing from:@user), the date-range quick presets (Today / Last week / Last month / Last year), and the Has link toggle.
Expected: each narrows results correctly and reflects in the search.
K3. Notification content + click target (P5-20 partial)
Trigger a desktop/browser notification for a new message.
Expected: it shows the real message body (username: message, not "New inbox notification from…"); clicking it brings the window to front and navigates directly to that message (not just the inbox).
Priority if you're short on time
- A4 (in-call banner) + A3 (ringtone) — newest, most logic, hardest to reproduce.
- B1–B3 (polls on a default theme) — the confirmed visual bug.
- D (EC 0.20.1 control sweep) — guards against the upstream merge breaking calls.
- A7 false-positive check (normal joins don't show the error overlay).
- Everything else.