rc/android-ios-parity #1
Reference in New Issue
Block a user
Delete Branch "rc/android-ios-parity"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds acceptResidenceInvite / declineResidenceInvite to ResidenceApi (POST /api/residences/{id}/invite/{accept|decline}) and exposes them via APILayer. On accept success, myResidences is force-refreshed so the newly-joined residence appears without a manual pull. Wires NotificationActionReceiver's ACCEPT_INVITE / DECLINE_INVITE handlers to the new APILayer calls, replacing the log-only TODOs left behind by P4 Stream O. Notifications are now cleared only on API success so a failed accept stays actionable. Tests: - ResidenceApiInviteTest covers correct HTTP method/path + error surfacing. - NotificationActionReceiverTest invite cases updated to assert the new APILayer calls (were previously asserting the log-only path). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Records initial golden set + wires verifyRoborazziDebug into CI. Diffs uploaded as artifact on failure. ScreenshotTests @Ignore removed. Root cause of the prior RoboMonitoringInstrumentation:102 failure: createComposeRule() launches ActivityScenarioRule<ComponentActivity> which fires a MAIN/LAUNCHER intent, but the merged unit-test manifest declares androidx.activity.ComponentActivity without a LAUNCHER filter, so Robolectric's PM returns "Unable to resolve activity for Intent". Fix: switch to the standalone captureRoboImage(path) { composable } helper from roborazzi-compose, which registers RoborazziTransparentActivity with Robolectric's shadow PackageManager at runtime and bypasses ActivityScenario entirely. Also pin roborazzi outputDir to src/androidUnitTest/roborazzi so goldens live in git (not build/) and survive gradle clean. 36 goldens, 540KB total. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>(a) liveRegion + error semantics on form error surfaces so TalkBack announces them when they appear: - Shared ErrorCard (used by LoginScreen, RegisterScreen, VerifyEmail/ResetCode, ForgotPassword, ResetPassword) - OnboardingCreateAccountContent inline error row - JoinResidenceScreen inline error row (b) focusRequester + ImeAction.Next on multi-field forms: - LoginScreen: auto-focus username, Next→password, Done→submit - RegisterScreen: auto-focus username, Next chain through email/password/confirm, Done on last (c) navigateUp() replaces navController.popBackStack() for simple back actions in App.kt (6 screens) and MainScreen.kt (3 screens), where the back behavior is purely navigation-controlled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>InMemoryDataManager + Fixtures with deterministic data (fixed clock 2026-04-15, 2 residences, 8 tasks, 3 contractors, 5 documents). FixtureDataManager.empty() and .populated() factories. Exposed to Swift via SKIE. Expanded IDataManager surface (5 -> 22 members) so fixtures cover every StateFlow and lookup helper screens read: myResidences, allTasks, tasksByResidence, documents, documentsByResidence, contractors, residenceTypes, taskFrequencies, taskPriorities, taskCategories, contractorSpecialties, taskTemplates, taskTemplatesGrouped, residenceSummaries, upgradeTriggers, promotions, plus get{ResidenceType,TaskFrequency,TaskPriority,TaskCategory, ContractorSpecialty}(id) lookup helpers. DataManager implementation is a pure override-keyword addition — no behavior change. Enables P2 (Android gallery) + P3 (iOS gallery) to render real screens against identical inputs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Records 58 baseline PNGs across 29 primary SwiftUI screens × {light, dark} for the honeyDue iOS app. Covers auth, password reset, onboarding, residences, tasks, contractors, documents, profile, and subscription surfaces — everything that's instantiable without complex runtime context. State coverage is empty-only for this first pass: views currently spin up their own ViewModels which read DataManagerObservable.shared directly, and the test host has no login → all flows render their empty states. A follow-up PR adds an optional `dataManager:` init param to each *ViewModel.swift so populated-state snapshots (backed by P1's FixtureDataManager) can land. Tolerance knobs: pixelPrecision 0.97 / perceptualPrecision 0.95 — tuned to absorb animation-frame drift (gradient blobs, focus rings) while catching structural regressions. Tooling: swift-snapshot-testing SPM dep added to the HoneyDueTests target only (not the app target) via scripts/add_snapshot_testing.rb, which is an idempotent xcodeproj-gem script so the edit is reproducible rather than a hand-crafted pbxproj diff. Pins resolve to 1.19.2 (up-to-next-major from the 1.17.0 plan floor). Blocks regressions at PR time via `xcodebuild test -only-testing:HoneyDueTests/SnapshotGalleryTests`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>- SnapshotGalleryTests rendered at displayScale: 2.0 (was native 3.0) → 49MB → 15MB (~69% reduction) - Records via SNAPSHOT_TESTING_RECORD=1 env var (no code edits needed) - scripts/optimize_goldens.sh runs zopflipng (or pngcrush fallback) over both iOS and Android golden dirs - scripts/{record,verify}_snapshots.sh one-command wrappers - Makefile targets: make {record,verify,optimize}-snapshots Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com><img>tags with fixed width/height instead of markdown image syntax so every screenshot renders at identical size in Gitea's markdown view. Gitea strips inline styles but keeps width/height attributes.