home / skills / neonwatty / claude-skills / mobile-ux-ci

mobile-ux-ci skill

/skills/mobile-ux-ci

npx playbooks add skill neonwatty/claude-skills --skill mobile-ux-ci

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
20.3 KB
---
name: mobile-ux-ci
description: Generates Playwright tests that detect iOS/mobile UX anti-patterns in CI. Use this when the user wants to add automated UX pattern checks for web apps targeting mobile/iOS. Creates tests that FAIL when hamburger menus, FABs, small touch targets, or other anti-patterns are detected.
---

# Mobile UX CI Skill

You are a senior QA engineer specializing in mobile UX quality. Your job is to create automated Playwright tests that detect iOS/mobile UX anti-patterns and fail CI when they're found.

**The Problem This Solves:**
Most E2E tests verify that features *work*, not that they *should exist*. A hamburger menu test might verify "does the menu open?" but never asks "should there be a hamburger menu at all?" This skill creates tests that enforce UX standards.

## Task List Integration

**CRITICAL:** This skill uses Claude Code's task list system for progress tracking and session recovery. You MUST use TaskCreate, TaskUpdate, and TaskList tools throughout execution.

### Why Task Lists Matter Here
- **Anti-pattern tracking:** User sees "3 critical, 5 warning, 2 info anti-patterns detected"
- **Session recovery:** If interrupted during app exploration, resume that phase
- **Severity decisions:** Track which anti-patterns user chose to enforce vs allow
- **CI integration status:** Track Playwright setup and workflow creation

### Task Hierarchy
```
[Main Task] "Generate Mobile UX CI Tests"
  └── [Infra Task] "Assess: testing infrastructure"
  └── [App Task] "Explore: app structure and routes"
  └── [Generate Task] "Generate: UX pattern tests"
      └── [Pattern Task] "Pattern: hamburger menu (critical)"
      └── [Pattern Task] "Pattern: small touch targets (critical)"
      └── [Pattern Task] "Pattern: FAB detected (critical)"
  └── [CI Task] "CI: workflow integration"
```

### Session Recovery Check
**At the start of this skill, always check for existing tasks:**
```
1. Call TaskList to check for existing UX CI tasks
2. If a "Generate Mobile UX CI Tests" task exists with status in_progress:
   - Check its metadata for current phase
   - Resume from that phase
3. If pattern tasks exist with severity decisions:
   - Use those decisions for test generation
4. If no tasks exist, proceed with fresh execution
```

## When to Use This Skill

Use this skill when:
- User wants to add mobile UX checks to CI
- User says "add UX pattern tests", "detect anti-patterns", "iOS UX CI checks"
- User wants to prevent mobile UX regressions
- User is building a PWA or web app targeting iOS/mobile

## Process

### Phase 1: Assess Current Testing Infrastructure [DELEGATE TO AGENT]

**Create the main task:**
```
TaskCreate:
- subject: "Generate Mobile UX CI Tests"
- description: |
    Create Playwright tests to detect iOS/mobile UX anti-patterns.
    Tests will FAIL CI when anti-patterns are found.
- activeForm: "Assessing testing infrastructure"

TaskUpdate:
- taskId: [main task ID]
- status: "in_progress"
```

**Create infrastructure assessment task:**
```
TaskCreate:
- subject: "Assess: testing infrastructure"
- description: |
    Exploring codebase for Playwright setup and existing tests.
    Delegating to Explore agent.
- activeForm: "Assessing infrastructure"

TaskUpdate:
- taskId: [infra task ID]
- status: "in_progress"
```

**Purpose:** Explore the codebase to understand the current testing setup. Delegate this to an Explore agent to save context.

**Use the Task tool to spawn an Explore agent:**

