mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 20:49:41 +02:00
Follow-up to #390. PHONE_MAX had become 599, an inclusive bound, while three of its four consumers still read it as exclusive (width < PHONE_MAX for phone); the one site that switched to <= disagreed with getDeviceType(). It is 600 again with < at every site. The breakpoint table in docs/mobile-testing-report.md says 600, and the three 430px visual baselines are removed: they depict the tablet tier now, and the visual suite recreates a missing baseline on its next run on the machine that owns them. device-matrix.test.ts is also run through Prettier, which the commit hook demanded and the format gate (src/ only) never did. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
229 lines
8.4 KiB
Markdown
229 lines
8.4 KiB
Markdown
# Mobile E2E Testing Report
|
|
|
|
**Date**: 2026-01-31
|
|
**Status**: All 32 tests passing
|
|
|
|
## Overview
|
|
|
|
Comprehensive mobile E2E testing was performed using Playwright with Chromium in mobile emulation mode. Tests validate touch interactions, responsive design, mobile-specific UI behaviors, and edge cases across various device viewports.
|
|
|
|
## Test Coverage Summary
|
|
|
|
| Test File | Tests | Description |
|
|
|-----------|-------|-------------|
|
|
| `mobile-safari.e2e.ts` | 6 | Core mobile Safari/iPhone tests |
|
|
| `mobile-comprehensive.e2e.ts` | 13 | UI components, modals, interactions |
|
|
| `mobile-edge-cases.e2e.ts` | 13 | Edge cases: orientation, narrow screens, safe areas |
|
|
|
|
## Bugs Found and Fixed
|
|
|
|
### 1. Monitor Panel Overlapping Toolbar on Mobile
|
|
|
|
**File**: `src/web/public/styles.css` (lines 7969-7982)
|
|
|
|
**Problem**: The monitor panel was positioned at `bottom: var(--toolbar-height)` (40px), but the mobile toolbar has `height: auto` with `flex-wrap: wrap`, causing it to be taller than 40px. This resulted in the monitor panel header intercepting tap events on the "Run Claude" button.
|
|
|
|
**Error message**:
|
|
```
|
|
<div class="monitor-panel-title">Monitor</div> from <div id="monitorPanel" class="monitor-panel">…</div> subtree intercepts pointer events
|
|
```
|
|
|
|
**Fix**: Hide monitor and subagents panels on phones by default:
|
|
```css
|
|
@media (max-width: 430px) {
|
|
.monitor-panel,
|
|
.subagents-panel {
|
|
display: none !important;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Rationale**: On phone screens (<430px), there isn't enough space for these panels anyway. Users can still access session info via the header and session options modal.
|
|
|
|
---
|
|
|
|
### 2. WebKit Browser Missing System Dependencies
|
|
|
|
**File**: `test/e2e/fixtures/mobile-browser.fixture.ts`
|
|
|
|
**Problem**: WebKit requires system libraries (libgtk-4, libgstreamer, etc.) that may not be installed on all systems, causing mobile tests to fail.
|
|
|
|
**Fix**: Added fallback to Chromium with mobile emulation:
|
|
```typescript
|
|
try {
|
|
browser = await webkit.launch({ headless: true });
|
|
userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X)...';
|
|
} catch {
|
|
// WebKit failed, use Chromium with mobile emulation
|
|
browser = await chromium.launch({ headless: true, args: [...] });
|
|
userAgent = 'Mozilla/5.0 (Linux; Android 14; Pixel 8)...';
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Race Condition in Session Tab Detection
|
|
|
|
**File**: `test/e2e/workflows/mobile-safari.e2e.ts`
|
|
|
|
**Problem**: Test waited for `.session-tab` selector but then checked `.session-tab.active`, causing timing issues where the tab existed but wasn't yet marked as active.
|
|
|
|
**Fix**: Wait for the active tab directly:
|
|
```typescript
|
|
// Before (race condition)
|
|
await page.waitForSelector('.session-tab', { timeout: ... });
|
|
const tabVisible = await page.isVisible('.session-tab.active');
|
|
|
|
// After (correct)
|
|
await page.waitForSelector('.session-tab.active', { timeout: ... });
|
|
const tabVisible = await page.isVisible('.session-tab.active');
|
|
```
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
### No Kill All Button on Mobile
|
|
|
|
**Status**: By design (not a bug)
|
|
|
|
The "Kill All" button is located in the Monitor panel, which is hidden on mobile devices (<430px). Users can close sessions individually via the close button on each session tab.
|
|
|
|
**Consideration for future**: Could add a "Kill All" option in the app settings modal or a long-press context menu on session tabs.
|
|
|
|
### No Help Button on Mobile
|
|
|
|
**Status**: By design
|
|
|
|
There is no dedicated help button in the mobile UI. Help is accessible via:
|
|
- Keyboard shortcut (`?` key)
|
|
- App settings modal
|
|
|
|
---
|
|
|
|
## Test Coverage
|
|
|
|
### mobile-safari.e2e.ts (Port 3191)
|
|
|
|
| Test | Description |
|
|
|------|-------------|
|
|
| Touch-friendly UI rendering | Verifies `touch-device` and `device-mobile` body classes |
|
|
| 44px minimum touch targets | Ensures buttons meet WCAG AA touch target requirements |
|
|
| Tap gestures for session creation | Creates session via tap on Run Claude button |
|
|
| Always-visible close buttons | Verifies opacity:1 on touch devices (no hover dependency) |
|
|
| Header hiding on small screens | Brand, stats, font controls hidden on phones |
|
|
| Tablet viewport rendering | iPad Pro 11" (834x1194) renders with `device-desktop` + `touch-device` |
|
|
|
|
### mobile-comprehensive.e2e.ts (Port 3192)
|
|
|
|
| Test | Description |
|
|
|------|-------------|
|
|
| Welcome overlay buttons | Touch-friendly welcome overlay with 44px+ button height |
|
|
| Run Claude button prominence | Button visible with `flex: 1` on mobile |
|
|
| Case dropdown visibility | Dropdown accessible and functional |
|
|
| Version display hiding | `.toolbar-center` hidden on phones |
|
|
| Horizontal tab scrolling | Session tabs allow `overflow-x: auto` scrolling |
|
|
| Tab switching on tap | Tapping tabs switches active session |
|
|
| Full-screen modals | Modals use 100% width/height on phones |
|
|
| Create case modal | Case creation modal accessible via + button |
|
|
| Notification button | Notification bell visible and tappable |
|
|
| Settings button | Settings gear has adequate touch target |
|
|
| Close confirmation modal | Close button triggers confirmation dialog |
|
|
| Token count display | Token counter visible in header |
|
|
| Ralph wizard full-screen | Wizard modal renders full-screen |
|
|
|
|
### mobile-edge-cases.e2e.ts (Port 3193)
|
|
|
|
| Test | Description |
|
|
|------|-------------|
|
|
| Landscape orientation handling | 874x402 landscape mode with proper classes |
|
|
| Terminal in landscape | Terminal renders with adequate height |
|
|
| Very narrow viewport (280px) | Galaxy Fold folded state usable |
|
|
| Narrow screen toolbar | Toolbar doesn't overflow on 280px |
|
|
| Session options via gear icon | Gear icon visible, modal opens on tap |
|
|
| Modal tab switching | Session options modal tabs work on touch |
|
|
| Terminal tap interactions | Terminal responds to touch events |
|
|
| Primary touch targets | Main buttons meet 44px height requirement |
|
|
| iOS safe area CSS variables | `--safe-area-*` variables defined |
|
|
| Double-tap zoom prevention | touch-action styles applied |
|
|
| Modal body scrolling | `overflow-y: auto` for touch scrolling |
|
|
| Viewport meta tag | Proper mobile viewport configuration |
|
|
| Android Pixel viewport | 412x915 Pixel 7a renders correctly |
|
|
|
|
---
|
|
|
|
## Mobile CSS Breakpoints
|
|
|
|
| Breakpoint | Class | Description |
|
|
|------------|-------|-------------|
|
|
| < 600px | `device-mobile` | Phone - most features hidden/simplified |
|
|
| 600-768px | `device-tablet` | Tablet - intermediate layout |
|
|
| > 768px | `device-desktop` | Desktop - full features |
|
|
|
|
Touch devices also get `touch-device` class regardless of screen size.
|
|
|
|
---
|
|
|
|
## Viewports Tested
|
|
|
|
| Device | Width | Height | Scale | Notes |
|
|
|--------|-------|--------|-------|-------|
|
|
| iPhone 17 Pro | 402 | 874 | 3x | Primary phone test |
|
|
| iPhone 17 Pro Landscape | 874 | 402 | 3x | Orientation testing |
|
|
| iPhone 17 Pro Max | 440 | 956 | 3x | Larger phone |
|
|
| iPad Pro 11" | 834 | 1194 | 2x | Tablet testing |
|
|
| Galaxy Fold (folded) | 280 | 653 | 3x | Extreme narrow test |
|
|
| Pixel 7a | 412 | 915 | 2.625x | Android testing |
|
|
|
|
---
|
|
|
|
## Running Mobile Tests
|
|
|
|
```bash
|
|
# Install Playwright browsers (Chromium is required, WebKit optional)
|
|
npx playwright install chromium
|
|
|
|
# Run individual test files
|
|
npx vitest run test/e2e/workflows/mobile-safari.e2e.ts
|
|
npx vitest run test/e2e/workflows/mobile-comprehensive.e2e.ts
|
|
npx vitest run test/e2e/workflows/mobile-edge-cases.e2e.ts
|
|
|
|
# Run all mobile tests together
|
|
npx vitest run test/e2e/workflows/mobile-safari.e2e.ts test/e2e/workflows/mobile-comprehensive.e2e.ts test/e2e/workflows/mobile-edge-cases.e2e.ts
|
|
```
|
|
|
|
---
|
|
|
|
## Port Allocations
|
|
|
|
| Port | Test File |
|
|
|------|-----------|
|
|
| 3191 | mobile-safari.e2e.ts |
|
|
| 3192 | mobile-comprehensive.e2e.ts |
|
|
| 3193 | mobile-edge-cases.e2e.ts |
|
|
|
|
---
|
|
|
|
## Key Mobile UI Behaviors
|
|
|
|
1. **Monitor/Subagents panels**: Hidden on phones (<430px)
|
|
2. **Toolbar**: Wraps content with `flex-wrap: wrap`, variable height
|
|
3. **Session tabs**: Horizontal scroll with hidden scrollbar
|
|
4. **Modals**: Full-screen on phones (100% width/height)
|
|
5. **Touch targets**: Minimum 44px height for WCAG compliance
|
|
6. **Close buttons**: Always visible (opacity: 1) on touch devices
|
|
7. **Header**: Brand, stats, font controls hidden on phones
|
|
8. **Safe areas**: CSS variables for iOS notch handling
|
|
|
|
---
|
|
|
|
## Future Improvements
|
|
|
|
1. Add swipe gesture tests for tab navigation
|
|
2. Add virtual keyboard handling tests (show/hide behavior)
|
|
3. Add orientation change tests (dynamic portrait/landscape switching)
|
|
4. Add safe area inset tests for iOS notch handling with actual device values
|
|
5. Consider showing a condensed monitor indicator on mobile
|
|
6. Add "Kill All" option accessible from mobile UI
|
|
7. Test pull-to-refresh prevention on iOS Safari
|