Files
EventSnap/docs/MOBILE_TESTING_GUIDE.md
MechaCat02 f7fdfa4627 docs: add mobile testing guide
Comprehensive testing guide for the v0.15.0 mobile-first UI
covering bottom nav, upload FAB/sheet, feed views, search,
account, host/admin dashboards, and edge cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:29:25 +02:00

393 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Mobile Testing Guide — EventSnap v0.15.0
## Setup
### Dev Servers
| Service | URL | Notes |
|---------|-----|-------|
| Frontend | `http://localhost:5173` | Vite dev server, hot-reload |
| Backend API | `http://localhost:3000` | Rust/Axum |
| Database | `localhost:5432` | PostgreSQL (Docker) |
The frontend dev server proxies `/api` and `/media` to the backend automatically.
**Mobile device access:** Connect your phone to the same Wi-Fi network.
Find your machine's local IP (`ip a | grep 192.168` or `hostname -I`), then open
`http://<your-ip>:5173` on your phone.
### Browser DevTools Mobile Emulation (quick testing without a phone)
1. Open Chrome → DevTools (`F12`) → Toggle device toolbar (`Ctrl+Shift+M`)
2. Select **iPhone 14 Pro** or **Pixel 7** from the device dropdown
3. Reload the page — safe-area insets and viewport are emulated
4. To test touch gestures: enable "Touch" in the three-dot menu inside the device toolbar
---
## Test Accounts
Use the following to get all three roles:
| Role | How to get it |
|------|--------------|
| Guest | Join at `/join` with any name |
| Host | Promote a guest via Host Dashboard, or set role in DB |
| Admin | POST to `/api/v1/admin/login` or navigate to `/admin/login` |
Admin password: `admin123` (set in `.env`)
---
## Section 1 — Bottom Navigation Bar
**Goal:** Verify the tab bar is present, thumb-accessible, and correct per role.
### 1.1 Bar Presence & Safe Area
- [ ] Open `/feed` — a bottom tab bar with **Galerie**, a blue circle FAB, and **Konto** appears
- [ ] On a real iPhone/Safari: the bar does **not** overlap the home indicator (safe-area padding)
- [ ] On Chrome DevTools with an iPhone device: the bar is above the viewport bottom
- [ ] Scroll down on a long feed — the bar stays **fixed** at the bottom at all times
- [ ] The bar has a frosted-glass blur effect (`bg-white/90 backdrop-blur-md`)
### 1.2 Active Tab Indicator
- [ ] On `/feed` — the Galerie icon is **blue**; Konto icon is gray
- [ ] Tap **Konto** — navigates to `/account`; Konto icon turns blue, Galerie goes gray
- [ ] Tap **Galerie** — navigates back to `/feed`
### 1.3 Role Gating
- [ ] Log in as a **guest** — bar shows Galerie · FAB · Konto (3 items)
- [ ] Log in as a **host** — same 3 items (dashboard links are inside Account, not the bar)
- [ ] Log in as **admin** — same 3 items
### 1.4 Auth Pages Hide the Bar
- [ ] Visit `/join`**no** bottom bar
- [ ] Visit `/recover`**no** bottom bar
- [ ] Visit `/admin/login`**no** bottom bar
---
## Section 2 — Upload FAB & Bottom Sheet
**Goal:** Verify the FAB opens the upload sheet and both source options work.
### 2.1 FAB Appearance
- [ ] The FAB is a blue circle elevated ~12 px above the tab bar
- [ ] A camera icon with an implicit "+" meaning is shown
- [ ] When uploads are in the queue (pending or uploading), a **red badge number** appears on the FAB
### 2.2 Sheet Opens & Closes
- [ ] Tap the FAB — a bottom sheet slides up smoothly (~300 ms) from below
- [ ] Sheet shows: **Galerie** (blue icon), **Kamera** (purple icon), **Abbrechen**
- [ ] Tap the gray backdrop — sheet slides **back down** and closes
- [ ] Tap **Abbrechen** — sheet closes
- [ ] Swipe the drag handle downward — sheet closes *(if touch gestures are enabled)*
### 2.3 Gallery Source
- [ ] Tap **Galerie** — the native file picker opens
- [ ] Select 13 images or videos
- [ ] Sheet closes; you are navigated to `/upload` (the composer page)
- [ ] Thumbnail strip at the top shows your selected files
- [ ] **Bottom nav is gone** on this page (immersive full-screen)
### 2.4 Camera Source
- [ ] Tap the FAB → **Kamera**
- [ ] Browser asks for camera permission — grant it
- [ ] Full-screen camera UI appears (existing CameraCapture component)
- [ ] Take a photo
- [ ] Camera closes; you are navigated to `/upload` with the captured image in the strip
### 2.5 Upload Composer Page
- [ ] Back `×` button top-left → returns to `/feed`, clears pending files
- [ ] Thumbnail strip scrolls horizontally when >3 files
- [ ] Each thumbnail has a small `×` to remove it — tapping removes that file only
- [ ] Caption `<textarea>` is **auto-focused** (keyboard opens on mobile)
- [ ] Type `#party #spaß` in the caption — **quick-tag chips** appear below the textarea in real time
- [ ] Quick-tag chips are read-only (they reflect what's already in the caption)
- [ ] The **"Hochladen"** sticky button at the bottom shows the file count: "2 Dateien hochladen"
- [ ] Button is **disabled** when the strip is empty
- [ ] Also a smaller "Hochladen" button in the header (convenient on desktop/landscape)
- [ ] Tap **Hochladen** — files are queued, you are returned to `/feed`
- [ ] A **slim blue progress bar** appears just above the bottom tab bar while uploading
- [ ] FAB shows a **red badge** during upload; badge disappears when done
- [ ] A brief "Fertig" / completed state appears in the UploadQueue (check queue store)
---
## Section 3 — Feed: List View
**Goal:** Verify the default chronological list view.
### 3.1 Default State
- [ ] Open `/feed`**list view** is active by default (≡ icon highlighted in the toggle)
- [ ] Posts appear as full-width cards in reverse-chronological order (newest first)
### 3.2 List Card Anatomy
For each card, verify:
- [ ] **Avatar circle** with the uploader's initial letter and a deterministic color
- [ ] **Display name** + **relative timestamp** ("vor 2 Min.", "vor 1 Std.", etc.)
- [ ] **Media**: full-width image, or video with a play button overlay
- [ ] **Caption** below the media (truncated to 3 lines with `...` if long)
- [ ] **Like count** (❤️) and **Comment count** (💬) action buttons
- [ ] Tapping the ❤️ toggles the like optimistically (count changes immediately)
- [ ] Tapping 💬 or the media opens the **Lightbox Modal** (existing behavior, unchanged)
### 3.3 Hashtag Chips (List View Only)
- [ ] Below the main header, hashtag filter chips are visible in **list view**
- [ ] Tap a hashtag chip — feed re-fetches filtered by that tag
- [ ] Tap **Alle** — returns to unfiltered feed
- [ ] Chips are **not visible** when grid view is active
### 3.4 Infinite Scroll
- [ ] Scroll to the bottom — more posts load automatically
- [ ] A spinner appears briefly while loading more
- [ ] Scroll sentinel triggers ~200 px before the actual bottom
### 3.5 Real-Time Updates (SSE)
- [ ] Open the feed on two devices/tabs simultaneously
- [ ] Upload a photo on one — it appears at the **top** of the other's list view in real time
- [ ] Like a post on one — the count updates on the other
---
## Section 4 — Feed: Grid View & Search
**Goal:** Verify the 3-column grid, search bar, autocomplete, and filter chips.
### 4.1 Switching to Grid View
- [ ] Tap the ⊞ grid icon in the header — view switches to a 3-column grid
- [ ] The ≡/⊞ toggle shows ⊞ as active (white background, shadow)
- [ ] Hashtag chips **disappear**; a **search bar** slides in below the header
### 4.2 Grid Layout
- [ ] Grid is **3 columns** with equal square cells (no 2-column fallback on mobile)
- [ ] Videos show a ▶ play button overlay
- [ ] Tapping a cell opens the Lightbox Modal
- [ ] Grid background is seamless (0.5px gap between cells)
### 4.3 Search Bar
- [ ] Search bar shows: 🔍 icon, placeholder "Nutzer oder #Tag suchen…", × clear button
- [ ] Tapping the bar focuses it and opens the keyboard
- [ ] × button appears only when there is text in the input; tapping it clears the query
### 4.4 Autocomplete — On Focus (Empty)
- [ ] Focus the search bar with no text — a dropdown appears with:
- Up to 3 uploader names (person icon)
- Up to 3 popular tags (#)
- [ ] The dropdown disappears when the input loses focus (150 ms delay)
### 4.5 Autocomplete — Tag Suggestions
- [ ] Type `#` — only **tag suggestions** appear (no users), sorted by frequency
- [ ] Type `#par` — only tags starting with "par" remain (e.g. `#party`, `#parade`)
- [ ] Tap a suggestion — it's added as a **blue filter chip** below the search bar; input clears
### 4.6 Autocomplete — User Suggestions
- [ ] Type a partial name (e.g. `max`) — users matching "max" appear first, then tags containing "max"
- [ ] Tap a user suggestion — chip added: shows the name without `#` prefix
### 4.7 Filter Chips
- [ ] After selecting a tag filter — grid shows only posts with that tag in the caption
- [ ] Select a second tag — grid shows posts with **either** tag (OR logic)
- [ ] Select a user **and** a tag — grid shows posts by that user **that also** have that tag (AND across types)
- [ ] Each chip has an **× remove button**; tapping it removes only that chip
- [ ] When 2+ chips are active: **"Alle löschen"** link appears; tapping clears all filters
- [ ] When no results match: "Keine Treffer für die gewählten Filter." + "Filter zurücksetzen" button
### 4.8 Switching Back to List View
- [ ] Tap ≡ — list view returns; search bar gone; hashtag chips reappear
- [ ] Active grid filters are **reset** when switching back to list (no stale state)
---
## Section 5 — Account Page
**Goal:** Verify the profile card, dashboard links, and leave-confirm flow.
### 5.1 Profile Card
- [ ] Open `/account` via the Konto tab
- [ ] **Avatar circle** shows your initial letter in a deterministic color
- [ ] **Display name** and **role badge** (Gast / Gastgeber / Admin) shown
- [ ] Session expiry date shown in small text below
### 5.2 Dashboard Links (Host/Admin Only)
- [ ] Log in as a **guest** — no "Dashboards" section visible at all
- [ ] Log in as a **host** — "Dashboards" section shows ⭐ **Host-Dashboard** → chevron
- [ ] Tapping it navigates to `/host`
- [ ] No Admin-Dashboard link visible
- [ ] Log in as **admin** — both links appear:
- [ ] ⭐ Host-Dashboard → `/host`
- [ ] 🛡 Admin-Dashboard → `/admin`
### 5.3 PIN Card
- [ ] Amber card shows the 4-digit PIN in large monospace font
- [ ] **Kopieren** button copies to clipboard; label changes to "Kopiert!" for 2 seconds
- [ ] If no PIN is stored: fallback message shown
### 5.4 Konto Section
- [ ] **Gerät wechseln / PIN nutzen** → navigates to `/recover`
- [ ] **Event verlassen** (red text) → tapping opens a **leave-confirm bottom sheet**
- [ ] Sheet shows: "Event verlassen?", "Du wirst abgemeldet…", red "Abmelden" + "Abbrechen"
- [ ] Tap backdrop — sheet closes, you remain logged in
- [ ] Tap **Abbrechen** — same
- [ ] Tap **Abmelden** — you are logged out and redirected to `/join`
### 5.5 No Stale Nav Links
- [ ] **No** "Zur Galerie" link in the header (navigation is via the bottom bar)
---
## Section 6 — Host Dashboard
**Goal:** Verify the back arrow, collapsible sections, and all existing host actions still work.
### 6.1 Navigation
- [ ] Open Host Dashboard via Account → ⭐ Host-Dashboard
- [ ] Page shows a **← back arrow** in the top-left header
- [ ] Tapping it navigates to `/account`
- [ ] **No** shield/gallery header icons (removed)
- [ ] Bottom tab bar is still visible
### 6.2 Statistiken Section (Collapsible)
- [ ] Section is **expanded** by default with a downward chevron
- [ ] Shows a 2×2 grid of stat cards: Gäste, Uploads, Uploads status (Offen/Gesperrt), Freigegeben (Ja/Nein)
- [ ] Numbers are large and readable on mobile
- [ ] Tap the **Statistiken** header button — section collapses (smooth max-height animation)
- [ ] Chevron rotates 180° to point upward when collapsed
- [ ] Tap again — section expands
### 6.3 Event-Einstellungen Section (Collapsible)
- [ ] Collapse/expand works same as above
- [ ] Shows **"Uploads sperren"** (amber) / **"Uploads wieder öffnen"** (green) button
- [ ] Shows **"Galerie freigeben"** (blue) / "Galerie bereits freigegeben" (disabled gray)
- [ ] Tap "Uploads sperren" — toast confirms, button switches to "Uploads wieder öffnen"
- [ ] Existing functionality unchanged
### 6.4 Nutzerverwaltung Section (Collapsible)
- [ ] **Search bar** at top of section filters the user list in real time (client-side)
- [ ] Each user row shows name, role badge, banned badge (if applicable), upload count/bytes
- [ ] **Sperren** button triggers the existing ban modal (confirm + hide-uploads checkbox)
- [ ] **Entsperren** appears for banned users
- [ ] **Host** button promotes a guest to host role
- [ ] **Degradieren** appears for hosts (admin only)
- [ ] Toast notifications appear above the bottom bar (not obscured by it)
---
## Section 7 — Admin Dashboard
**Goal:** Verify the inner tab bar, all 4 tabs, and the new Nutzer tab.
### 7.1 Navigation
- [ ] Open Admin Dashboard via Account → 🛡 Admin-Dashboard
- [ ] Page shows **← back arrow** → `/account`
- [ ] **No** star/gallery header icons
- [ ] Bottom tab bar visible
### 7.2 Inner Tab Bar
- [ ] A second tab bar appears **below the main header**, sticky on scroll
- [ ] 4 tabs: **Stats · Config · Export · Nutzer**
- [ ] Active tab has a blue bottom border and blue text
- [ ] Inactive tabs are gray
- [ ] Tabs are scrollable horizontally (try narrowing viewport)
- [ ] Switching tabs is instant with no page reload
### 7.3 Stats Tab
- [ ] Shows a **2×2 grid** of metric cards: Gäste, Uploads, Kommentare, Speicher %
- [ ] Values are large (`text-3xl`)
- [ ] Below the grid: a full-width disk usage bar with color coding
- Blue ≤ 74%, Amber 7589%, Red ≥ 90%
- [ ] Exact used/total/free values shown
### 7.4 Config Tab
- [ ] Shows stacked label + full-width input for each of the 8 config keys
- [ ] Inputs are `type="number"` with large touch targets
- [ ] A **"Speichern"** button is **sticky at the bottom** of the tab (always visible, even on long scroll)
- [ ] Edit a value → tap Speichern → toast "Konfiguration gespeichert."
- [ ] Tap Speichern with no changes → toast "Keine Änderungen."
### 7.5 Export Tab
- [ ] **"Galerie freigeben"** button triggers gallery release
- [ ] **"Aktualisieren"** button refreshes the jobs list only (no full page flash)
- [ ] Export jobs listed with status chips: Ausstehend (gray) / Läuft (blue) / Fertig (green) / Fehlgeschlagen (red)
- [ ] Running jobs show a progress bar
- [ ] Failed jobs show the error message in red
### 7.6 Nutzer Tab (New)
- [ ] Users are loaded from `/host/users` (admin shares host permissions)
- [ ] **Search bar** filters list in real time
- [ ] Same ban/unban/promote/demote actions as Host dashboard
- [ ] After an action (e.g. ban) only the users list refreshes, not the whole page
---
## Section 8 — Toast Position
- [ ] On host/admin pages, toasts appear at `bottom-24` (above the bottom nav bar)
- [ ] Toasts are **not** obscured by the nav bar
---
## Section 9 — Desktop Usability (Second Citizen)
**Goal:** Confirm all pages are still usable on a wide viewport.
### 9.1 Layout Centering
- [ ] On a 1280px+ viewport, all pages center their content at `max-w-2xl` or `max-w-3xl`
- [ ] Bottom tab bar spans full width but content columns remain centered
- [ ] No content is clipped or overflows horizontally
### 9.2 Feed Desktop
- [ ] List view: cards are centered, readable at 672px max width
- [ ] Grid view: 3 columns at max-width — cells are larger and look good
- [ ] Search bar is full-width within the max-width container
### 9.3 Upload Composer Desktop
- [ ] Upload page is full-height, centered column
- [ ] Both the header "Hochladen" button AND the sticky bottom button are present
- [ ] Desktop users can click the header button (more convenient without reaching to bottom)
### 9.4 Host / Admin Desktop
- [ ] Host collapsible sections work with mouse clicks
- [ ] Admin inner tabs work with mouse clicks; all 4 tabs visible without scrolling at 1280px
- [ ] Config tab sticky save is visible on desktop scroll
---
## Section 10 — Edge Cases
### 10.1 Upload with No Files Selected
- [ ] Navigate directly to `/upload` in the browser
- [ ] No files pending → "Keine Dateien ausgewählt" screen shown with "Zurück" button
- [ ] "Hochladen" button is disabled
### 10.2 Rate Limiting
- [ ] Upload rapidly beyond the configured limit (default: 10/hour)
- [ ] A `429` response is received
- [ ] The countdown banner appears above the bottom nav: "Upload-Limit erreicht. Wird in X Sek. automatisch fortgesetzt."
- [ ] After the countdown, the queue resumes automatically
### 10.3 SSE Reconnect
- [ ] Stop the backend briefly and restart
- [ ] The feed reconnects (SSE) — new uploads appear once the backend is back
### 10.4 Back Navigation from Upload
- [ ] Pick files → navigate to `/upload`
- [ ] Tap `×` → files are discarded (`clearPending()` runs, object URLs are revoked)
- [ ] Navigate back to `/upload` directly — "Keine Dateien ausgewählt" shown (not stale files)
### 10.5 Grid Filter Persistence
- [ ] Set a filter chip in grid view
- [ ] Switch to list view — filter is cleared (list always shows full unfiltered feed)
- [ ] Switch back to grid — search bar is empty, no stale chips
---
## Known Limitations (Not Bugs)
| Item | Status |
|------|--------|
| "Anzeigename ändern" in Account | Deferred — shown as disabled; requires `/me` PATCH endpoint |
| Upload count in Account profile card | Deferred — requires `/me` GET endpoint |
| CSS collapse animation on host sections | Uses `max-h` trick; may be slightly sluggish for very large user lists |
| Autocomplete results | Derived from currently-loaded posts only; new posts via SSE update the pool automatically |