Commit Graph

35 Commits

Author SHA1 Message Date
jay d627fe8e67 test(ios): XCUITest coverage for pairing/switcher/statusbar/settings/modbar/lock
Test target piRemoteUITests now covers 8 features across 7 files (~73s total).

UI tests:
  - SmokeUITests: app launches
  - PairingUITests: launchUnpaired→PairingFlow, deep-link auto-pair
  - StatusBarUITests: three icon buttons (Switcher/Settings/Unpair)
  - SessionSwitcherUITests: list, select, create-with-unique-name, cleanup
  - SettingsUITests: open sheet, Face-ID toggle flip, content checks
  - ModifierBarUITests: button presence, paste sheet
  - LockScreenUITests: lock overlay via --force-lock

App-source changes for testability (all dev/uitest-only):
  - AppState: --reset-state / --enable-faceid / --force-lock launch args
  - piRemoteApp: --pair-with-url launch arg auto-triggers .onOpenURL
  - MainTerminalView: --uitest mode replaces SwiftTerm with static
    placeholder and skips WS connection to keep app idle for XCUI
  - TerminalViewController.feed: defensive guard against nil terminalView

Accessibility identifiers added:
  - StatusBar buttons: accessibilityLabel + identifier
  - ModifierBar BarButton/RepeatingBarButton: accessibilityLabel + .isButton
  - SessionSwitcher '+' button

Tooling notes:
  - cliclick workaround replaced by simctl privacy grant pasteboard
  - Tests pre-fetch fresh pair-token from /pair-qr each run
  - SwiftUI Toggle inside Form needs coordinate tap (not .tap())

Bug fixes uncovered while writing tests:
  - Sidecar POST /sessions response was missing 'state' field
    (now returns { id, name, state, lastOutputAt } to match GET).
    iOS SessionItem decoder hardened to default state='idle' when missing.
2026-05-16 22:07:42 +02:00
jay 413c94601f feat(ios): add piRemoteUITests XCUITest target with smoke test
- New target 'piRemoteUITests' (bundle.ui-testing) in project.yml
- TEST_TARGET_NAME=piRemote, deploymentTarget 17.0
- Added to scheme 'piRemote' test targets
- UITests/SmokeUITests.swift: @MainActor smoke test verifying app launches
- Verified: xcodebuild test -only-testing:piRemoteUITests passes (5.8s)
2026-05-16 16:59:26 +02:00
jay 29de5025de Merge docs/sim-automation 2026-05-16 13:04:27 +02:00
jay 398e3b71d3 docs: simulator UI automation guide (verified) 2026-05-16 13:04:16 +02:00
jay a36e4ed643 feat(ios): .onOpenURL handler for pi-remote:// deep-link pairing (sim convenience)
Adds App-level .onOpenURL that parses pi-remote:// URLs and calls
PairingService.exchange directly. Useful in the simulator where the
QR scanner isn't available.

Also documents the iPhone 12 mini simulator UUID + deep-link workflow
in BUILD.md.
2026-05-16 12:42:12 +02:00
jay f74887f898 Merge fix/session-switch-reconnect: tear down + reconnect on session switch 2026-05-16 12:07:54 +02:00
jay 856f0ebf03 fix(ios): session switch — tear down and reconnect on activeSessionId change 2026-05-16 12:07:29 +02:00
jay df85c9e85b fix: remove public visibility from app-internal types; fix StatusBar arg order 2026-05-16 11:58:23 +02:00
jay 267d8a0f23 Merge T-2.6 + T-2.8 + T-2.11 into main 2026-05-16 11:54:22 +02:00
jay 7be9e64a95 feat: merge T-2.6 SessionSwitcher + T-2.8 StatusBar + T-2.11 Face-ID
- SessionRegistry + SessionSwitcher + SessionRow (T-2.6)
- StatusBar component with pi-state indicator (T-2.8)
- FaceIDGate + SettingsView + LockView (T-2.11)
- Reconciled MainTerminalView: StatusBar wired with onSwitcher/onSettings/onUnpair,
  two .task modifiers, two .sheet modifiers (SessionSwitcher + SettingsView)
- AppState: appDidBackground/appWillForeground + isLocked (T-2.11)
- ContentView: scenePhase tracking + LockView overlay (T-2.11)
- Pairing.swift: fp param is optional pre-TLS (dev convenience)
2026-05-16 11:54:12 +02:00
jay fb56c11a29 fix: default font size 13pt → 11pt for ~53 cols on iPhone 12 mini 2026-05-16 04:04:48 +02:00
jay d085444adc fix: clear terminal on connect, increase SIGWINCH settle time to 600ms 2026-05-16 04:00:02 +02:00
jay 994b450fe4 fix: fresh connect uses resize+snapshot instead of full history replay; wire onInput 2026-05-16 03:46:24 +02:00
jay 044a4920bb fix: terminal rendering — resize sync, TERM via sidecar, remove double-dot status 2026-05-16 03:30:31 +02:00
Johannes Merz 3a4a6af942 docs: fix trailing slash in pair-qr curl command 2026-05-16 02:58:18 +02:00
Johannes Merz ad95ea3efd docs: BUILD.md — fix pair command, use GET /pair-qr endpoint 2026-05-16 02:56:20 +02:00
Johannes Merz 91baac5420 docs: BUILD.md — device ID, sidecar start, build/install/launch commands 2026-05-16 02:53:43 +02:00
Johannes Merz 480a06981c feat: app wiring — ContentView + AppState + MainTerminalView
- AppState: loads credential from Keychain on launch, persists on pair
- ContentView: switches PairingFlowView ↔ MainTerminalView on credential
- PairingFlowView: onDismiss → onSuccess(credential) callback
- MainTerminalView: auto-resolves/creates session, connects WebSocket stream
  to TerminalViewController, ModifierBar wired to SessionConnection.send()