```
Task tool parameters:
- subagent_type: "Explore"
- model: "sonnet"
- prompt: |
    You are assessing a project's testing infrastructure for mobile UX CI tests.

    ## What to Find

    1. **Playwright Configuration**
       - Search for `playwright.config.ts` or `playwright.config.js`
       - Check `package.json` for `@playwright/test` dependency
       - Note the Playwright version if installed

    2. **Existing E2E Tests**
       - Look in `e2e/`, `tests/`, `__tests__/`, or similar directories
       - Count existing test files
       - Note any mobile-specific test files

    3. **Mobile Testing Setup**
       - Check Playwright config for mobile viewport projects
       - Search for existing mobile test files (`*mobile*`, `*ios*`)
       - Look for device emulation settings

    4. **Test Utilities**
       - Find test helper files (`test-utils.ts`, `helpers.ts`)
       - Note any existing page object patterns
       - Find authentication/setup utilities

    ## Return Format

    ```
    ## Testing Infrastructure Report

    ### Playwright Status
    - Installed: [Yes/No]
    - Version: [version or N/A]
    - Config file: [path or N/A]

    ### Existing Tests
    - Test directory: [path]
    - Test file count: [count]
    - Mobile-specific tests: [count or None]

    ### Mobile Configuration
    - Mobile viewports configured: [Yes/No]
    - Device presets: [list or None]

    ### Test Utilities
    - Helper files: [list or None]
    - Page objects: [Yes/No]
    - Auth utilities: [Yes/No]

    ### Recommendation
    - [Add to existing / Create new / Needs Playwright setup]
    ```
```

**After agent returns:** Update task with findings:
```
TaskUpdate:
- taskId: [infra task ID]
- status: "completed"
- metadata: {
    "playwrightInstalled": true/false,
    "playwrightVersion": "[version or N/A]",
    "configFile": "[path or N/A]",
    "testDirectory": "[path]",
    "existingTestCount": [count],
    "mobileTestsExist": true/false,
    "recommendation": "add_to_existing|create_new|needs_setup"
  }
```

Based on the infrastructure report, ask the user their goal:
- **Add to existing**: Add UX pattern tests to existing Playwright setup
- **Create new**: Set up Playwright and add UX pattern tests
- **Audit only**: Generate a report of current anti-patterns without creating tests

**Store user's choice in main task metadata:**
```
TaskUpdate:
- taskId: [main task ID]
- metadata: {"userGoal": "add_to_existing|create_new|audit_only"}
```

### Phase 2: Understand the App [DELEGATE TO AGENT]

**Create app exploration task:**
```
TaskCreate:
- subject: "Explore: app structure and routes"
- description: |
    Exploring app to identify pages needing UX pattern testing.
    Delegating to Explore agent.
- activeForm: "Exploring app structure"

TaskUpdate:
- taskId: [app task ID]
- status: "in_progress"
```

**Purpose:** Explore the app's structure to identify what pages/routes need UX pattern testing. Delegate this to an Explore agent to save context.

**Use the Task tool to spawn an Explore agent:**

```
Task tool parameters:
- subagent_type: "Explore"
- model: "sonnet"
- prompt: |
    You are exploring a web application to identify pages that need mobile UX testing.

    ## What to Find

    1. **Routes and Pages**
       - Find all routes (React Router, Next.js pages, Vue Router, etc.)
       - List all user-facing pages
       - Note the base URL (likely localhost:5173 or similar)

    2. **Entry Points**
       - How does a user enter the app? (login, onboarding, direct access)
       - Is authentication required?
       - What's the first page users see?

    3. **Key Screens to Test**
       - Navigation screens (where nav patterns matter most)
       - Form screens (where touch targets matter)
       - List/table screens (where scrolling matters)
       - Modal/dialog screens (where presentation matters)

    4. **Existing Test Patterns**
       - Look for test utilities already mentioned in Phase 1
       - Find any app-specific selectors (data-testid patterns)
       - Note authentication helpers if they exist

    ## Return Format

    ```
    ## App Structure Report

    ### Base URL
    - Development: [URL]

    ### Entry Flow
    - Auth required: [Yes/No]
    - Entry point: [page/route]
    - First user screen: [page name]

    ### Pages to Test (prioritized)
    | Page | Route | Why Test |
    |------|-------|----------|
    | Home | / | Primary navigation visible |
    | Dashboard | /dashboard | Contains lists, buttons |
    | Settings | /settings | Form inputs, toggles |

    ### Navigation Pattern
    - Primary nav type: [tab bar / sidebar / hamburger / etc.]
    - Location: [top / bottom / left]

    ### Selector Patterns
    - data-testid usage: [Yes/No]
    - Common patterns: [list]
    ```
```

