# Sample mobile CAPTCHA app — `examples/sample_captcha_mobile_app/`

> ⚠️ **v0.8 Maestro-driver mobile work was parked.** See
> [`docs/v0.8-mobile-postmortem.md`](../../docs/v0.8-mobile-postmortem.md)
> for why. This app still builds and runs correctly as a WKWebView
> reference and is the natural starting point for any future Appium
> pivot or in-app bridge experiment.

A minimal SwiftUI iOS app that loads the v0.7 reCAPTCHA-shaped fixture
(`examples/sample_captcha_fixture/`) in a `WKWebView`. Originally
shipped as the Tier 1 target for the v0.8 Maestro mobile dogfood (now
parked).

The fixture HTML is unchanged from the Playwright desktop dogfood —
this app is just the iOS-side container that gives Maestro a WebView
to point at.

## Prereqs

- macOS with Xcode 15+ (and an iOS 16+ Simulator runtime)
- `xcodegen` — `brew install xcodegen`
- `maestro` — `brew install maestro` (only needed for end-to-end)

## Quick start

```bash
cd examples/sample_captcha_mobile_app

# 1. Build for iOS Simulator (rsyncs fixture, runs xcodegen, then xcodebuild).
./build.sh

# 2. Boot any iPhone simulator if none is running.
xcrun simctl boot 'iPhone 15' || true
open -a Simulator

# 3. Install + launch the app on the booted simulator.
xcrun simctl install booted DerivedData/Build/Products/Debug-iphonesimulator/SampleCaptchaApp.app
xcrun simctl launch booted dev.mkqa.SampleCaptchaApp
```

You should see a 3x3 blue grid with a "Verify" button — the same
layout as the desktop fixture, now running inside a real iOS WebView.

## Driving it from mk-qa-master

With the app launched on a booted simulator, point the v0.8 visual
challenge tools at it:

```python
# When calling via the MCP client:
inspect_visual_challenge(
    target_url=None,                    # WebView, not a URL
    _driver="maestro",
    _maestro_app_id="dev.mkqa.SampleCaptchaApp",
    _maestro_device_id=None,            # uses currently-booted device
)

# Then solve_visual_challenge(...) with the returned record handle —
# Maestro runs a single mega-YAML that taps tiles + verify + reads the
# response token via runScript.
```

The fixture's `postMessage`-based verify flow populates
`textarea[name="g-recaptcha-response"]` with a fixed token (same
behavior as the desktop fixture), which the solve mega-YAML reads
back through `output.token`.

## Directory layout

```
sample_captcha_mobile_app/
├── project.yml          # XcodeGen spec — `xcodegen generate` produces .xcodeproj
├── build.sh             # rsync fixture → Resources/, xcodegen, xcodebuild
├── Sources/
│   ├── SampleCaptchaApp.swift   # @main entry
│   ├── ContentView.swift        # hosts the WebView
│   ├── FixtureWebView.swift     # WKWebView UIViewRepresentable
│   └── Info.plist
└── Resources/
    └── FixtureHTML/             # synced from ../sample_captcha_fixture/ by build.sh
        ├── index.html
        └── iframe.html
```

The `.xcodeproj` and `Resources/FixtureHTML/` directories are
gitignored — both are regenerated by `build.sh` from the canonical
sources (`project.yml` and `../sample_captcha_fixture/`).

## CI usage

`.github/workflows/visual-challenge-maestro-ios.yml` (PR 7) builds
this app, boots a simulator, installs the .app, launches it, and
runs the v0.8 inspect+solve flow under Maestro — all on macOS GitHub
Actions runners.