- piRemoteApp: AppState injected as environmentObject
2026-05-16 02:48:08 +02:00
Johannes Merz 333797ea36 docs: update status table — T-2.0..T-2.5+T-2.9 done 2026-05-16 02:42:02 +02:00
Johannes Merz 9c617a7c14 fix: Swift 6 concurrency build errors — all files compile clean
- SessionConnection: ConnectionState not nested in WebSocketClient
- WebSocketClient: nonisolated(unsafe) for WebSocketEvent across actor boundary
- ModifierBar: explicit init() + RepeatingBarButton access level fix
- NotificationDelegate: nonisolated(unsafe) for completion handlers
- QRScannerView: DispatchQueue instead of Task.detached for AVCaptureSession
- piRemoteApp: add UserNotifications import
- xcodegen regenerate to pick up all new source files
2026-05-16 02:38:16 +02:00
jay 0f680cfcc2 merge: feat/p2-t2-5-session 2026-05-15 19:04:52 +02:00
jay 9f2046c7cb merge: feat/p2-t2-4-modifierbar 2026-05-15 19:04:52 +02:00
jay 5a4e814d9f merge: feat/p2-tests-2 2026-05-15 19:04:44 +02:00
jay 45a0884beb test(T-2.4/2.5/2.9): ModifierState, ScrollbackCache, DeviceTokenRegistrar tests 2026-05-15 19:03:56 +02:00
jay dc4f08d8ee feat(T-2.4): ModifierBar, ModifierState, PasteSheet 2026-05-15 18:57:42 +02:00
jay 048036d6a7 feat(T-2.5): SessionConnection (IC-2.1) + ScrollbackCache (5MB ring) 2026-05-15 18:54:56 +02:00
jay a5c937ad75 feat(T-2.9): APNs NotificationDelegate + DeviceTokenRegistrar 2026-05-15 18:54:10 +02:00
Johannes Merz 6b953008ce merge: 78 unit tests (FrameCodec, ResumeCursor, Pairing, Keychain, Theme) 2026-05-15 18:34:36 +02:00
jay 27d0a43dbe merge: T-2.2 Pairing/Keychain/QR + T-2.3 TerminalView/Themes/Fonts 2026-05-15 18:34:25 +02:00
jay d6062000e8 merge: T-2.1 WebSocketClient + FrameCodec + ResumeCursor 2026-05-15 18:34:16 +02:00
jay 89c27c0eae test(T-2.1/2.2/2.3): unit tests for FrameCodec, ResumeCursor, Pairing, Keychain, Theme
78 test functions across 5 test files:
- FrameCodecTests.swift (24): BinaryFrame.decode, ClientToServer encoding,
  ServerToClient decoding, round-trip — full IC-1 field name verification
- ResumeCursorTests.swift (12): save/load, overwrite, UInt64.max, clear,
  multi-session isolation — each test uses isolated UserDefaults suite
- PairingTests.swift (18): parseQR happy-path, missing params, wrong scheme,
  missing port, error type assertions
- KeychainTests.swift (7): round-trip SidecarCredential, upsert, notFound,
  delete, production key guard, generic Codable
- ThemeTests.swift (17): ansiColors count, color range, dark≠github,
  SwiftTerm conversion, ThemeStore select, Codable round-trip

Review notes: Tests/CoreTests/REVIEW_NOTES.md
- feat/p2-t2-2-pairing branch was EMPTY; Auth/Pairing code on t2-3-terminal
- IC-1 compliance: all JSON field names correct including 'awaiting-input'
- Minor: Keychain.encodingFailed used for decode failure (misleading name)
- Merge order: t2-1 → t2-3 → t2-2 (empty) → p2-tests
2026-05-15 18:33:26 +02:00
jay 9fb5f813a1 feat(T-2.1): WebSocketClient + FrameCodec + ResumeCursor 2026-05-15 18:27:48 +02:00
jay 49667667eb feat(T-2.3): TerminalView UIKit wrapper, theme store, font store 2026-05-15 18:26:12 +02:00
jay f6396bc70e feat(T-2.2): Pairing flow, Keychain, QR scanner, TLS pinning stub 2026-05-15 18:21:40 +02:00
Johannes Merz aa010cf874 feat(T-2.0): Xcode project scaffold — SwiftUI shell, SwiftTerm + Starscream SPM deps
- xcodegen project.yml: de.vpsj.pi-remote, team KNXX8R3648, iOS 17+
- SwiftTerm 1.13.0, Starscream 4.0.8 resolved
- App entry point + ContentView hello shell
- Push Notifications entitlement (aps-environment: development)
- pi-remote:// URL scheme registered
- NSCameraUsageDescription (QR pairing), NSFaceIDUsageDescription
- UIBackgroundModes: remote-notification
2026-05-15 13:19:48 +02:00