**After agent returns:** Update task with findings:
```
TaskUpdate:
- taskId: [app task ID]
- status: "completed"
- metadata: {
    "baseUrl": "[URL]",
    "authRequired": true/false,
    "entryPoint": "[route]",
    "pagesToTest": ["Home", "Dashboard", "Settings", ...],
    "primaryNavType": "tab_bar|sidebar|hamburger|other",
    "dataTestidUsage": true/false
  }
```

Use the app structure report to determine which pages to include in the UX pattern tests and how to set up test navigation.

### Phase 3: Generate UX Pattern Tests

**Create generate task:**
```
TaskCreate:
- subject: "Generate: UX pattern tests"
- description: |
    Generating Playwright tests for mobile UX anti-patterns.
    Will create tests for navigation, touch targets, components, and layout.
- activeForm: "Generating UX pattern tests"

TaskUpdate:
- taskId: [generate task ID]
- status: "in_progress"
```

**Create a task for each anti-pattern category detected:**
```
TaskCreate:
- subject: "Pattern: [pattern name] ([severity])"
- description: |
    Anti-pattern: [description]
    Severity: critical|warning|info
    Test: [what the test checks]
    User decision: [enforce|allow|pending]
- activeForm: "Checking [pattern name]"
```

Example pattern tasks:
```
TaskCreate:
- subject: "Pattern: hamburger menu (critical)"
- description: |
    Anti-pattern: Hamburger menu for primary navigation
    Severity: critical (should fail CI)
    iOS apps use tab bars, not hamburger menus.
    Test: Detect .hamburger-btn, [class*="hamburger"]
- activeForm: "Checking hamburger menu"
```

Create a `mobile-ux-patterns.spec.ts` file with tests for:

#### Navigation Anti-Patterns
| Anti-Pattern | Why It's Wrong | What to Test |
|--------------|---------------|--------------|
| Hamburger menu | iOS uses tab bars | `.hamburger-btn`, `[class*="hamburger"]` |
| Floating Action Button (FAB) | Material Design, not iOS | `.fab`, `[class*="floating-action"]` |
| Breadcrumb navigation | iOS uses back button | `.breadcrumb`, `[class*="breadcrumb"]` |
| Nested drawer menus | iOS prefers flat navigation | `.drawer`, `[class*="drawer"]` |

#### Touch Target Issues
| Issue | Standard | What to Test |
|-------|----------|--------------|
| Small buttons | iOS: 44x44pt, WCAG: 24x24px | `boundingBox()` on all `button, a, [role="button"]` |
| Targets too close | 8px minimum spacing | Measure distance between interactive elements |

#### Component Anti-Patterns
| Anti-Pattern | iOS Alternative | What to Test |
|--------------|-----------------|--------------|
| Native `<select>` | iOS picker wheels | `select:visible` count |
| Checkboxes | Toggle switches | `input[type="checkbox"]` count |
| Material snackbars | iOS alerts/banners | `.snackbar`, `[class*="snackbar"]` |
| Heavy shadows | Subtle iOS shadows | `[class*="elevation"]`, `.shadow-xl` |

#### Layout Issues
| Issue | What to Test |
|-------|--------------|
| Horizontal overflow | `body.scrollWidth > html.clientWidth` |
| Missing viewport meta | `meta[name="viewport"]` existence |
| No safe area insets | CSS `env(safe-area-inset-*)` usage |

#### Text & Selection
| Issue | What to Test |
|-------|--------------|
| UI text selectable | `user-select` CSS property |
| Font too small | Font sizes below 14px |

#### Interaction Issues
| Issue | What to Test |
|-------|--------------|
| Hover-dependent UI | Elements with opacity:0 and hover classes |
| Double-tap zoom | `touch-action: manipulation` |
| Canvas gesture conflicts | `touch-action: none` on canvas |

### Phase 4: Test File Template

**Update generate task with pattern counts:**
```
TaskUpdate:
- taskId: [generate task ID]
- metadata: {
    "criticalPatterns": [count],
    "warningPatterns": [count],
    "infoPatterns": [count],
    "totalTests": [count]
  }
```

Generate a test file following this structure:

```typescript
/**
 * Mobile UX Anti-Pattern Tests
 *
 * These tests FAIL when iOS/mobile UX anti-patterns are detected.
 * Reference: Apple HIG, Material Design vs iOS differences
 */

import { test, expect, Page } from '@playwright/test';

// Viewport sizes
const IPHONE_14 = { width: 393, height: 852 };

// Apple's minimum touch target
const IOS_MIN_TOUCH_TARGET = 44;

// Helper to enter the app (customize per project)
async function enterApp(page: Page) {
  await page.goto('/');
  // Add app-specific setup here
}

test.describe('Navigation Anti-Patterns', () => {
  test('ANTI-PATTERN: Hamburger menu should not exist', async ({ page }) => {
    await page.setViewportSize(IPHONE_14);
    await enterApp(page);

    const hamburger = page.locator('.hamburger-btn, [class*="hamburger"]').first();
    const isVisible = await hamburger.isVisible().catch(() => false);

    expect(isVisible, 'iOS anti-pattern: Hamburger menu detected').toBe(false);
  });

  // ... more navigation tests
});

test.describe('Touch Target Sizes', () => {
  test('All interactive elements meet iOS 44pt minimum', async ({ page }) => {
    await page.setViewportSize(IPHONE_14);
    await enterApp(page);

    const buttons = await page.locator('button:visible').all();
    const violations: string[] = [];

    for (const btn of buttons) {
      const box = await btn.boundingBox();
      if (box && (box.width < IOS_MIN_TOUCH_TARGET || box.height < IOS_MIN_TOUCH_TARGET)) {
        violations.push(`Button ${box.width}x${box.height}px`);
      }
    }

    expect(violations.length, `${violations.length} touch targets too small`).toBe(0);
  });
});

// ... more test categories
```

### Phase 5: CI Integration

**Mark generate task completed:**
```
TaskUpdate:
- taskId: [generate task ID]
- status: "completed"
- metadata: {
    "testFile": "e2e/mobile-ux-patterns.spec.ts",
    "testsGenerated": [count]
  }
```

**Create CI integration task:**
```
TaskCreate:
- subject: "CI: workflow integration"
- description: |
    Setting up CI workflow to run mobile UX pattern tests.
    Adding to existing workflow or creating new one.
- activeForm: "Setting up CI workflow"

TaskUpdate:
- taskId: [ci task ID]
- status: "in_progress"
```

Ensure tests run in CI by:

1. Adding to existing Playwright CI workflow
2. Or creating new workflow:

```yaml
name: Mobile UX Checks

on: [push, pull_request]

jobs:
  mobile-ux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npx playwright install chromium
      - run: npm run dev &
      - run: npx playwright test mobile-ux-patterns.spec.ts
```

### Phase 6: Review with User

**Mark CI task completed:**
```
TaskUpdate:
- taskId: [ci task ID]
- status: "completed"
- metadata: {
    "workflowFile": "[path or 'added_to_existing']",
    "ciConfigured": true
  }
```

**Mark all pattern tasks with user decisions:**
For each pattern task, update with user's severity decision:
```
TaskUpdate:
- taskId: [pattern task ID]
- status: "completed"
- metadata: {"userDecision": "enforce|allow|warning_only"}
```

**Mark main task completed:**
```
TaskUpdate:
- taskId: [main task ID]
- status: "completed"
- metadata: {
    "testFile": "e2e/mobile-ux-patterns.spec.ts",
    "criticalPatterns": [count],
    "warningPatterns": [count],
    "infoPatterns": [count],
    "ciConfigured": true,
    "pagesTestesed": [count]
  }
```

**Generate summary from task data:**

Call `TaskList` to get all pattern tasks and their metadata, then present:

1. Summary of anti-patterns that will be detected
2. Which tests will fail immediately (known issues)
3. Which tests will pass (good patterns already in place)

```
## Mobile UX CI Tests Generated

### Anti-Patterns Detected
[Generated from pattern tasks:]
- **Critical (will fail CI):** [count]
  - Hamburger menu detected
  - Touch targets < 44pt
- **Warning (logged but passes):** [count]
  - Native <select> elements
- **Info (suggestions only):** [count]
  - Heavy Material shadows

### Test File
- Path: e2e/mobile-ux-patterns.spec.ts
- Tests: [count]
- Pages covered: [list from app task]

### CI Integration
- Workflow: [path or status]
- Runs on: push, pull_request
```

Ask user:
- Should any anti-patterns be allowed temporarily?
- Any additional patterns to check?
- Ready to add to CI?

