Watch: snapshot tests render the complication and multi-select screenshots
ImageRenderer draws the real views with demo data, since the watch simulator is not drivable here. README covers the widget target and how to add it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
0994fd7d5a
commit
67992dbf43
8 files changed
+241
-80
No files matched your search
+30
-2
@@ -22,6 +22,7 @@ targets, the same pair Xcode's "Watch-only App" template makes:
|
||||
| --- | --- | --- |
|
||||
| `WristCodeContainer` | `org.gbrown.wristcode` | iOS stub that owns the App Store Connect record and embeds the watch app |
|
||||
| `WristCode` | `org.gbrown.wristcode.watchkitapp` | The watch app, and the APNs topic |
|
||||
| `WristCodeWidget` | `org.gbrown.wristcode.watchkitapp.widget` | The complication, embedded in the watch app |
|
||||
|
||||
```sh
|
||||
scripts/testflight.sh # archive, export and upload to App Store Connect
|
||||
@@ -46,7 +47,31 @@ xcrun simctl launch <udid> org.gbrown.wristcode.watchkitapp -demo -thread little
|
||||
xcrun simctl launch <udid> org.gbrown.wristcode.watchkitapp -demo -screen new # new thread
|
||||
```
|
||||
|
||||
`screenshots/` holds the screens captured this way.
|
||||
`screenshots/` holds the screens captured this way. The complication and the multi-select question
|
||||
are rendered by `SnapshotTests` instead, which only run when given a directory:
|
||||
|
||||
```sh
|
||||
TEST_RUNNER_WC_SCREENSHOT_DIR=$PWD/screenshots xcodebuild -scheme WristCode \
|
||||
-destination 'platform=watchOS Simulator,name=Apple Watch Series 12 (46mm)' test \
|
||||
-only-testing:WristCodeTests/SnapshotTests
|
||||
```
|
||||
|
||||
In demo mode the complication shows the demo counts too.
|
||||
|
||||
## Complication
|
||||
|
||||
`WristCodeWidget` shows how many threads wait on you, from `GET /v1/summary`, in the circular,
|
||||
rectangular, inline and corner families. Tapping it opens the app, at the longest-waiting thread when
|
||||
there is one (`wristcode://thread/<hostId>/<threadId>`). WidgetKit refreshes it about every 15 minutes;
|
||||
the app reloads it sooner when its feed counts change, when a push arrives in the foreground, and
|
||||
after a notification action.
|
||||
|
||||
The app and the extension share the App Group `group.org.gbrown.wristcode`. The device token and
|
||||
gateway URL live in that group's Keychain access group, and the demo flag and last summary in its
|
||||
defaults. Builds before the complication kept the token in the app's own Keychain group;
|
||||
`DeviceStore.migrateToSharedGroup()` moves it on launch, so a paired watch stays paired.
|
||||
|
||||
To add it: long-press the watch face, Edit, swipe to Complications, pick a slot, then WristCode.
|
||||
|
||||
## Layout
|
||||
|
||||
@@ -56,7 +81,10 @@ xcrun simctl launch <udid> org.gbrown.wristcode.watchkitapp -demo -screen new
|
||||
| `AppModel.swift` | Paired, demo or unpaired; navigation path; the feed; 401 sends you back to pairing |
|
||||
| `API/GatewayClient.swift` | `GatewayAPI` protocol and the URLSession client |
|
||||
| `API/Models.swift` | Codable mirror of the contract |
|
||||
| `Auth/DeviceStore.swift` | Device token and gateway URL in the Keychain |
|
||||
| `API/Route.swift` | Screens the app can open, and their `wristcode://` URLs |
|
||||
| `Auth/DeviceStore.swift` | Device token and gateway URL in the shared Keychain group |
|
||||
| `Shared/SharedState.swift` | Demo flag and last summary in the App Group, for the complication |
|
||||
| `Demo/DemoGateway.swift` | In-memory gateway with fixtures |
|
||||
| `Views/` | Pair, Feed, Thread, New thread, and the mock B theme |
|
||||
| `Notifications/NotificationHandler.swift` | Categories `approval`, `finished`, `failed`, `input`, `host` and their actions |
|
||||
| `../WristCodeWidget/` | The complication: timeline provider, and one view per family |
|
||||
Reference in new issue
Block a user