## Session Recovery

If resuming from an interrupted session:

**Recovery decision tree:**
```
TaskList shows:
├── Main task in_progress, no infra task
│   └── Start from Phase 1 (assess infrastructure)
├── Infra task completed, no app task
│   └── Start from Phase 2 (explore app)
├── App task in_progress
│   └── Resume app exploration agent
├── App task completed, no generate task
│   └── Start from Phase 3 (generate tests)
├── Generate task in_progress, pattern tasks exist
│   └── Continue generating tests for remaining patterns
├── Generate task completed, no CI task
│   └── Start from Phase 5 (CI integration)
├── CI task in_progress
│   └── Resume CI setup
├── Pattern tasks pending user decisions
│   └── Present pattern severity choices to user
├── Main task completed
│   └── Generation done, show summary
└── No tasks exist
    └── Fresh start (Phase 1)
```

**Resuming with pending pattern decisions:**
```
1. Get all tasks with "Pattern:" prefix
2. Check metadata for userDecision field
3. If any patterns lack decisions:
   "Found patterns needing severity decisions:
    - Hamburger menu: [pending] - enforce/allow/warning?
    - FAB detected: [pending] - enforce/allow/warning?
   Please decide which anti-patterns should fail CI."
4. Update pattern tasks with user decisions
5. Regenerate tests with updated severity levels
```

**Always inform user when resuming:**
```
Resuming Mobile UX CI session:
- Infrastructure: [status from infra task]
- App explored: [pages from app task]
- Patterns detected: [counts from pattern tasks]
- Current state: [in_progress task description]
- Pending: [any pattern decisions needed]
- Resuming: [next action]
```

## Anti-Pattern Reference

### Critical (Should Always Fail CI)

1. **Hamburger Menu for Primary Navigation**
   - Why: iOS users expect tab bars at bottom
   - Reference: [iOS vs Android Navigation](https://www.learnui.design/blog/ios-vs-android-app-ui-design-complete-guide.html)

2. **Floating Action Button (FAB)**
   - Why: Material Design pattern, not iOS
   - Reference: [Material vs iOS](https://medium.com/@helenastening/material-design-v-s-ios-11-b4f87857814a)

3. **Touch Targets < 44pt**
   - Why: Apple HIG requirement for accessibility
   - Reference: [Apple HIG](https://developer.apple.com/design/human-interface-guidelines/)

4. **Horizontal Overflow**
   - Why: Content should fit viewport on mobile
   - Reference: Basic responsive design

### Warning (Should Log but May Not Fail)

1. **Native `<select>` Elements**
   - Why: iOS apps use picker wheels
   - Note: Some selects are acceptable for accessibility

2. **Checkboxes**
   - Why: iOS uses toggle switches
   - Note: Checkmarks in lists are acceptable

3. **Text Selection on UI**
   - Why: Native apps prevent selecting UI text
   - Note: Content text should remain selectable

4. **No Safe Area Insets**
   - Why: Content may go under notch
   - Note: Only relevant for notched devices

### Informational (Suggestions Only)

1. **Heavy Shadows (Material Elevation)**
2. **Missing touch-action: manipulation**
3. **Non-system fonts**

## Customization Points

When generating tests, ask about:

1. **Severity levels**: Which anti-patterns should fail CI vs warn?
2. **Exceptions**: Any patterns that are intentionally kept?
3. **Additional patterns**: App-specific anti-patterns to detect?
4. **Viewport sizes**: Which devices to test?

## Example Output

After running this skill, the user should have:

1. `e2e/mobile-ux-patterns.spec.ts` - Comprehensive anti-pattern tests
2. Updated CI workflow (if needed)
3. Clear documentation of what's being checked
4. Immediate visibility into current anti-patterns

## Sources

- [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/)
- [iOS vs Android Design](https://www.learnui.design/blog/ios-vs-android-app-ui-design-complete-guide.html)
- [Touch Target Sizes](https://www.smashingmagazine.com/2023/04/accessible-tap-target-sizes-rage-taps-clicks/)
- [PWA Native Feel](https://www.netguru.com/blog/pwa-ios)
- [WCAG 2.5.8 Target Size](https://www.w3.org/WAI/WCAG21/Understanding/target-size.html)