From 3521788e7ae1ed7efa0e7cd4b44ca67c6318480d Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 19:10:21 -0700 Subject: [PATCH 1/8] Relocate generic snapshot-pipeline tests into a SnapshotKitTesting bundle The capture/compare pipeline had no test bundle of its own; its generic regression tests (async settle, concurrent-capture serialization, duplicate identifiers, tile-and-stitch/full-content, the pre-capture hook, and the same-image capture-flag probe) lived in WhereUISnapshotTests despite being WhereUI-free and asserting on probed pixels rather than LFS references. Move them into a new Shared/SnapshotKitTesting/Tests + SnapshotKitTestingTests bundle, wired into Project.swift and the Stuff-iOS-Tests scheme (fast, no __Snapshots__, so it runs in the main test job, not the snapshot job). Promote PixelSample/probePixel into SnapshotKitTesting as @_spi(Testing) API shared by both bundles, and add a SafeAreaComposition regression test pinning that the swizzle zeroes the captured root while a safeAreaInset bar still composes on top. The WhereUI-defined cross-boundary probe test + view stay in WhereUI (they exist to detect a WhereUI<->bundle SnapshotKit split). Closes review comments on test placement (Plan to-do: bundle). --- Project.swift | 19 ++++++ .../Sources}/SnapshotPixelProbe.swift | 16 +++-- .../Tests}/AsyncContentCaptureTests.swift | 2 +- .../Tests}/ConcurrentCaptureTests.swift | 2 +- .../DuplicateSnapshotIdentifiersTests.swift | 0 .../Tests}/LargeViewCaptureTests.swift | 2 +- .../Tests}/PreCaptureHookTests.swift | 2 +- .../Tests/SafeAreaCompositionTests.swift | 63 +++++++++++++++++++ .../Tests}/SnapshotCaptureFlagTests.swift | 2 +- .../SnapshotCaptureFlagProbeTests.swift | 2 +- 10 files changed, 98 insertions(+), 12 deletions(-) rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Sources}/SnapshotPixelProbe.swift (82%) rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Tests}/AsyncContentCaptureTests.swift (97%) rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Tests}/ConcurrentCaptureTests.swift (99%) rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Tests}/DuplicateSnapshotIdentifiersTests.swift (100%) rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Tests}/LargeViewCaptureTests.swift (98%) rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Tests}/PreCaptureHookTests.swift (98%) create mode 100644 Shared/SnapshotKitTesting/Tests/SafeAreaCompositionTests.swift rename {Where/WhereUI/SnapshotTests => Shared/SnapshotKitTesting/Tests}/SnapshotCaptureFlagTests.swift (97%) diff --git a/Project.swift b/Project.swift index a1532a4d..cc860408 100644 --- a/Project.swift +++ b/Project.swift @@ -333,6 +333,22 @@ let project = Project( productDependency: "SnapshotKit", sources: ["Shared/SnapshotKit/Tests/**"], ), + // The capture/compare pipeline's own regression tests. They render + // through `renderSnapshotImage` (so they need the `StuffTestHost` key + // window) but assert on probed pixels rather than LFS reference images, + // so — unlike `WhereUISnapshotTests` — this bundle is fast, has no + // `__Snapshots__/`, and runs in the main `Stuff-iOS-Tests` scheme / + // `test` CI job. `SnapshotKitTesting` embeds its dependency closure + // (SnapshotKit, SnapshotTesting, AccessibilitySnapshot) into the + // `.xctest`; that's fine here since no WhereUI dynamic-framework + // boundary is crossed (the duplicate-metadata hazard is specific to the + // WhereUISnapshotTests topology). + unitTests( + name: "SnapshotKitTestingTests", + bundleIdSuffix: "snapshotkittesting", + productDependency: "SnapshotKitTesting", + sources: ["Shared/SnapshotKitTesting/Tests/**"], + ), unitTests( name: "RegionKitTests", bundleIdSuffix: "regionkit", @@ -485,6 +501,7 @@ let project = Project( "PeriscopeToolsTests", "SwiftDataInspectorTests", "SnapshotKitTests", + "SnapshotKitTestingTests", "RegionKitTests", "WhereCoreTests", "WhereTests", @@ -506,6 +523,7 @@ let project = Project( "PeriscopeToolsTests", "SwiftDataInspectorTests", "SnapshotKitTests", + "SnapshotKitTestingTests", "RegionKitTests", "WhereCoreTests", "WhereTests", @@ -526,6 +544,7 @@ let project = Project( testScheme(name: "PeriscopeToolsTests"), testScheme(name: "SwiftDataInspectorTests"), testScheme(name: "SnapshotKitTests"), + testScheme(name: "SnapshotKitTestingTests"), testScheme(name: "RegionKitTests"), testScheme(name: "WhereCoreTests"), testScheme(name: "WhereTests"), diff --git a/Where/WhereUI/SnapshotTests/SnapshotPixelProbe.swift b/Shared/SnapshotKitTesting/Sources/SnapshotPixelProbe.swift similarity index 82% rename from Where/WhereUI/SnapshotTests/SnapshotPixelProbe.swift rename to Shared/SnapshotKitTesting/Sources/SnapshotPixelProbe.swift index d226f093..c8350c74 100644 --- a/Where/WhereUI/SnapshotTests/SnapshotPixelProbe.swift +++ b/Shared/SnapshotKitTesting/Sources/SnapshotPixelProbe.swift @@ -3,18 +3,22 @@ import UIKit /// A single RGBA pixel sampled from a rendered snapshot, with components in /// `0...1`. Shared by the pipeline regression tests that assert on rendered /// colors rather than reference images. -struct PixelSample { - let red: CGFloat - let green: CGFloat - let blue: CGFloat - let alpha: CGFloat +/// +/// `@_spi(Testing)`: a probe for snapshot-pipeline tests, not shipping API. +@_spi(Testing) +public struct PixelSample { + public let red: CGFloat + public let green: CGFloat + public let blue: CGFloat + public let alpha: CGFloat } +@_spi(Testing) extension UIImage { /// Samples the pixel at a unit-space point (`(0.5, 0.5)` is the center), /// clamped to the image bounds. Returns transparent black if the image has /// no bitmap backing. - func probePixel(atUnitPoint unit: CGPoint) -> PixelSample { + public func probePixel(atUnitPoint unit: CGPoint) -> PixelSample { guard let cgImage else { return PixelSample(red: 0, green: 0, blue: 0, alpha: 0) } let x = min(cgImage.width - 1, max(0, Int(CGFloat(cgImage.width) * unit.x))) let y = min(cgImage.height - 1, max(0, Int(CGFloat(cgImage.height) * unit.y))) diff --git a/Where/WhereUI/SnapshotTests/AsyncContentCaptureTests.swift b/Shared/SnapshotKitTesting/Tests/AsyncContentCaptureTests.swift similarity index 97% rename from Where/WhereUI/SnapshotTests/AsyncContentCaptureTests.swift rename to Shared/SnapshotKitTesting/Tests/AsyncContentCaptureTests.swift index 0f5c32f5..876870e1 100644 --- a/Where/WhereUI/SnapshotTests/AsyncContentCaptureTests.swift +++ b/Shared/SnapshotKitTesting/Tests/AsyncContentCaptureTests.swift @@ -1,4 +1,4 @@ -import SnapshotKitTesting +@_spi(Testing) import SnapshotKitTesting import SwiftUI import TestHostSupport import Testing diff --git a/Where/WhereUI/SnapshotTests/ConcurrentCaptureTests.swift b/Shared/SnapshotKitTesting/Tests/ConcurrentCaptureTests.swift similarity index 99% rename from Where/WhereUI/SnapshotTests/ConcurrentCaptureTests.swift rename to Shared/SnapshotKitTesting/Tests/ConcurrentCaptureTests.swift index 09ed0c18..f69f7c64 100644 --- a/Where/WhereUI/SnapshotTests/ConcurrentCaptureTests.swift +++ b/Shared/SnapshotKitTesting/Tests/ConcurrentCaptureTests.swift @@ -1,4 +1,4 @@ -import SnapshotKitTesting +@_spi(Testing) import SnapshotKitTesting import SwiftUI import TestHostSupport import Testing diff --git a/Where/WhereUI/SnapshotTests/DuplicateSnapshotIdentifiersTests.swift b/Shared/SnapshotKitTesting/Tests/DuplicateSnapshotIdentifiersTests.swift similarity index 100% rename from Where/WhereUI/SnapshotTests/DuplicateSnapshotIdentifiersTests.swift rename to Shared/SnapshotKitTesting/Tests/DuplicateSnapshotIdentifiersTests.swift diff --git a/Where/WhereUI/SnapshotTests/LargeViewCaptureTests.swift b/Shared/SnapshotKitTesting/Tests/LargeViewCaptureTests.swift similarity index 98% rename from Where/WhereUI/SnapshotTests/LargeViewCaptureTests.swift rename to Shared/SnapshotKitTesting/Tests/LargeViewCaptureTests.swift index 07925b9a..a7263712 100644 --- a/Where/WhereUI/SnapshotTests/LargeViewCaptureTests.swift +++ b/Shared/SnapshotKitTesting/Tests/LargeViewCaptureTests.swift @@ -1,4 +1,4 @@ -import SnapshotKitTesting +@_spi(Testing) import SnapshotKitTesting import SwiftUI import TestHostSupport import Testing diff --git a/Where/WhereUI/SnapshotTests/PreCaptureHookTests.swift b/Shared/SnapshotKitTesting/Tests/PreCaptureHookTests.swift similarity index 98% rename from Where/WhereUI/SnapshotTests/PreCaptureHookTests.swift rename to Shared/SnapshotKitTesting/Tests/PreCaptureHookTests.swift index 4beffa83..73bf0d51 100644 --- a/Where/WhereUI/SnapshotTests/PreCaptureHookTests.swift +++ b/Shared/SnapshotKitTesting/Tests/PreCaptureHookTests.swift @@ -1,5 +1,5 @@ import Observation -import SnapshotKitTesting +@_spi(Testing) import SnapshotKitTesting import SwiftUI import TestHostSupport import Testing diff --git a/Shared/SnapshotKitTesting/Tests/SafeAreaCompositionTests.swift b/Shared/SnapshotKitTesting/Tests/SafeAreaCompositionTests.swift new file mode 100644 index 00000000..b956b341 --- /dev/null +++ b/Shared/SnapshotKitTesting/Tests/SafeAreaCompositionTests.swift @@ -0,0 +1,63 @@ +@_spi(Testing) import SnapshotKitTesting +import SwiftUI +import TestHostSupport +import Testing +import UIKit + +/// Regression guard for `SafeAreaInsetsSwizzling`. The swizzle zeroes the +/// captured **root**'s `safeAreaInsets` — decoupling the image from the +/// simulator's notch/home indicator — so a safe-area-respecting view reaches the +/// top edge instead of being pushed down by the device insets +/// (`zeroedRootLeavesNoDeviceInset`). It must do that *without* erasing +/// contributions layered mid-tree: a `safeAreaInset` bar (the same mechanism a +/// nav bar / toolbar uses) still composes on top of the zeroed base, so the bar +/// sits flush at the top and its content lays out below it — not crammed under +/// it and not offset by the device insets (`safeAreaInsetBarComposesOnTheZeroedRoot`). +/// An earlier design that returned the override for *every* in-tree view erased +/// such contributions; this pins that it doesn't. +@MainActor +struct SafeAreaCompositionTests { + @Test func zeroedRootLeavesNoDeviceInset() async throws { + try waitFor { hostKeyWindow() != nil } + let host = UIHostingController(rootView: Color.red) + host.view.frame = CGRect(x: 0, y: 0, width: 100, height: 100) + let image = await renderSnapshotImage(of: host, safeAreaInsets: .zero) + + // A safe-area-respecting fill reaches the very top: the device's real + // top inset was zeroed at the root rather than leaking into the image. + let top = image.probePixel(atUnitPoint: CGPoint(x: 0.5, y: 0.05)) + #expect(top.red > 0.5) + #expect(top.green < 0.5) + } + + @Test func safeAreaInsetBarComposesOnTheZeroedRoot() async throws { + try waitFor { hostKeyWindow() != nil } + let host = UIHostingController(rootView: BarProbeView()) + host.view.frame = CGRect(x: 0, y: 0, width: 100, height: 100) + let image = await renderSnapshotImage(of: host, safeAreaInsets: .zero) + + // The 30pt bar sits flush at the top (not offset by device insets) — + // the interior contribution composed on the zeroed base. + let inBar = image.probePixel(atUnitPoint: CGPoint(x: 0.5, y: 0.15)) + #expect(inBar.green > 0.5) + #expect(inBar.red < 0.5) + + // Below the bar: the content the bar inset, still present rather than + // crammed under the bar. + let belowBar = image.probePixel(atUnitPoint: CGPoint(x: 0.5, y: 0.6)) + #expect(belowBar.red > 0.5) + #expect(belowBar.green < 0.5) + } +} + +/// A red content pane with a 30pt green `safeAreaInset` bar pinned to the top — +/// the bar's contribution must compose on top of the captured root's zeroed +/// safe area. +private struct BarProbeView: View { + var body: some View { + Color.red + .safeAreaInset(edge: .top, spacing: 0) { + Color.green.frame(height: 30) + } + } +} diff --git a/Where/WhereUI/SnapshotTests/SnapshotCaptureFlagTests.swift b/Shared/SnapshotKitTesting/Tests/SnapshotCaptureFlagTests.swift similarity index 97% rename from Where/WhereUI/SnapshotTests/SnapshotCaptureFlagTests.swift rename to Shared/SnapshotKitTesting/Tests/SnapshotCaptureFlagTests.swift index e406f433..0ae7c6ce 100644 --- a/Where/WhereUI/SnapshotTests/SnapshotCaptureFlagTests.swift +++ b/Shared/SnapshotKitTesting/Tests/SnapshotCaptureFlagTests.swift @@ -1,4 +1,4 @@ -import SnapshotKitTesting +@_spi(Testing) import SnapshotKitTesting import SwiftUI import TestHostSupport import Testing diff --git a/Where/WhereUI/SnapshotTests/SnapshotCaptureFlagProbeTests.swift b/Where/WhereUI/SnapshotTests/SnapshotCaptureFlagProbeTests.swift index ad5dd341..92f088f1 100644 --- a/Where/WhereUI/SnapshotTests/SnapshotCaptureFlagProbeTests.swift +++ b/Where/WhereUI/SnapshotTests/SnapshotCaptureFlagProbeTests.swift @@ -1,4 +1,4 @@ -import SnapshotKitTesting +@_spi(Testing) import SnapshotKitTesting import SwiftUI import TestHostSupport import Testing From 9378f1577721e5bba7b471aa543c77effb4700cd Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:24:13 -0700 Subject: [PATCH 2/8] Move snapshot declarations into each view's file, sharing the preview cutsheet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each view's SnapshotProviding conformance lived in Sources/Preview/{Screen, Widget,AppFlow}Snapshots.swift, divorced from the view, and no #Preview rendered the snapshotPreviews cutsheet — so the preview/snapshot single-source the architecture is built around wasn't actually realized. Move every conformance into its own view file under #if DEBUG and point the view's #Preview at Self.snapshotPreviews, so one declaration drives both the Xcode cutsheet and the image tests. RegionMapView keeps a bespoke live-Map preview alongside the cutsheet (the cutsheet renders the deterministic stand-in); RootView keeps its from-scratch launch preview. Delete the three Preview/*Snapshots.swift files (WhereSnapshot.swift's helpers stay). Also centralize the pinned widget instant on PreviewSupport (reusing the same value the references were recorded with) and add PreviewSupport.onboardingModel() over in-memory preferences, fixing the onboarding fixture's real-UserDefaults leak as its declaration moves. Renders identically — the fixtures/config are byte-for-byte the prior declarations, verified by a full WhereUISnapshotTests run with zero reference changes (the lone exception, resolution.Empty_iPhone{,_dark}, is a pre-existing sub-threshold local rendering drift on the all-clear ContentUnavailableView, not introduced here — the reference is unchanged and the fixture is identical). Plan to-do: declarations-in-views. --- .../Sources/Developer/DeveloperOverlay.swift | 22 +- .../Developer/DeveloperToolsView.swift | 13 +- .../Sources/Developer/RegionMapView.swift | 17 +- .../Sources/Launch/LaunchSplashView.swift | 29 +- .../Sources/Manual/LoggedDaysView.swift | 43 ++- .../Sources/Manual/ManualDayView.swift | 108 +++--- .../Sources/Onboarding/OnboardingView.swift | 16 +- .../Sources/Preview/AppFlowSnapshots.swift | 62 --- .../Sources/Preview/PreviewSupport.swift | 22 +- .../Sources/Preview/ScreenSnapshots.swift | 355 ------------------ .../Sources/Preview/WidgetSnapshots.swift | 125 ------ .../Sources/Primary/CalendarView.swift | 52 ++- .../Primary/PresenceTimelineView.swift | 11 +- .../WhereUI/Sources/Primary/PrimaryView.swift | 34 +- .../Primary/RecentActivitySummaryView.swift | 54 +-- .../Resolution/FlightDayDetailView.swift | 45 ++- .../Sources/Resolution/ResolutionView.swift | 28 +- Where/WhereUI/Sources/RootView.swift | 42 ++- .../Sources/Secondary/DayRelabelView.swift | 80 ++-- .../Sources/Secondary/RegionDaysView.swift | 18 +- .../Sources/Secondary/SecondaryView.swift | 13 +- .../Sources/Settings/AppIconView.swift | 11 +- .../Sources/Settings/SettingsView.swift | 21 +- .../Sources/Widgets/TodayAccessoryViews.swift | 57 ++- .../Sources/Widgets/TodayWidgetView.swift | 49 ++- .../YearTotalsRectangularAccessoryView.swift | 25 +- .../Widgets/YearTotalsWidgetView.swift | 33 +- 27 files changed, 571 insertions(+), 814 deletions(-) delete mode 100644 Where/WhereUI/Sources/Preview/AppFlowSnapshots.swift delete mode 100644 Where/WhereUI/Sources/Preview/ScreenSnapshots.swift delete mode 100644 Where/WhereUI/Sources/Preview/WidgetSnapshots.swift diff --git a/Where/WhereUI/Sources/Developer/DeveloperOverlay.swift b/Where/WhereUI/Sources/Developer/DeveloperOverlay.swift index a508d63e..f91dd023 100644 --- a/Where/WhereUI/Sources/Developer/DeveloperOverlay.swift +++ b/Where/WhereUI/Sources/Developer/DeveloperOverlay.swift @@ -1,4 +1,5 @@ #if DEBUG + import SnapshotKit import SwiftUI import UIKit @@ -203,17 +204,16 @@ } } - #Preview("Collapsed") { - ZStack { - LinearGradient( - colors: [.mint, .indigo], - startPoint: .top, - endPoint: .bottom, - ) - .ignoresSafeArea() - - DeveloperOverlay() - .environment(PreviewSupport.loadedSession()) + extension DeveloperOverlay: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Collapsed", configurations: .phoneLightDark) { + DeveloperOverlay() + .environment(PreviewSupport.loadedSession()) + } } } + + #Preview { + DeveloperOverlay.snapshotPreviews + } #endif diff --git a/Where/WhereUI/Sources/Developer/DeveloperToolsView.swift b/Where/WhereUI/Sources/Developer/DeveloperToolsView.swift index 6f8b838f..88c8b0fb 100644 --- a/Where/WhereUI/Sources/Developer/DeveloperToolsView.swift +++ b/Where/WhereUI/Sources/Developer/DeveloperToolsView.swift @@ -1,6 +1,7 @@ #if DEBUG import LogViewerUI import RegionKit + import SnapshotKit import SwiftDataInspector import SwiftUI import WhereCore @@ -59,8 +60,16 @@ } } + extension DeveloperToolsView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .phoneLightDark) { + DeveloperToolsView() + .environment(PreviewSupport.loadedSession()) + } + } + } + #Preview { - DeveloperToolsView() - .environment(PreviewSupport.loadedSession()) + DeveloperToolsView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Developer/RegionMapView.swift b/Where/WhereUI/Sources/Developer/RegionMapView.swift index 12310852..913e1236 100644 --- a/Where/WhereUI/Sources/Developer/RegionMapView.swift +++ b/Where/WhereUI/Sources/Developer/RegionMapView.swift @@ -352,9 +352,24 @@ private struct LegendGroup: Identifiable { } #if DEBUG - #Preview { + extension RegionMapView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .phoneLightDark) { + NavigationStack { RegionMapView() } + } + } + } + + // The live `Map` preview stays alongside the cutsheet: the cutsheet renders + // the deterministic capture stand-in (`\.isCapturingSnapshot` is set there), + // but a developer previewing this screen still wants the real MapKit map. + #Preview("Live map") { NavigationStack { RegionMapView() } } + + #Preview("Snapshot cutsheet") { + RegionMapView.snapshotPreviews + } #endif diff --git a/Where/WhereUI/Sources/Launch/LaunchSplashView.swift b/Where/WhereUI/Sources/Launch/LaunchSplashView.swift index e3b86c44..979c3ef8 100644 --- a/Where/WhereUI/Sources/Launch/LaunchSplashView.swift +++ b/Where/WhereUI/Sources/Launch/LaunchSplashView.swift @@ -207,21 +207,22 @@ private struct RadarPingBackground: View { } #if DEBUG - // `accessibilityReduceMotion` is a read-only environment value, so the - // motion-pinned variant can't be previewed via `.environment`; at rest the - // animated splash looks identical to it anyway. These cover the color-mode - // variation (which changes the rendered icon art) and the slow-launch caption. - #Preview("Light") { - LaunchSplashView(previewImageName: "AppIconClassic") - .environment(\.colorScheme, .light) - } - - #Preview("Dark") { - LaunchSplashView(previewImageName: "AppIconClassic") - .environment(\.colorScheme, .dark) + extension LaunchSplashView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .phoneLightDark) { + LaunchSplashView(previewImageName: "AppIconClassic") + } + whereSnapshot(name: "SlowLaunchCaption", configurations: .phoneLightDark) { + LaunchSplashView(previewImageName: "AppIconClassic", previewShowsCaption: true) + } + } } - #Preview("Slow launch") { - LaunchSplashView(previewImageName: "AppIconClassic", previewShowsCaption: true) + // The cutsheet covers the color-mode variation (which changes the rendered + // icon art) and the slow-launch caption. Reduce Motion isn't shown: it's a + // read-only environment value that can't be set via `.environment`, and at + // rest the animated splash looks identical to its motion-pinned frame. + #Preview { + LaunchSplashView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Manual/LoggedDaysView.swift b/Where/WhereUI/Sources/Manual/LoggedDaysView.swift index cfd0ada5..b26c741e 100644 --- a/Where/WhereUI/Sources/Manual/LoggedDaysView.swift +++ b/Where/WhereUI/Sources/Manual/LoggedDaysView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -250,25 +251,31 @@ private struct LoggedDayRow: View { } #if DEBUG - #Preview("Loaded") { - LoggedDaysView( - report: PreviewSupport.loadedYearReportModel(), - model: PreviewSupport - .loggedDaysModel(state: .loaded(PreviewSupport.sampleManualDays())), - ) - } - - #Preview("Empty") { - LoggedDaysView( - report: PreviewSupport.loadedYearReportModel(), - model: PreviewSupport.loggedDaysModel(state: .empty), - ) + extension LoggedDaysView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Loaded", configurations: .screenDefaults) { + LoggedDaysView( + report: PreviewSupport.loadedYearReportModel(), + model: PreviewSupport + .loggedDaysModel(state: .loaded(PreviewSupport.sampleManualDays())), + ) + } + whereSnapshot(name: "Empty", configurations: .phoneLightDark) { + LoggedDaysView( + report: PreviewSupport.loadedYearReportModel(), + model: PreviewSupport.loggedDaysModel(state: .empty), + ) + } + whereSnapshot(name: "Failed", configurations: .phoneLightDark) { + LoggedDaysView( + report: PreviewSupport.loadedYearReportModel(), + model: PreviewSupport.loggedDaysModel(state: .failed("iCloud is unavailable.")), + ) + } + } } - #Preview("Failed") { - LoggedDaysView( - report: PreviewSupport.loadedYearReportModel(), - model: PreviewSupport.loggedDaysModel(state: .failed("iCloud is unavailable.")), - ) + #Preview { + LoggedDaysView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Manual/ManualDayView.swift b/Where/WhereUI/Sources/Manual/ManualDayView.swift index 498fa164..16ef22ba 100644 --- a/Where/WhereUI/Sources/Manual/ManualDayView.swift +++ b/Where/WhereUI/Sources/Manual/ManualDayView.swift @@ -509,54 +509,70 @@ extension ManualDayView { } #if DEBUG - #Preview("Add") { - NavigationStack { - ManualDayView(report: PreviewSupport.loadedYearReportModel(), mode: .add(prefill: nil)) - } - } - - #Preview("Add — prefilled range") { - NavigationStack { - ManualDayView( - report: PreviewSupport.missingDaysYearReportModel(), - mode: .add(prefill: MissingDayRange( - start: CalendarDay(year: 2026, month: 1, day: 1), - end: CalendarDay(year: 2026, month: 1, day: 5), - dayCount: 5, - )), - ) - } - } - - #Preview("Edit — additive backfill") { - NavigationStack { - ManualDayView( - report: PreviewSupport.loadedYearReportModel(), - mode: .edit(DayPresence(date: .now, in: .current, regions: [.california])), - ) + extension ManualDayView: SnapshotProviding { + /// A plain add (`prefill: nil`) would default its date pickers to the + /// real current date and churn the references daily, so the add cases + /// prefill a fixed single day instead — same form, deterministic date. + private static var addPrefill: MissingDayRange { + let day = CalendarDay(from: PreviewSupport.referenceNow, in: .current) + return MissingDayRange(start: day, end: day, dayCount: 1) + } + + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Add", configurations: .screenDefaults) { + NavigationStack { + ManualDayView( + report: PreviewSupport.loadedYearReportModel(), + mode: .add(prefill: addPrefill), + showsCancelButton: false, + ) + } + } + whereSnapshot(name: "AddWithCancel", configurations: .phoneLightDark) { + NavigationStack { + ManualDayView( + report: PreviewSupport.loadedYearReportModel(), + mode: .add(prefill: addPrefill), + showsCancelButton: true, + ) + } + } + whereSnapshot(name: "EditPlain", configurations: .phoneLightDark) { + NavigationStack { + ManualDayView( + report: PreviewSupport.loadedYearReportModel(), + mode: .edit(DayPresence( + date: PreviewSupport.referenceNow, + in: .current, + regions: [.california], + )), + showsCancelButton: true, + ) + } + } + whereSnapshot(name: "EditAuthoritative", configurations: .phoneLightDark) { + NavigationStack { + ManualDayView( + report: PreviewSupport.loadedYearReportModel(), + mode: .edit(DayPresence( + date: PreviewSupport.referenceNow, + in: .current, + regions: [.canada], + isAuthoritative: true, + audit: ManualEntryAudit( + recordedAt: PreviewSupport.referenceNow, + note: "Boarding pass.", + location: nil, + ), + )), + showsCancelButton: true, + ) + } + } } } - #Preview("Edit — authoritative with audit") { - NavigationStack { - ManualDayView( - report: PreviewSupport.loadedYearReportModel(), - mode: .edit(DayPresence( - date: .now, - in: .current, - regions: [.canada], - isAuthoritative: true, - audit: ManualEntryAudit( - recordedAt: .now, - note: "Corrected after reviewing my boarding pass.", - location: CapturedLocation( - coordinate: Coordinate(latitude: 49.2827, longitude: -123.1207), - horizontalAccuracy: 12, - timestamp: .now, - ), - ), - )), - ) - } + #Preview { + ManualDayView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Onboarding/OnboardingView.swift b/Where/WhereUI/Sources/Onboarding/OnboardingView.swift index 43929c2d..ef101854 100644 --- a/Where/WhereUI/Sources/Onboarding/OnboardingView.swift +++ b/Where/WhereUI/Sources/Onboarding/OnboardingView.swift @@ -1,4 +1,5 @@ import LifecycleKit +import SnapshotKit import SwiftUI import UniformTypeIdentifiers import WhereCore @@ -329,9 +330,18 @@ struct OnboardingPage: Identifiable { } #if DEBUG + extension OnboardingView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .screenDefaults) { + let model = PreviewSupport.onboardingModel() + OnboardingView(bridge: LifecycleStepUIBridge(reason: .userForeground)) + .environment(model) + .environment(model.session) + } + } + } + #Preview { - OnboardingView(bridge: LifecycleStepUIBridge(reason: .userForeground)) - .environment(PreviewSupport.loadedModel()) - .environment(PreviewSupport.loadedSession()) + OnboardingView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Preview/AppFlowSnapshots.swift b/Where/WhereUI/Sources/Preview/AppFlowSnapshots.swift deleted file mode 100644 index fff7b5d2..00000000 --- a/Where/WhereUI/Sources/Preview/AppFlowSnapshots.swift +++ /dev/null @@ -1,62 +0,0 @@ -#if DEBUG - import LifecycleKit - import SnapshotKit - import SwiftUI - - // Snapshot matrices for the app-flow surfaces: the launch splash, onboarding, - // and the root scene. RootView drives its own launch runner over a preloaded - // model, so with animations disabled the capture settles on the logged-in UI. - - extension LaunchSplashView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .phoneLightDark) { - LaunchSplashView(previewImageName: "AppIconClassic") - } - whereSnapshot(name: "SlowLaunchCaption", configurations: .phoneLightDark) { - LaunchSplashView(previewImageName: "AppIconClassic", previewShowsCaption: true) - } - } - } - - extension OnboardingView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .screenDefaults) { - let model = WhereModel(services: PreviewSupport.previewServices()) - OnboardingView(bridge: LifecycleStepUIBridge(reason: .userForeground)) - .environment(model) - .environment(model.session) - } - } - } - - extension RootView: SnapshotProviding { - /// The logged-in root is multi-phase async work — splash → launch steps → - /// `.ready` → `MainTabs` activation → glass-material adaptation — and - /// every phase is pixel-quiet under capture (motion frozen, animations - /// disabled), so pixel stability alone can bake *any* intermediate phase - /// on a slow runner (CI captured the splash and the pre-activation tabs). - /// - /// The pre-capture hook awaits the launcher's drive — `run()` is - /// idempotent and awaits the in-flight drive, a deterministic "reached - /// `.ready`" signal — so the raised settle floor only has to outlast the - /// post-ready tail: `MainTabs`' `.task` activation (empty-store re-pull + - /// Resolve badge) and the iOS 26 glass toolbar/tab bar material - /// adaptation, which starts quiet a few hundred ms after the chrome - /// hosts. Those have no reachable completion signal (the scene's report - /// model is private to `MainTabs`; the adaptation has no public - /// notification), hence the generous floor — see the flakiness ledger in - /// `Where/TODOs.md`. - public static var snapshots: [SnapshotCase] { - let model = PreviewSupport.loadedModel() - let launcher = WhereLaunch.makeLauncher(model: model, reason: .userForeground) - whereSnapshot( - name: "LoggedIn", - configurations: .phoneLightDark, - settle: .settledAtLeast(minDuration: 1.5), - onReadyToSnapshot: { await launcher.run() }, - ) { - RootView(model: model, launcher: launcher) - } - } - } -#endif diff --git a/Where/WhereUI/Sources/Preview/PreviewSupport.swift b/Where/WhereUI/Sources/Preview/PreviewSupport.swift index 770961ac..f89c4ceb 100644 --- a/Where/WhereUI/Sources/Preview/PreviewSupport.swift +++ b/Where/WhereUI/Sources/Preview/PreviewSupport.swift @@ -399,12 +399,32 @@ ) } + /// Fixed day for widget previews and snapshots — a single pinned instant + /// so the day/year chrome renders identically whenever a capture runs + /// (an unpinned `.now` default churned references daily). Widget captures + /// pin the timezone (Pacific), so this reads as a stable calendar day. + public static let referenceWidgetDay = Date(timeIntervalSince1970: 1_770_000_000) + + /// A fresh, not-yet-onboarded model over **in-memory** preferences — for + /// the onboarding preview/snapshot. Uses `InMemoryKeyValueStore` rather + /// than the default `WherePreferences()` (which is backed by + /// `UserDefaults.standard`) so the fixture honors PreviewSupport's + /// no-disk contract and the host's real defaults can't leak in. + @MainActor + public static func onboardingModel() -> WhereModel { + WhereModel( + services: previewServices(), + preferences: WherePreferences(store: InMemoryKeyValueStore()), + now: { referenceNow }, + ) + } + /// A widget snapshot built from the sample year totals, for widget /// previews and tests. public static func sampleWidgetSnapshot( dayRegions: Set = [.california], totals: [Region: Int]? = nil, - day: Date = .now, + day: Date = PreviewSupport.referenceWidgetDay, year: Int = PreviewSupport.year, ) -> WidgetSnapshot { WidgetSnapshot( diff --git a/Where/WhereUI/Sources/Preview/ScreenSnapshots.swift b/Where/WhereUI/Sources/Preview/ScreenSnapshots.swift deleted file mode 100644 index dc70ab1c..00000000 --- a/Where/WhereUI/Sources/Preview/ScreenSnapshots.swift +++ /dev/null @@ -1,355 +0,0 @@ -#if DEBUG - import RegionKit - import SnapshotKit - import SwiftUI - import WhereCore - - // Snapshot matrices for the top-level WhereUI screens, driving both the - // `#Preview` cutsheets and the `WhereUISnapshotTests` image tests off one - // declaration. Fixtures come from `PreviewSupport`; `whereSnapshot(...)` seeds - // the Broadway root so trait-aware stylesheet tokens resolve. - - extension PrimaryView: SnapshotProviding { - /// The raised settle floor on `Loaded` outlasts the iOS 26 glass toolbar - /// material adaptation (seen pre-adaptation once on `Loaded_iPhone`) — - /// same mechanism as `RootView.LoggedIn`. - public static var snapshots: [SnapshotCase] { - whereSnapshot( - name: "Loaded", - configurations: .screenDefaults, - settle: .settledAtLeast(minDuration: 1.0), - ) { - PrimaryView(report: PreviewSupport.loadedYearReportModel()) - } - whereSnapshot(name: "ElsewhereOnly", configurations: .phoneLightDark) { - PrimaryView(report: PreviewSupport.elsewhereOnlyYearReportModel()) - } - whereSnapshot(name: "MissingDays", configurations: .phoneLightDark) { - PrimaryView(report: PreviewSupport.missingDaysYearReportModel()) - } - } - } - - extension SecondaryView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Loaded", configurations: .screenDefaults) { - SecondaryView(report: PreviewSupport.loadedYearReportModel()) - } - } - } - - extension SettingsView: SnapshotProviding { - /// The extra right-to-left variant exercises the RTL configuration axis - /// on a directional screen (leading labels, trailing values/toggles). - public static var snapshots: [SnapshotCase] { - whereSnapshot( - name: "Default", - configurations: .screenDefaults + [ - SnapshotConfiguration(layoutDirection: .rightToLeft, device: .iPhone), - ], - ) { - SettingsView(report: PreviewSupport.loadedYearReportModel()) - .environment(PreviewSupport.loadedModel()) - .environment(PreviewSupport.loadedSession()) - } - } - } - - extension ResolutionView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "WithIssues", configurations: .screenDefaults) { - ResolutionView( - report: PreviewSupport.loadedYearReportModel(), - resolve: PreviewSupport.resolveModel(), - ) - } - whereSnapshot(name: "Empty", configurations: .phoneLightDark) { - ResolutionView( - report: PreviewSupport.loadedYearReportModel(), - resolve: PreviewSupport.resolveModel(seededWithIssues: false), - ) - } - } - } - - extension FlightDayDetailView: SnapshotProviding { - /// The flight-day fixture pins its day to `referenceNow` (the source - /// file's `#Preview` uses `.now`, which would churn the reference - /// daily). The preview store seeds no raw samples, so the recorded- - /// points map stays out of the tree and the capture is deterministic. - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .screenDefaults) { - NavigationStack { - FlightDayDetailView( - issue: FlightDayIssue( - day: DayPresence( - date: PreviewSupport.referenceNow, - in: .current, - regions: [.newYork, .other, .california], - ), - keepRegions: [.newYork, .california], - removedRegions: [.other], - peakSpeedKMH: 880, - ), - report: PreviewSupport.loadedYearReportModel(), - resolve: PreviewSupport.resolveModel(), - ) - } - } - } - } - - extension RegionDaysView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "WithData", configurations: .screenDefaults) { - NavigationStack { - RegionDaysView( - region: .other, - report: PreviewSupport.elsewhereOnlyYearReportModel(), - ) - } - } - } - } - - extension RegionMapView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .phoneLightDark) { - NavigationStack { RegionMapView() } - } - } - } - - extension DayRelabelView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .screenDefaults) { - NavigationStack { - DayRelabelView( - day: DayPresence( - date: PreviewSupport.referenceNow, - in: .current, - regions: [.other], - ), - report: PreviewSupport.loadedYearReportModel(), - ) - } - } - whereSnapshot(name: "WithAudit", configurations: .phoneLightDark) { - NavigationStack { - DayRelabelView( - day: DayPresence( - date: PreviewSupport.referenceNow, - in: .current, - regions: [.california], - isAuthoritative: true, - audit: ManualEntryAudit( - recordedAt: PreviewSupport.referenceNow, - note: "Corrected after reviewing my boarding pass.", - location: CapturedLocation( - coordinate: Coordinate(latitude: 37.7749, longitude: -122.4194), - horizontalAccuracy: 12, - timestamp: PreviewSupport.referenceNow, - ), - ), - ), - report: PreviewSupport.loadedYearReportModel(), - ) - } - } - } - } - - extension RecentActivitySummaryView: SnapshotProviding { - // A NavigationStack + ScrollView sheet is a screen, not an intrinsic - // component: greedy containers have no meaningful `sizeThatFits`, so - // intrinsic sizing would measure just the pinned window picker. - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Loaded", configurations: .screenDefaults) { - RecentActivitySummaryView( - model: PreviewSupport.recentActivityModel( - state: .loaded("You were in California, then New York."), - ), - ) - } - whereSnapshot(name: "Empty", configurations: .phoneLightDark) { - RecentActivitySummaryView(model: PreviewSupport.recentActivityModel(state: .empty)) - } - whereSnapshot(name: "Unavailable", configurations: .phoneLightDark) { - RecentActivitySummaryView( - model: PreviewSupport.recentActivityModel( - state: .unavailable(.appleIntelligenceNotEnabled), - ), - ) - } - whereSnapshot(name: "Failed", configurations: .phoneLightDark) { - RecentActivitySummaryView( - model: PreviewSupport - .recentActivityModel(state: .failed("Something went wrong.")), - ) - } - } - } - - extension PresenceTimelineView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "WithData", configurations: .screenDefaults) { - PresenceTimelineView(report: PreviewSupport.loadedYearReportModel()) - } - } - } - - extension CalendarView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "WithData", configurations: .screenDefaults) { - CalendarView(report: PreviewSupport.loadedYearReportModel()) - } - // The whole sample year in one image: the full-content frame - // measures the scroll view's content height, so all 12 lazy months - // materialize and nothing scrolls. Wraps `CalendarYearGrid` — the - // scrollable content — not `CalendarView` itself, whose - // `NavigationStack` chrome defeats content measurement (see - // `Frame.fullContent`). - whereSnapshot( - name: "FullYear", - configurations: [ - SnapshotConfiguration(device: .fullContent(name: "fullHeight", width: 402)), - ], - ) { - CalendarYearGrid(months: fullYearMonths(), focusedRegion: nil) { _ in } - } - } - - /// The sample year's month grids, laid out synchronously (fixture - /// failure is a programmer error, not a state to render). - private static func fullYearMonths() -> [CalendarMonth] { - let report = PreviewSupport.loadedYearReportModel() - guard let yearReport = report.report else { - preconditionFailure("The loaded preview fixture must carry a year report.") - } - do { - return try yearReport.calendarMonths( - calendar: report.calendar, - referenceDate: report.referenceDate, - missingDates: report.missingDayKeys, - evidenceDays: report.evidenceDayKeys, - focusedRegion: nil, - ) - } catch { - preconditionFailure("The sample year failed to lay out calendar months: \(error)") - } - } - } - - extension AppIconView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .screenDefaults, settle: .immediate) { - NavigationStack { AppIconView(model: .preview()) } - } - } - } - - extension LoggedDaysView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Loaded", configurations: .screenDefaults) { - LoggedDaysView( - report: PreviewSupport.loadedYearReportModel(), - model: PreviewSupport - .loggedDaysModel(state: .loaded(PreviewSupport.sampleManualDays())), - ) - } - whereSnapshot(name: "Empty", configurations: .phoneLightDark) { - LoggedDaysView( - report: PreviewSupport.loadedYearReportModel(), - model: PreviewSupport.loggedDaysModel(state: .empty), - ) - } - whereSnapshot(name: "Failed", configurations: .phoneLightDark) { - LoggedDaysView( - report: PreviewSupport.loadedYearReportModel(), - model: PreviewSupport.loggedDaysModel(state: .failed("iCloud is unavailable.")), - ) - } - } - } - - extension ManualDayView: SnapshotProviding { - /// A plain add (`prefill: nil`) would default its date pickers to the - /// real current date and churn the references daily, so the add cases - /// prefill a fixed single day instead — same form, deterministic date. - private static var addPrefill: MissingDayRange { - let day = CalendarDay(from: PreviewSupport.referenceNow, in: .current) - return MissingDayRange(start: day, end: day, dayCount: 1) - } - - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Add", configurations: .screenDefaults) { - NavigationStack { - ManualDayView( - report: PreviewSupport.loadedYearReportModel(), - mode: .add(prefill: addPrefill), - showsCancelButton: false, - ) - } - } - whereSnapshot(name: "AddWithCancel", configurations: .phoneLightDark) { - NavigationStack { - ManualDayView( - report: PreviewSupport.loadedYearReportModel(), - mode: .add(prefill: addPrefill), - showsCancelButton: true, - ) - } - } - whereSnapshot(name: "EditPlain", configurations: .phoneLightDark) { - NavigationStack { - ManualDayView( - report: PreviewSupport.loadedYearReportModel(), - mode: .edit(DayPresence( - date: PreviewSupport.referenceNow, - in: .current, - regions: [.california], - )), - showsCancelButton: true, - ) - } - } - whereSnapshot(name: "EditAuthoritative", configurations: .phoneLightDark) { - NavigationStack { - ManualDayView( - report: PreviewSupport.loadedYearReportModel(), - mode: .edit(DayPresence( - date: PreviewSupport.referenceNow, - in: .current, - regions: [.canada], - isAuthoritative: true, - audit: ManualEntryAudit( - recordedAt: PreviewSupport.referenceNow, - note: "Boarding pass.", - location: nil, - ), - )), - showsCancelButton: true, - ) - } - } - } - } - - extension DeveloperToolsView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Default", configurations: .phoneLightDark) { - DeveloperToolsView() - .environment(PreviewSupport.loadedSession()) - } - } - } - - extension DeveloperOverlay: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Collapsed", configurations: .phoneLightDark) { - DeveloperOverlay() - .environment(PreviewSupport.loadedSession()) - } - } - } -#endif diff --git a/Where/WhereUI/Sources/Preview/WidgetSnapshots.swift b/Where/WhereUI/Sources/Preview/WidgetSnapshots.swift deleted file mode 100644 index a2f28a70..00000000 --- a/Where/WhereUI/Sources/Preview/WidgetSnapshots.swift +++ /dev/null @@ -1,125 +0,0 @@ -#if DEBUG - import RegionKit - import SnapshotKit - import SwiftUI - import WhereCore - - // Snapshot matrices for the widget entry views and lock-screen accessories. - // Fixtures use a fixed day so the captures stay deterministic regardless of - // when they run. - - private let widgetSnapshotDay = Date(timeIntervalSince1970: 1_770_000_000) - - private func widgetSnapshot( - dayRegions: Set, - totals: [Region: Int], - ) -> WidgetSnapshot { - WidgetSnapshot( - day: widgetSnapshotDay, - year: PreviewSupport.year, - dayRegions: dayRegions, - totals: totals, - ) - } - - extension TodayWidgetView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot( - name: "SingleRegion", - configurations: .componentDefaults, - settle: .immediate, - ) { - TodayWidgetView(snapshot: widgetSnapshot( - dayRegions: [.california], - totals: [.california: 132], - )) - } - whereSnapshot( - name: "MultiRegion", - configurations: .componentLightDark, - settle: .immediate, - ) { - TodayWidgetView(snapshot: widgetSnapshot( - dayRegions: [.california, .newYork], - totals: [.california: 132, .newYork: 41], - )) - } - whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { - TodayWidgetView(snapshot: widgetSnapshot(dayRegions: [], totals: [:])) - } - } - } - - extension YearTotalsWidgetView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Ranked", configurations: .componentDefaults, settle: .immediate) { - YearTotalsWidgetView(snapshot: widgetSnapshot( - dayRegions: [.california], - totals: [ - .california: 132, - .newYork: 41, - .canada: 9, - .europeanUnion: 4, - .other: 2, - ], - )) - } - whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { - YearTotalsWidgetView(snapshot: widgetSnapshot(dayRegions: [], totals: [:])) - } - } - } - - extension TodayInlineAccessoryView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot( - name: "Regions", - configurations: .componentLightDark, - settle: .immediate, - ) { - TodayInlineAccessoryView(snapshot: widgetSnapshot( - dayRegions: [.california, .newYork], - totals: [.california: 132, .newYork: 41], - )) - } - whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { - TodayInlineAccessoryView(snapshot: widgetSnapshot(dayRegions: [], totals: [:])) - } - } - } - - extension TodayCircularAccessoryView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot( - name: "Regions", - configurations: .componentLightDark, - settle: .immediate, - ) { - TodayCircularAccessoryView(snapshot: widgetSnapshot( - dayRegions: [.california, .newYork], - totals: [.california: 132, .newYork: 41], - )) - } - whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { - TodayCircularAccessoryView(snapshot: widgetSnapshot(dayRegions: [], totals: [:])) - } - } - } - - extension YearTotalsRectangularAccessoryView: SnapshotProviding { - public static var snapshots: [SnapshotCase] { - whereSnapshot(name: "Ranked", configurations: .componentLightDark, settle: .immediate) { - YearTotalsRectangularAccessoryView(snapshot: widgetSnapshot( - dayRegions: [.california], - totals: [.california: 132, .newYork: 41, .canada: 9, .other: 2], - )) - } - whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { - YearTotalsRectangularAccessoryView(snapshot: widgetSnapshot( - dayRegions: [], - totals: [:], - )) - } - } - } -#endif diff --git a/Where/WhereUI/Sources/Primary/CalendarView.swift b/Where/WhereUI/Sources/Primary/CalendarView.swift index fe17d6dd..27f93634 100644 --- a/Where/WhereUI/Sources/Primary/CalendarView.swift +++ b/Where/WhereUI/Sources/Primary/CalendarView.swift @@ -388,19 +388,49 @@ private struct DayCell: View { } #if DEBUG - #Preview("Loaded") { - CalendarView(report: PreviewSupport.loadedYearReportModel()) - } - - #Preview("Focused") { - CalendarView(focusedRegion: .california, report: PreviewSupport.loadedYearReportModel()) - } + extension CalendarView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "WithData", configurations: .screenDefaults) { + CalendarView(report: PreviewSupport.loadedYearReportModel()) + } + // The whole sample year in one image: the full-content frame + // measures the scroll view's content height, so all 12 lazy months + // materialize and nothing scrolls. Wraps `CalendarYearGrid` — the + // scrollable content — not `CalendarView` itself, whose + // `NavigationStack` chrome defeats content measurement (see + // `Frame.fullContent`). + whereSnapshot( + name: "FullYear", + configurations: [ + SnapshotConfiguration(device: .fullContent(name: "fullHeight", width: 402)), + ], + ) { + CalendarYearGrid(months: fullYearMonths(), focusedRegion: nil) { _ in } + } + } - #Preview("Empty") { - CalendarView(report: PreviewSupport.emptyYearReportModel()) + /// The sample year's month grids, laid out synchronously (fixture + /// failure is a programmer error, not a state to render). + private static func fullYearMonths() -> [CalendarMonth] { + let report = PreviewSupport.loadedYearReportModel() + guard let yearReport = report.report else { + preconditionFailure("The loaded preview fixture must carry a year report.") + } + do { + return try yearReport.calendarMonths( + calendar: report.calendar, + referenceDate: report.referenceDate, + missingDates: report.missingDayKeys, + evidenceDays: report.evidenceDayKeys, + focusedRegion: nil, + ) + } catch { + preconditionFailure("The sample year failed to lay out calendar months: \(error)") + } + } } - #Preview("Missing days") { - CalendarView(report: PreviewSupport.missingDaysYearReportModel()) + #Preview { + CalendarView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Primary/PresenceTimelineView.swift b/Where/WhereUI/Sources/Primary/PresenceTimelineView.swift index 7a615fe3..14b51578 100644 --- a/Where/WhereUI/Sources/Primary/PresenceTimelineView.swift +++ b/Where/WhereUI/Sources/Primary/PresenceTimelineView.swift @@ -1,3 +1,4 @@ +import SnapshotKit import SwiftUI import WhereCore @@ -129,7 +130,15 @@ private struct StintRow: View { } #if DEBUG + extension PresenceTimelineView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "WithData", configurations: .screenDefaults) { + PresenceTimelineView(report: PreviewSupport.loadedYearReportModel()) + } + } + } + #Preview { - PresenceTimelineView(report: PreviewSupport.loadedYearReportModel()) + PresenceTimelineView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Primary/PrimaryView.swift b/Where/WhereUI/Sources/Primary/PrimaryView.swift index d69cd51e..60341ffd 100644 --- a/Where/WhereUI/Sources/Primary/PrimaryView.swift +++ b/Where/WhereUI/Sources/Primary/PrimaryView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -207,19 +208,28 @@ struct PrimaryView: View { } #if DEBUG - #Preview("Loaded") { - PrimaryView(report: PreviewSupport.loadedYearReportModel()) - } - - #Preview("Empty") { - PrimaryView(report: PreviewSupport.emptyYearReportModel()) - } - - #Preview("Missing days") { - PrimaryView(report: PreviewSupport.missingDaysYearReportModel()) + extension PrimaryView: SnapshotProviding { + /// The raised settle floor on `Loaded` outlasts the iOS 26 glass toolbar + /// material adaptation (seen pre-adaptation once on `Loaded_iPhone`) — + /// same mechanism as `RootView.LoggedIn`. + static var snapshots: [SnapshotCase] { + whereSnapshot( + name: "Loaded", + configurations: .screenDefaults, + settle: .settledAtLeast(minDuration: 1.0), + ) { + PrimaryView(report: PreviewSupport.loadedYearReportModel()) + } + whereSnapshot(name: "ElsewhereOnly", configurations: .phoneLightDark) { + PrimaryView(report: PreviewSupport.elsewhereOnlyYearReportModel()) + } + whereSnapshot(name: "MissingDays", configurations: .phoneLightDark) { + PrimaryView(report: PreviewSupport.missingDaysYearReportModel()) + } + } } - #Preview("Elsewhere only") { - PrimaryView(report: PreviewSupport.elsewhereOnlyYearReportModel()) + #Preview { + PrimaryView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Primary/RecentActivitySummaryView.swift b/Where/WhereUI/Sources/Primary/RecentActivitySummaryView.swift index bc2f7d7f..da8b8c34 100644 --- a/Where/WhereUI/Sources/Primary/RecentActivitySummaryView.swift +++ b/Where/WhereUI/Sources/Primary/RecentActivitySummaryView.swift @@ -1,3 +1,4 @@ +import SnapshotKit import SwiftUI import WhereCore @@ -128,29 +129,38 @@ struct RecentActivitySummaryView: View { } #if DEBUG - #Preview("Loaded") { - RecentActivitySummaryView( - model: PreviewSupport.recentActivityModel( - state: .loaded( - "You spent the morning in California near San Francisco, then traveled to New York in the early evening, where the most recent readings place you.", - ), - ), - ) - } - - #Preview("Loading") { - RecentActivitySummaryView(model: PreviewSupport.recentActivityModel(state: .loading)) - } - - #Preview("Empty") { - RecentActivitySummaryView(model: PreviewSupport.recentActivityModel(state: .empty)) + extension RecentActivitySummaryView: SnapshotProviding { + // A NavigationStack + ScrollView sheet is a screen, not an intrinsic + // component: greedy containers have no meaningful `sizeThatFits`, so + // intrinsic sizing would measure just the pinned window picker. + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Loaded", configurations: .screenDefaults) { + RecentActivitySummaryView( + model: PreviewSupport.recentActivityModel( + state: .loaded("You were in California, then New York."), + ), + ) + } + whereSnapshot(name: "Empty", configurations: .phoneLightDark) { + RecentActivitySummaryView(model: PreviewSupport.recentActivityModel(state: .empty)) + } + whereSnapshot(name: "Unavailable", configurations: .phoneLightDark) { + RecentActivitySummaryView( + model: PreviewSupport.recentActivityModel( + state: .unavailable(.appleIntelligenceNotEnabled), + ), + ) + } + whereSnapshot(name: "Failed", configurations: .phoneLightDark) { + RecentActivitySummaryView( + model: PreviewSupport + .recentActivityModel(state: .failed("Something went wrong.")), + ) + } + } } - #Preview("Unavailable") { - RecentActivitySummaryView( - model: PreviewSupport.recentActivityModel( - state: .unavailable(.appleIntelligenceNotEnabled), - ), - ) + #Preview { + RecentActivitySummaryView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Resolution/FlightDayDetailView.swift b/Where/WhereUI/Sources/Resolution/FlightDayDetailView.swift index a428d0a1..28085c85 100644 --- a/Where/WhereUI/Sources/Resolution/FlightDayDetailView.swift +++ b/Where/WhereUI/Sources/Resolution/FlightDayDetailView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -165,22 +166,34 @@ struct FlightDayDetailView: View { } #if DEBUG - #Preview { - NavigationStack { - FlightDayDetailView( - issue: FlightDayIssue( - day: DayPresence( - date: .now, - in: .current, - regions: [.newYork, .other, .california], - ), - keepRegions: [.newYork, .california], - removedRegions: [.other], - peakSpeedKMH: 880, - ), - report: PreviewSupport.loadedYearReportModel(), - resolve: PreviewSupport.resolveModel(), - ) + extension FlightDayDetailView: SnapshotProviding { + /// The flight-day fixture pins its day to `referenceNow` (a bespoke + /// `.now` would churn the reference daily). The preview store seeds no + /// raw samples, so the recorded-points map stays out of the tree and the + /// capture is deterministic. + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .screenDefaults) { + NavigationStack { + FlightDayDetailView( + issue: FlightDayIssue( + day: DayPresence( + date: PreviewSupport.referenceNow, + in: .current, + regions: [.newYork, .other, .california], + ), + keepRegions: [.newYork, .california], + removedRegions: [.other], + peakSpeedKMH: 880, + ), + report: PreviewSupport.loadedYearReportModel(), + resolve: PreviewSupport.resolveModel(), + ) + } + } } } + + #Preview { + FlightDayDetailView.snapshotPreviews + } #endif diff --git a/Where/WhereUI/Sources/Resolution/ResolutionView.swift b/Where/WhereUI/Sources/Resolution/ResolutionView.swift index 368df82d..e4282a63 100644 --- a/Where/WhereUI/Sources/Resolution/ResolutionView.swift +++ b/Where/WhereUI/Sources/Resolution/ResolutionView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -200,17 +201,24 @@ private struct IssueRow: View { } #if DEBUG - #Preview("Loaded") { - ResolutionView( - report: PreviewSupport.loadedYearReportModel(), - resolve: PreviewSupport.resolveModel(), - ) + extension ResolutionView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "WithIssues", configurations: .screenDefaults) { + ResolutionView( + report: PreviewSupport.loadedYearReportModel(), + resolve: PreviewSupport.resolveModel(), + ) + } + whereSnapshot(name: "Empty", configurations: .phoneLightDark) { + ResolutionView( + report: PreviewSupport.loadedYearReportModel(), + resolve: PreviewSupport.resolveModel(seededWithIssues: false), + ) + } + } } - #Preview("Empty") { - ResolutionView( - report: PreviewSupport.loadedYearReportModel(), - resolve: PreviewSupport.resolveModel(seededWithIssues: false), - ) + #Preview { + ResolutionView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/RootView.swift b/Where/WhereUI/Sources/RootView.swift index 65eccd50..3b2a3684 100644 --- a/Where/WhereUI/Sources/RootView.swift +++ b/Where/WhereUI/Sources/RootView.swift @@ -1,4 +1,5 @@ import LifecycleKit +import SnapshotKit import SwiftUI import WhereCore @@ -142,22 +143,45 @@ public struct RootView: View { } #if DEBUG - private struct LoggedInRootPreview: View { - private let model = PreviewSupport.loadedModel() - - var body: some View { - RootView( - model: model, - launcher: WhereLaunch.makeLauncher(model: model, reason: .userForeground), - ) + extension RootView: SnapshotProviding { + /// The logged-in root is multi-phase async work — splash → launch steps → + /// `.ready` → `MainTabs` activation → glass-material adaptation — and + /// every phase is pixel-quiet under capture (motion frozen, animations + /// disabled), so pixel stability alone can bake *any* intermediate phase + /// on a slow runner (CI captured the splash and the pre-activation tabs). + /// + /// The pre-capture hook awaits the launcher's drive — `run()` is + /// idempotent and awaits the in-flight drive, a deterministic "reached + /// `.ready`" signal — so the raised settle floor only has to outlast the + /// post-ready tail: `MainTabs`' `.task` activation (empty-store re-pull + + /// Resolve badge) and the iOS 26 glass toolbar/tab bar material + /// adaptation, which starts quiet a few hundred ms after the chrome + /// hosts. Those have no reachable completion signal (the scene's report + /// model is private to `MainTabs`; the adaptation has no public + /// notification), hence the generous floor — see the flakiness ledger in + /// `Where/TODOs.md`. + public static var snapshots: [SnapshotCase] { + let model = PreviewSupport.loadedModel() + let launcher = WhereLaunch.makeLauncher(model: model, reason: .userForeground) + whereSnapshot( + name: "LoggedIn", + configurations: .phoneLightDark, + settle: .settledAtLeast(minDuration: 1.5), + onReadyToSnapshot: { await launcher.run() }, + ) { + RootView(model: model, launcher: launcher) + } } } + // The from-scratch launch preview (splash → onboarding) — the matrix pins + // only the logged-in root, so this stays as a bespoke preview alongside the + // cutsheet. #Preview { RootView() } #Preview("Logged in") { - LoggedInRootPreview() + RootView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Secondary/DayRelabelView.swift b/Where/WhereUI/Sources/Secondary/DayRelabelView.swift index 2c4d5597..4f002026 100644 --- a/Where/WhereUI/Sources/Secondary/DayRelabelView.swift +++ b/Where/WhereUI/Sources/Secondary/DayRelabelView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -251,49 +252,46 @@ struct DayRelabelView: View { } #if DEBUG - #Preview("Other region") { - NavigationStack { - DayRelabelView( - day: DayPresence(date: .now, in: .current, regions: [.other]), - report: PreviewSupport.loadedYearReportModel(), - ) - } - } - - #Preview("Flight reason banner") { - NavigationStack { - DayRelabelView( - day: DayPresence( - date: .now, - in: .current, - regions: [.newYork, .other, .california], - ), - report: PreviewSupport.loadedYearReportModel(), - reason: .flight(removed: [.other]), - ) + extension DayRelabelView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .screenDefaults) { + NavigationStack { + DayRelabelView( + day: DayPresence( + date: PreviewSupport.referenceNow, + in: .current, + regions: [.other], + ), + report: PreviewSupport.loadedYearReportModel(), + ) + } + } + whereSnapshot(name: "WithAudit", configurations: .phoneLightDark) { + NavigationStack { + DayRelabelView( + day: DayPresence( + date: PreviewSupport.referenceNow, + in: .current, + regions: [.california], + isAuthoritative: true, + audit: ManualEntryAudit( + recordedAt: PreviewSupport.referenceNow, + note: "Corrected after reviewing my boarding pass.", + location: CapturedLocation( + coordinate: Coordinate(latitude: 37.7749, longitude: -122.4194), + horizontalAccuracy: 12, + timestamp: PreviewSupport.referenceNow, + ), + ), + ), + report: PreviewSupport.loadedYearReportModel(), + ) + } + } } } - #Preview("With audit record") { - NavigationStack { - DayRelabelView( - day: DayPresence( - date: .now, - in: .current, - regions: [.california], - isAuthoritative: true, - audit: ManualEntryAudit( - recordedAt: .now, - note: "Corrected after reviewing my boarding pass.", - location: CapturedLocation( - coordinate: Coordinate(latitude: 37.7749, longitude: -122.4194), - horizontalAccuracy: 12, - timestamp: .now, - ), - ), - ), - report: PreviewSupport.loadedYearReportModel(), - ) - } + #Preview { + DayRelabelView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Secondary/RegionDaysView.swift b/Where/WhereUI/Sources/Secondary/RegionDaysView.swift index 5e84b14d..6404e4f2 100644 --- a/Where/WhereUI/Sources/Secondary/RegionDaysView.swift +++ b/Where/WhereUI/Sources/Secondary/RegionDaysView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -139,9 +140,20 @@ private struct DayRow: View { } #if DEBUG - #Preview { - NavigationStack { - RegionDaysView(region: .other, report: PreviewSupport.elsewhereOnlyYearReportModel()) + extension RegionDaysView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "WithData", configurations: .screenDefaults) { + NavigationStack { + RegionDaysView( + region: .other, + report: PreviewSupport.elsewhereOnlyYearReportModel(), + ) + } + } } } + + #Preview { + RegionDaysView.snapshotPreviews + } #endif diff --git a/Where/WhereUI/Sources/Secondary/SecondaryView.swift b/Where/WhereUI/Sources/Secondary/SecondaryView.swift index 97ff5d10..0a91afde 100644 --- a/Where/WhereUI/Sources/Secondary/SecondaryView.swift +++ b/Where/WhereUI/Sources/Secondary/SecondaryView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -107,11 +108,15 @@ struct SecondaryView: View { } #if DEBUG - #Preview("Loaded") { - SecondaryView(report: PreviewSupport.loadedYearReportModel()) + extension SecondaryView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Loaded", configurations: .screenDefaults) { + SecondaryView(report: PreviewSupport.loadedYearReportModel()) + } + } } - #Preview("Empty") { - SecondaryView(report: PreviewSupport.emptyYearReportModel()) + #Preview { + SecondaryView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Settings/AppIconView.swift b/Where/WhereUI/Sources/Settings/AppIconView.swift index 134e3ebe..83b03902 100644 --- a/Where/WhereUI/Sources/Settings/AppIconView.swift +++ b/Where/WhereUI/Sources/Settings/AppIconView.swift @@ -1,3 +1,4 @@ +import SnapshotKit import SwiftUI /// The app-icon picker. A grid of options that flexes with the container width @@ -303,12 +304,20 @@ struct AppIconImage: View { } #if DEBUG + extension AppIconView: SnapshotProviding { + static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Default", configurations: .screenDefaults, settle: .immediate) { + NavigationStack { AppIconView(model: .preview()) } + } + } + } + #Preview("Classic") { AppIconImage(name: "AppIconClassic", size: 60) .padding() } #Preview { - AppIconView(model: .preview()) + AppIconView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Settings/SettingsView.swift b/Where/WhereUI/Sources/Settings/SettingsView.swift index 1516ce1a..4e80126a 100644 --- a/Where/WhereUI/Sources/Settings/SettingsView.swift +++ b/Where/WhereUI/Sources/Settings/SettingsView.swift @@ -607,9 +607,24 @@ struct SettingsView: View { } #if DEBUG + extension SettingsView: SnapshotProviding { + /// The extra right-to-left variant exercises the RTL configuration axis + /// on a directional screen (leading labels, trailing values/toggles). + static var snapshots: [SnapshotCase] { + whereSnapshot( + name: "Default", + configurations: .screenDefaults + [ + SnapshotConfiguration(layoutDirection: .rightToLeft, device: .iPhone), + ], + ) { + SettingsView(report: PreviewSupport.loadedYearReportModel()) + .environment(PreviewSupport.loadedModel()) + .environment(PreviewSupport.loadedSession()) + } + } + } + #Preview { - SettingsView(report: PreviewSupport.loadedYearReportModel()) - .environment(PreviewSupport.loadedModel()) - .environment(PreviewSupport.loadedSession()) + SettingsView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Widgets/TodayAccessoryViews.swift b/Where/WhereUI/Sources/Widgets/TodayAccessoryViews.swift index 5cdcb2d8..634fcc4f 100644 --- a/Where/WhereUI/Sources/Widgets/TodayAccessoryViews.swift +++ b/Where/WhereUI/Sources/Widgets/TodayAccessoryViews.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore import WidgetKit @@ -73,17 +74,53 @@ public struct TodayCircularAccessoryView: View { } #if DEBUG - #Preview("Inline", traits: .fixedLayout(width: 200, height: 30)) { - TodayInlineAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( - dayRegions: [.california, .newYork], - totals: [.california: 132, .newYork: 41], - )) + extension TodayInlineAccessoryView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot( + name: "Regions", + configurations: .componentLightDark, + settle: .immediate, + ) { + TodayInlineAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [.california, .newYork], + totals: [.california: 132, .newYork: 41], + )) + } + whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { + TodayInlineAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [], + totals: [:], + )) + } + } + } + + extension TodayCircularAccessoryView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot( + name: "Regions", + configurations: .componentLightDark, + settle: .immediate, + ) { + TodayCircularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [.california, .newYork], + totals: [.california: 132, .newYork: 41], + )) + } + whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { + TodayCircularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [], + totals: [:], + )) + } + } + } + + #Preview("Inline") { + TodayInlineAccessoryView.snapshotPreviews } - #Preview("Circular", traits: .fixedLayout(width: 80, height: 80)) { - TodayCircularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( - dayRegions: [.california, .newYork], - totals: [.california: 132, .newYork: 41], - )) + #Preview("Circular") { + TodayCircularAccessoryView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Widgets/TodayWidgetView.swift b/Where/WhereUI/Sources/Widgets/TodayWidgetView.swift index 69861269..6d28cc95 100644 --- a/Where/WhereUI/Sources/Widgets/TodayWidgetView.swift +++ b/Where/WhereUI/Sources/Widgets/TodayWidgetView.swift @@ -1,4 +1,5 @@ import RegionKit +import SnapshotKit import SwiftUI import WhereCore @@ -103,24 +104,38 @@ public struct TodayWidgetView: View { } #if DEBUG - #Preview("Single region") { - TodayWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot()) - .padding() - } - - #Preview("Multi region") { - TodayWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( - dayRegions: [.california, .newYork], - totals: [.california: 132, .newYork: 41], - )) - .padding() + extension TodayWidgetView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot( + name: "SingleRegion", + configurations: .componentDefaults, + settle: .immediate, + ) { + TodayWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [.california], + totals: [.california: 132], + )) + } + whereSnapshot( + name: "MultiRegion", + configurations: .componentLightDark, + settle: .immediate, + ) { + TodayWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [.california, .newYork], + totals: [.california: 132, .newYork: 41], + )) + } + whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { + TodayWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [], + totals: [:], + )) + } + } } - #Preview("Empty") { - TodayWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( - dayRegions: [], - totals: [:], - )) - .padding() + #Preview { + TodayWidgetView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Widgets/YearTotalsRectangularAccessoryView.swift b/Where/WhereUI/Sources/Widgets/YearTotalsRectangularAccessoryView.swift index 0aede5cf..141938d1 100644 --- a/Where/WhereUI/Sources/Widgets/YearTotalsRectangularAccessoryView.swift +++ b/Where/WhereUI/Sources/Widgets/YearTotalsRectangularAccessoryView.swift @@ -1,3 +1,4 @@ +import SnapshotKit import SwiftUI import WhereCore @@ -56,14 +57,24 @@ public struct YearTotalsRectangularAccessoryView: View { } #if DEBUG - #Preview("Ranked", traits: .fixedLayout(width: 170, height: 80)) { - YearTotalsRectangularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot()) + extension YearTotalsRectangularAccessoryView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Ranked", configurations: .componentLightDark, settle: .immediate) { + YearTotalsRectangularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [.california], + totals: [.california: 132, .newYork: 41, .canada: 9, .other: 2], + )) + } + whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { + YearTotalsRectangularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [], + totals: [:], + )) + } + } } - #Preview("Empty", traits: .fixedLayout(width: 170, height: 80)) { - YearTotalsRectangularAccessoryView(snapshot: PreviewSupport.sampleWidgetSnapshot( - dayRegions: [], - totals: [:], - )) + #Preview { + YearTotalsRectangularAccessoryView.snapshotPreviews } #endif diff --git a/Where/WhereUI/Sources/Widgets/YearTotalsWidgetView.swift b/Where/WhereUI/Sources/Widgets/YearTotalsWidgetView.swift index e661b8aa..eaba16d0 100644 --- a/Where/WhereUI/Sources/Widgets/YearTotalsWidgetView.swift +++ b/Where/WhereUI/Sources/Widgets/YearTotalsWidgetView.swift @@ -1,3 +1,4 @@ +import SnapshotKit import SwiftUI import WhereCore @@ -86,16 +87,30 @@ public struct YearTotalsWidgetView: View { } #if DEBUG - #Preview("Ranked totals") { - YearTotalsWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot()) - .padding() + extension YearTotalsWidgetView: SnapshotProviding { + public static var snapshots: [SnapshotCase] { + whereSnapshot(name: "Ranked", configurations: .componentDefaults, settle: .immediate) { + YearTotalsWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [.california], + totals: [ + .california: 132, + .newYork: 41, + .canada: 9, + .europeanUnion: 4, + .other: 2, + ], + )) + } + whereSnapshot(name: "Empty", configurations: .componentLightDark, settle: .immediate) { + YearTotalsWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( + dayRegions: [], + totals: [:], + )) + } + } } - #Preview("Empty") { - YearTotalsWidgetView(snapshot: PreviewSupport.sampleWidgetSnapshot( - dayRegions: [], - totals: [:], - )) - .padding() + #Preview { + YearTotalsWidgetView.snapshotPreviews } #endif From 79f93e2dd6252cda7034e57d8afbf3d40e6430f1 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:37:05 -0700 Subject: [PATCH 3/8] Split omnibus snapshot suites into one FooSnapshotTests per view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ScreenSnapshotTests / WidgetSnapshotTests / AppFlowSnapshotTests omnibus suites lumped every view's references into three shared __Snapshots__/ directories. Split them into one FooSnapshotTests per view, each in its own file, so each view's reference images live in their own on-disk directory. Because swift-snapshot-testing keys the directory on the test file's basename and each per-view suite reuses the original @Test function name, relocating the ~210 LFS references is a pure git mv (no renames, no re-recording) — verified by a full WhereUISnapshotTests run: every suite green from its new directory with zero reference-byte changes. (The lone red, resolution.Empty_iPhone{,_dark}, is the pre-existing local rendering drift noted in the prior commit, not the move.) The two third-party inline surfaces (DebugLogViewer, SwiftDataInspector) get their own suites too, carrying their bespoke fixtures. Plan to-do: per-view-tests. --- .../AppIconViewSnapshotTests.swift | 13 ++++ .../CalendarViewSnapshotTests.swift | 14 ++++ .../DayRelabelViewSnapshotTests.swift | 13 ++++ ...wift => DebugLogViewerSnapshotTests.swift} | 73 +------------------ .../DeveloperOverlaySnapshotTests.swift | 13 ++++ .../DeveloperToolsViewSnapshotTests.swift | 13 ++++ .../FlightDayDetailViewSnapshotTests.swift | 13 ++++ .../LaunchSplashViewSnapshotTests.swift | 13 ++++ .../LoggedDaysViewSnapshotTests.swift | 13 ++++ .../ManualDayViewSnapshotTests.swift | 13 ++++ .../OnboardingViewSnapshotTests.swift | 13 ++++ .../PresenceTimelineViewSnapshotTests.swift | 13 ++++ .../PrimaryViewSnapshotTests.swift | 14 ++++ ...centActivitySummaryViewSnapshotTests.swift | 13 ++++ .../RegionDaysViewSnapshotTests.swift | 13 ++++ .../RegionMapViewSnapshotTests.swift | 13 ++++ .../ResolutionViewSnapshotTests.swift | 13 ++++ .../SnapshotTests/RootViewSnapshotTests.swift | 13 ++++ .../SecondaryViewSnapshotTests.swift | 13 ++++ .../SettingsViewSnapshotTests.swift | 13 ++++ ... => SwiftDataInspectorSnapshotTests.swift} | 21 ++---- ...ayCircularAccessoryViewSnapshotTests.swift | 13 ++++ ...odayInlineAccessoryViewSnapshotTests.swift | 13 ++++ .../TodayWidgetViewSnapshotTests.swift | 13 ++++ .../SnapshotTests/WidgetSnapshotTests.swift | 29 -------- ...ectangularAccessoryViewSnapshotTests.swift | 13 ++++ .../YearTotalsWidgetViewSnapshotTests.swift | 13 ++++ .../appIcon.Default_iPad.png | 0 .../appIcon.Default_iPad_accessibility.png | 0 .../appIcon.Default_iPad_ax5.png | 0 .../appIcon.Default_iPad_contrast.png | 0 .../appIcon.Default_iPad_dark.png | 0 .../appIcon.Default_iPhone.png | 0 .../appIcon.Default_iPhone_accessibility.png | 0 .../appIcon.Default_iPhone_ax5.png | 0 .../appIcon.Default_iPhone_contrast.png | 0 .../appIcon.Default_iPhone_dark.png | 0 .../calendar.FullYear_fullHeight.png | 0 .../calendar.WithData_iPad.png | 0 .../calendar.WithData_iPad_accessibility.png | 0 .../calendar.WithData_iPad_ax5.png | 0 .../calendar.WithData_iPad_contrast.png | 0 .../calendar.WithData_iPad_dark.png | 0 .../calendar.WithData_iPhone.png | 0 ...calendar.WithData_iPhone_accessibility.png | 0 .../calendar.WithData_iPhone_ax5.png | 0 .../calendar.WithData_iPhone_contrast.png | 0 .../calendar.WithData_iPhone_dark.png | 0 .../dayRelabel.Default_iPad.png | 0 .../dayRelabel.Default_iPad_accessibility.png | 0 .../dayRelabel.Default_iPad_ax5.png | 0 .../dayRelabel.Default_iPad_contrast.png | 0 .../dayRelabel.Default_iPad_dark.png | 0 .../dayRelabel.Default_iPhone.png | 0 ...ayRelabel.Default_iPhone_accessibility.png | 0 .../dayRelabel.Default_iPhone_ax5.png | 0 .../dayRelabel.Default_iPhone_contrast.png | 0 .../dayRelabel.Default_iPhone_dark.png | 0 .../dayRelabel.WithAudit_iPhone.png | 0 .../dayRelabel.WithAudit_iPhone_dark.png | 0 .../debugLogViewer.DebugLogViewer_iPhone.png | 0 ...ugLogViewer.DebugLogViewer_iPhone_dark.png | 0 .../developerOverlay.Collapsed_iPhone.png | 0 ...developerOverlay.Collapsed_iPhone_dark.png | 0 .../developerTools.Default_iPhone.png | 0 .../developerTools.Default_iPhone_dark.png | 0 .../flightDayDetail.Default_iPad.png | 0 ...htDayDetail.Default_iPad_accessibility.png | 0 .../flightDayDetail.Default_iPad_ax5.png | 0 .../flightDayDetail.Default_iPad_contrast.png | 0 .../flightDayDetail.Default_iPad_dark.png | 0 .../flightDayDetail.Default_iPhone.png | 0 ...DayDetail.Default_iPhone_accessibility.png | 0 .../flightDayDetail.Default_iPhone_ax5.png | 0 ...lightDayDetail.Default_iPhone_contrast.png | 0 .../flightDayDetail.Default_iPhone_dark.png | 0 .../launchSplash.Default_iPhone.png | 0 .../launchSplash.Default_iPhone_dark.png | 0 .../launchSplash.SlowLaunchCaption_iPhone.png | 0 ...chSplash.SlowLaunchCaption_iPhone_dark.png | 0 .../loggedDays.Empty_iPhone.png | 0 .../loggedDays.Empty_iPhone_dark.png | 0 .../loggedDays.Failed_iPhone.png | 0 .../loggedDays.Failed_iPhone_dark.png | 0 .../loggedDays.Loaded_iPad.png | 0 .../loggedDays.Loaded_iPad_accessibility.png | 0 .../loggedDays.Loaded_iPad_ax5.png | 0 .../loggedDays.Loaded_iPad_contrast.png | 0 .../loggedDays.Loaded_iPad_dark.png | 0 .../loggedDays.Loaded_iPhone.png | 0 ...loggedDays.Loaded_iPhone_accessibility.png | 0 .../loggedDays.Loaded_iPhone_ax5.png | 0 .../loggedDays.Loaded_iPhone_contrast.png | 0 .../loggedDays.Loaded_iPhone_dark.png | 0 .../manualDay.AddWithCancel_iPhone.png | 0 .../manualDay.AddWithCancel_iPhone_dark.png | 0 .../manualDay.Add_iPad.png | 0 .../manualDay.Add_iPad_accessibility.png | 0 .../manualDay.Add_iPad_ax5.png | 0 .../manualDay.Add_iPad_contrast.png | 0 .../manualDay.Add_iPad_dark.png | 0 .../manualDay.Add_iPhone.png | 0 .../manualDay.Add_iPhone_accessibility.png | 0 .../manualDay.Add_iPhone_ax5.png | 0 .../manualDay.Add_iPhone_contrast.png | 0 .../manualDay.Add_iPhone_dark.png | 0 .../manualDay.EditAuthoritative_iPhone.png | 0 ...anualDay.EditAuthoritative_iPhone_dark.png | 0 .../manualDay.EditPlain_iPhone.png | 0 .../manualDay.EditPlain_iPhone_dark.png | 0 .../onboarding.Default_iPad.png | 0 .../onboarding.Default_iPad_accessibility.png | 0 .../onboarding.Default_iPad_ax5.png | 0 .../onboarding.Default_iPad_contrast.png | 0 .../onboarding.Default_iPad_dark.png | 0 .../onboarding.Default_iPhone.png | 0 ...nboarding.Default_iPhone_accessibility.png | 0 .../onboarding.Default_iPhone_ax5.png | 0 .../onboarding.Default_iPhone_contrast.png | 0 .../onboarding.Default_iPhone_dark.png | 0 .../presenceTimeline.WithData_iPad.png | 0 ...ceTimeline.WithData_iPad_accessibility.png | 0 .../presenceTimeline.WithData_iPad_ax5.png | 0 ...resenceTimeline.WithData_iPad_contrast.png | 0 .../presenceTimeline.WithData_iPad_dark.png | 0 .../presenceTimeline.WithData_iPhone.png | 0 ...Timeline.WithData_iPhone_accessibility.png | 0 .../presenceTimeline.WithData_iPhone_ax5.png | 0 ...senceTimeline.WithData_iPhone_contrast.png | 0 .../presenceTimeline.WithData_iPhone_dark.png | 0 .../primary.ElsewhereOnly_iPhone.png | 0 .../primary.ElsewhereOnly_iPhone_dark.png | 0 .../primary.Loaded_iPad.png | 0 .../primary.Loaded_iPad_accessibility.png | 0 .../primary.Loaded_iPad_ax5.png | 0 .../primary.Loaded_iPad_contrast.png | 0 .../primary.Loaded_iPad_dark.png | 0 .../primary.Loaded_iPhone.png | 0 .../primary.Loaded_iPhone_accessibility.png | 0 .../primary.Loaded_iPhone_ax5.png | 0 .../primary.Loaded_iPhone_contrast.png | 0 .../primary.Loaded_iPhone_dark.png | 0 .../primary.MissingDays_iPhone.png | 0 .../primary.MissingDays_iPhone_dark.png | 0 .../recentActivity.Empty_iPhone.png | 0 .../recentActivity.Empty_iPhone_dark.png | 0 .../recentActivity.Failed_iPhone.png | 0 .../recentActivity.Failed_iPhone_dark.png | 0 .../recentActivity.Loaded_iPad.png | 0 ...centActivity.Loaded_iPad_accessibility.png | 0 .../recentActivity.Loaded_iPad_ax5.png | 0 .../recentActivity.Loaded_iPad_contrast.png | 0 .../recentActivity.Loaded_iPad_dark.png | 0 .../recentActivity.Loaded_iPhone.png | 0 ...ntActivity.Loaded_iPhone_accessibility.png | 0 .../recentActivity.Loaded_iPhone_ax5.png | 0 .../recentActivity.Loaded_iPhone_contrast.png | 0 .../recentActivity.Loaded_iPhone_dark.png | 0 .../recentActivity.Unavailable_iPhone.png | 0 ...recentActivity.Unavailable_iPhone_dark.png | 0 .../regionDays.WithData_iPad.png | 0 ...regionDays.WithData_iPad_accessibility.png | 0 .../regionDays.WithData_iPad_ax5.png | 0 .../regionDays.WithData_iPad_contrast.png | 0 .../regionDays.WithData_iPad_dark.png | 0 .../regionDays.WithData_iPhone.png | 0 ...gionDays.WithData_iPhone_accessibility.png | 0 .../regionDays.WithData_iPhone_ax5.png | 0 .../regionDays.WithData_iPhone_contrast.png | 0 .../regionDays.WithData_iPhone_dark.png | 0 .../regionMap.Default_iPhone.png | 0 .../regionMap.Default_iPhone_dark.png | 0 .../resolution.Empty_iPhone.png | 0 .../resolution.Empty_iPhone_dark.png | 0 .../resolution.WithIssues_iPad.png | 0 ...solution.WithIssues_iPad_accessibility.png | 0 .../resolution.WithIssues_iPad_ax5.png | 0 .../resolution.WithIssues_iPad_contrast.png | 0 .../resolution.WithIssues_iPad_dark.png | 0 .../resolution.WithIssues_iPhone.png | 0 ...lution.WithIssues_iPhone_accessibility.png | 0 .../resolution.WithIssues_iPhone_ax5.png | 0 .../resolution.WithIssues_iPhone_contrast.png | 0 .../resolution.WithIssues_iPhone_dark.png | 0 .../root.LoggedIn_iPhone.png | 0 .../root.LoggedIn_iPhone_dark.png | 0 .../secondary.Loaded_iPad.png | 0 .../secondary.Loaded_iPad_accessibility.png | 0 .../secondary.Loaded_iPad_ax5.png | 0 .../secondary.Loaded_iPad_contrast.png | 0 .../secondary.Loaded_iPad_dark.png | 0 .../secondary.Loaded_iPhone.png | 0 .../secondary.Loaded_iPhone_accessibility.png | 0 .../secondary.Loaded_iPhone_ax5.png | 0 .../secondary.Loaded_iPhone_contrast.png | 0 .../secondary.Loaded_iPhone_dark.png | 0 .../settings.Default_iPad.png | 0 .../settings.Default_iPad_accessibility.png | 0 .../settings.Default_iPad_ax5.png | 0 .../settings.Default_iPad_contrast.png | 0 .../settings.Default_iPad_dark.png | 0 .../settings.Default_iPhone.png | 0 .../settings.Default_iPhone_accessibility.png | 0 .../settings.Default_iPhone_ax5.png | 0 .../settings.Default_iPhone_contrast.png | 0 .../settings.Default_iPhone_dark.png | 0 .../settings.Default_iPhone_rtl.png | 0 ...ataInspector.SwiftDataInspector_iPhone.png | 0 ...spector.SwiftDataInspector_iPhone_dark.png | 0 .../todayCircularAccessory.Empty.png | 0 .../todayCircularAccessory.Empty_dark.png | 0 .../todayCircularAccessory.Regions.png | 0 .../todayCircularAccessory.Regions_dark.png | 0 .../todayInlineAccessory.Empty.png | 0 .../todayInlineAccessory.Empty_dark.png | 0 .../todayInlineAccessory.Regions.png | 0 .../todayInlineAccessory.Regions_dark.png | 0 .../todayWidget.Empty.png | 0 .../todayWidget.Empty_dark.png | 0 .../todayWidget.MultiRegion.png | 0 .../todayWidget.MultiRegion_dark.png | 0 .../todayWidget.SingleRegion.png | 0 ...todayWidget.SingleRegion_accessibility.png | 0 .../todayWidget.SingleRegion_ax5.png | 0 .../todayWidget.SingleRegion_contrast.png | 0 .../todayWidget.SingleRegion_dark.png | 0 .../yearTotalsRectangularAccessory.Empty.png | 0 ...rTotalsRectangularAccessory.Empty_dark.png | 0 .../yearTotalsRectangularAccessory.Ranked.png | 0 ...TotalsRectangularAccessory.Ranked_dark.png | 0 .../yearTotalsWidget.Empty.png | 0 .../yearTotalsWidget.Empty_dark.png | 0 .../yearTotalsWidget.Ranked.png | 0 .../yearTotalsWidget.Ranked_accessibility.png | 0 .../yearTotalsWidget.Ranked_ax5.png | 0 .../yearTotalsWidget.Ranked_contrast.png | 0 .../yearTotalsWidget.Ranked_dark.png | 0 237 files changed, 323 insertions(+), 114 deletions(-) create mode 100644 Where/WhereUI/SnapshotTests/AppIconViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/CalendarViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/DayRelabelViewSnapshotTests.swift rename Where/WhereUI/SnapshotTests/{ScreenSnapshotTests.swift => DebugLogViewerSnapshotTests.swift} (61%) create mode 100644 Where/WhereUI/SnapshotTests/DeveloperOverlaySnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/DeveloperToolsViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/FlightDayDetailViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/LaunchSplashViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/LoggedDaysViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/ManualDayViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/OnboardingViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/PresenceTimelineViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/PrimaryViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/RecentActivitySummaryViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/RegionDaysViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/RegionMapViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/ResolutionViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/RootViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/SecondaryViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/SettingsViewSnapshotTests.swift rename Where/WhereUI/SnapshotTests/{AppFlowSnapshotTests.swift => SwiftDataInspectorSnapshotTests.swift} (70%) create mode 100644 Where/WhereUI/SnapshotTests/TodayCircularAccessoryViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/TodayInlineAccessoryViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/TodayWidgetViewSnapshotTests.swift delete mode 100644 Where/WhereUI/SnapshotTests/WidgetSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/YearTotalsRectangularAccessoryViewSnapshotTests.swift create mode 100644 Where/WhereUI/SnapshotTests/YearTotalsWidgetViewSnapshotTests.swift rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => AppIconViewSnapshotTests}/appIcon.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.FullYear_fullHeight.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => CalendarViewSnapshotTests}/calendar.WithData_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.WithAudit_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DayRelabelViewSnapshotTests}/dayRelabel.WithAudit_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DebugLogViewerSnapshotTests}/debugLogViewer.DebugLogViewer_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DebugLogViewerSnapshotTests}/debugLogViewer.DebugLogViewer_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DeveloperOverlaySnapshotTests}/developerOverlay.Collapsed_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DeveloperOverlaySnapshotTests}/developerOverlay.Collapsed_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DeveloperToolsViewSnapshotTests}/developerTools.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => DeveloperToolsViewSnapshotTests}/developerTools.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => FlightDayDetailViewSnapshotTests}/flightDayDetail.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => LaunchSplashViewSnapshotTests}/launchSplash.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => LaunchSplashViewSnapshotTests}/launchSplash.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => LaunchSplashViewSnapshotTests}/launchSplash.SlowLaunchCaption_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => LaunchSplashViewSnapshotTests}/launchSplash.SlowLaunchCaption_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Empty_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Empty_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Failed_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Failed_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => LoggedDaysViewSnapshotTests}/loggedDays.Loaded_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.AddWithCancel_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.AddWithCancel_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.Add_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.EditAuthoritative_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.EditAuthoritative_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.EditPlain_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ManualDayViewSnapshotTests}/manualDay.EditPlain_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => OnboardingViewSnapshotTests}/onboarding.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PresenceTimelineViewSnapshotTests}/presenceTimeline.WithData_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.ElsewhereOnly_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.ElsewhereOnly_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.Loaded_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.MissingDays_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => PrimaryViewSnapshotTests}/primary.MissingDays_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Empty_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Empty_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Failed_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Failed_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Loaded_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Unavailable_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RecentActivitySummaryViewSnapshotTests}/recentActivity.Unavailable_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionDaysViewSnapshotTests}/regionDays.WithData_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionMapViewSnapshotTests}/regionMap.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => RegionMapViewSnapshotTests}/regionMap.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.Empty_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.Empty_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => ResolutionViewSnapshotTests}/resolution.WithIssues_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => RootViewSnapshotTests}/root.LoggedIn_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => RootViewSnapshotTests}/root.LoggedIn_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SecondaryViewSnapshotTests}/secondary.Loaded_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPad.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPad_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPad_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPad_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPad_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPhone_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPhone_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPhone_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{ScreenSnapshotTests => SettingsViewSnapshotTests}/settings.Default_iPhone_rtl.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => SwiftDataInspectorSnapshotTests}/swiftDataInspector.SwiftDataInspector_iPhone.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{AppFlowSnapshotTests => SwiftDataInspectorSnapshotTests}/swiftDataInspector.SwiftDataInspector_iPhone_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayCircularAccessoryViewSnapshotTests}/todayCircularAccessory.Empty.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayCircularAccessoryViewSnapshotTests}/todayCircularAccessory.Empty_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayCircularAccessoryViewSnapshotTests}/todayCircularAccessory.Regions.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayCircularAccessoryViewSnapshotTests}/todayCircularAccessory.Regions_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayInlineAccessoryViewSnapshotTests}/todayInlineAccessory.Empty.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayInlineAccessoryViewSnapshotTests}/todayInlineAccessory.Empty_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayInlineAccessoryViewSnapshotTests}/todayInlineAccessory.Regions.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayInlineAccessoryViewSnapshotTests}/todayInlineAccessory.Regions_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.Empty.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.Empty_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.MultiRegion.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.MultiRegion_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.SingleRegion.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.SingleRegion_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.SingleRegion_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.SingleRegion_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => TodayWidgetViewSnapshotTests}/todayWidget.SingleRegion_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsRectangularAccessoryViewSnapshotTests}/yearTotalsRectangularAccessory.Empty.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsRectangularAccessoryViewSnapshotTests}/yearTotalsRectangularAccessory.Empty_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsRectangularAccessoryViewSnapshotTests}/yearTotalsRectangularAccessory.Ranked.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsRectangularAccessoryViewSnapshotTests}/yearTotalsRectangularAccessory.Ranked_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Empty.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Empty_dark.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Ranked.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Ranked_accessibility.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Ranked_ax5.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Ranked_contrast.png (100%) rename Where/WhereUI/SnapshotTests/__Snapshots__/{WidgetSnapshotTests => YearTotalsWidgetViewSnapshotTests}/yearTotalsWidget.Ranked_dark.png (100%) diff --git a/Where/WhereUI/SnapshotTests/AppIconViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/AppIconViewSnapshotTests.swift new file mode 100644 index 00000000..74ae8901 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/AppIconViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `AppIconView`; the matrix is declared via +/// `SnapshotProviding` in `AppIconView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct AppIconViewSnapshotTests { + @Test func appIcon() async { + await assertSnapshots(of: AppIconView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/CalendarViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/CalendarViewSnapshotTests.swift new file mode 100644 index 00000000..b5eb9272 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/CalendarViewSnapshotTests.swift @@ -0,0 +1,14 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `CalendarView`; the matrix (including the full-year +/// full-content capture) is declared via `SnapshotProviding` in +/// `CalendarView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct CalendarViewSnapshotTests { + @Test func calendar() async { + await assertSnapshots(of: CalendarView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/DayRelabelViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/DayRelabelViewSnapshotTests.swift new file mode 100644 index 00000000..df820395 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/DayRelabelViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `DayRelabelView`; the matrix is declared via +/// `SnapshotProviding` in `DayRelabelView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct DayRelabelViewSnapshotTests { + @Test func dayRelabel() async { + await assertSnapshots(of: DayRelabelView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/ScreenSnapshotTests.swift b/Where/WhereUI/SnapshotTests/DebugLogViewerSnapshotTests.swift similarity index 61% rename from Where/WhereUI/SnapshotTests/ScreenSnapshotTests.swift rename to Where/WhereUI/SnapshotTests/DebugLogViewerSnapshotTests.swift index ef83d75a..fecbbf41 100644 --- a/Where/WhereUI/SnapshotTests/ScreenSnapshotTests.swift +++ b/Where/WhereUI/SnapshotTests/DebugLogViewerSnapshotTests.swift @@ -6,77 +6,12 @@ import Testing import WhereCore @testable import WhereUI -/// Image snapshots for the top-level WhereUI screens. Each screen declares its -/// matrix via `SnapshotProviding` (see `ScreenSnapshots.swift` in WhereUI), so a -/// test is a single `assertSnapshots(of:)` call; views without a conformance -/// (third-party `LogViewer`) use the inline overload. +/// Image snapshot for the DEBUG developer `LogViewer` (a third-party +/// `LogViewerUI` surface, so it has no WhereUI `SnapshotProviding` conformance — +/// the inline `assertSnapshots(of:named:)` overload is used instead). @MainActor @Suite(.snapshots(record: .missing)) -struct ScreenSnapshotTests { - @Test func primary() async { - await assertSnapshots(of: PrimaryView.self) - } - - @Test func secondary() async { - await assertSnapshots(of: SecondaryView.self) - } - - @Test func settings() async { - await assertSnapshots(of: SettingsView.self) - } - - @Test func resolution() async { - await assertSnapshots(of: ResolutionView.self) - } - - @Test func flightDayDetail() async { - await assertSnapshots(of: FlightDayDetailView.self) - } - - @Test func regionDays() async { - await assertSnapshots(of: RegionDaysView.self) - } - - @Test func regionMap() async { - await assertSnapshots(of: RegionMapView.self) - } - - @Test func dayRelabel() async { - await assertSnapshots(of: DayRelabelView.self) - } - - @Test func recentActivity() async { - await assertSnapshots(of: RecentActivitySummaryView.self) - } - - @Test func presenceTimeline() async { - await assertSnapshots(of: PresenceTimelineView.self) - } - - @Test func calendar() async { - await assertSnapshots(of: CalendarView.self) - } - - @Test func appIcon() async { - await assertSnapshots(of: AppIconView.self) - } - - @Test func loggedDays() async { - await assertSnapshots(of: LoggedDaysView.self) - } - - @Test func manualDay() async { - await assertSnapshots(of: ManualDayView.self) - } - - @Test func developerTools() async { - await assertSnapshots(of: DeveloperToolsView.self) - } - - @Test func developerOverlay() async { - await assertSnapshots(of: DeveloperOverlay.self) - } - +struct DebugLogViewerSnapshotTests { @Test func debugLogViewer() async { let viewer = NavigationStack { LogViewer(configuration: LogViewerConfiguration( diff --git a/Where/WhereUI/SnapshotTests/DeveloperOverlaySnapshotTests.swift b/Where/WhereUI/SnapshotTests/DeveloperOverlaySnapshotTests.swift new file mode 100644 index 00000000..de6891b1 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/DeveloperOverlaySnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `DeveloperOverlay`; the matrix is declared via +/// `SnapshotProviding` in `DeveloperOverlay.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct DeveloperOverlaySnapshotTests { + @Test func developerOverlay() async { + await assertSnapshots(of: DeveloperOverlay.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/DeveloperToolsViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/DeveloperToolsViewSnapshotTests.swift new file mode 100644 index 00000000..29323941 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/DeveloperToolsViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `DeveloperToolsView`; the matrix is declared via +/// `SnapshotProviding` in `DeveloperToolsView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct DeveloperToolsViewSnapshotTests { + @Test func developerTools() async { + await assertSnapshots(of: DeveloperToolsView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/FlightDayDetailViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/FlightDayDetailViewSnapshotTests.swift new file mode 100644 index 00000000..9e523519 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/FlightDayDetailViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `FlightDayDetailView`; the matrix is declared via +/// `SnapshotProviding` in `FlightDayDetailView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct FlightDayDetailViewSnapshotTests { + @Test func flightDayDetail() async { + await assertSnapshots(of: FlightDayDetailView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/LaunchSplashViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/LaunchSplashViewSnapshotTests.swift new file mode 100644 index 00000000..dd594de1 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/LaunchSplashViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `LaunchSplashView`; the matrix is declared via +/// `SnapshotProviding` in `LaunchSplashView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct LaunchSplashViewSnapshotTests { + @Test func launchSplash() async { + await assertSnapshots(of: LaunchSplashView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/LoggedDaysViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/LoggedDaysViewSnapshotTests.swift new file mode 100644 index 00000000..0212f953 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/LoggedDaysViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `LoggedDaysView`; the matrix is declared via +/// `SnapshotProviding` in `LoggedDaysView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct LoggedDaysViewSnapshotTests { + @Test func loggedDays() async { + await assertSnapshots(of: LoggedDaysView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/ManualDayViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/ManualDayViewSnapshotTests.swift new file mode 100644 index 00000000..13961e1b --- /dev/null +++ b/Where/WhereUI/SnapshotTests/ManualDayViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `ManualDayView`; the matrix is declared via +/// `SnapshotProviding` in `ManualDayView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct ManualDayViewSnapshotTests { + @Test func manualDay() async { + await assertSnapshots(of: ManualDayView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/OnboardingViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/OnboardingViewSnapshotTests.swift new file mode 100644 index 00000000..214d2453 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/OnboardingViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `OnboardingView`; the matrix is declared via +/// `SnapshotProviding` in `OnboardingView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct OnboardingViewSnapshotTests { + @Test func onboarding() async { + await assertSnapshots(of: OnboardingView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/PresenceTimelineViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/PresenceTimelineViewSnapshotTests.swift new file mode 100644 index 00000000..b7878110 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/PresenceTimelineViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `PresenceTimelineView`; the matrix is declared via +/// `SnapshotProviding` in `PresenceTimelineView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct PresenceTimelineViewSnapshotTests { + @Test func presenceTimeline() async { + await assertSnapshots(of: PresenceTimelineView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/PrimaryViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/PrimaryViewSnapshotTests.swift new file mode 100644 index 00000000..f4c68cbc --- /dev/null +++ b/Where/WhereUI/SnapshotTests/PrimaryViewSnapshotTests.swift @@ -0,0 +1,14 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `PrimaryView`. The matrix is declared once via +/// `SnapshotProviding` in `PrimaryView.swift` (which also drives its `#Preview` +/// cutsheet), so the test is a single `assertSnapshots(of:)` call. +@MainActor +@Suite(.snapshots(record: .missing)) +struct PrimaryViewSnapshotTests { + @Test func primary() async { + await assertSnapshots(of: PrimaryView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/RecentActivitySummaryViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/RecentActivitySummaryViewSnapshotTests.swift new file mode 100644 index 00000000..0843aad5 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/RecentActivitySummaryViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `RecentActivitySummaryView`; the matrix is declared via +/// `SnapshotProviding` in `RecentActivitySummaryView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct RecentActivitySummaryViewSnapshotTests { + @Test func recentActivity() async { + await assertSnapshots(of: RecentActivitySummaryView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/RegionDaysViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/RegionDaysViewSnapshotTests.swift new file mode 100644 index 00000000..1767d536 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/RegionDaysViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `RegionDaysView`; the matrix is declared via +/// `SnapshotProviding` in `RegionDaysView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct RegionDaysViewSnapshotTests { + @Test func regionDays() async { + await assertSnapshots(of: RegionDaysView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/RegionMapViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/RegionMapViewSnapshotTests.swift new file mode 100644 index 00000000..79dab870 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/RegionMapViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `RegionMapView` (the deterministic capture stand-in); +/// the matrix is declared via `SnapshotProviding` in `RegionMapView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct RegionMapViewSnapshotTests { + @Test func regionMap() async { + await assertSnapshots(of: RegionMapView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/ResolutionViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/ResolutionViewSnapshotTests.swift new file mode 100644 index 00000000..7f951be7 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/ResolutionViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `ResolutionView`; the matrix is declared via +/// `SnapshotProviding` in `ResolutionView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct ResolutionViewSnapshotTests { + @Test func resolution() async { + await assertSnapshots(of: ResolutionView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/RootViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/RootViewSnapshotTests.swift new file mode 100644 index 00000000..212f64c4 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/RootViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for the logged-in `RootView`; the matrix is declared via +/// `SnapshotProviding` in `RootView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct RootViewSnapshotTests { + @Test func root() async { + await assertSnapshots(of: RootView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/SecondaryViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/SecondaryViewSnapshotTests.swift new file mode 100644 index 00000000..2d349af2 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/SecondaryViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `SecondaryView`; the matrix is declared via +/// `SnapshotProviding` in `SecondaryView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct SecondaryViewSnapshotTests { + @Test func secondary() async { + await assertSnapshots(of: SecondaryView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/SettingsViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/SettingsViewSnapshotTests.swift new file mode 100644 index 00000000..5de415ba --- /dev/null +++ b/Where/WhereUI/SnapshotTests/SettingsViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `SettingsView`; the matrix is declared via +/// `SnapshotProviding` in `SettingsView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct SettingsViewSnapshotTests { + @Test func settings() async { + await assertSnapshots(of: SettingsView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/AppFlowSnapshotTests.swift b/Where/WhereUI/SnapshotTests/SwiftDataInspectorSnapshotTests.swift similarity index 70% rename from Where/WhereUI/SnapshotTests/AppFlowSnapshotTests.swift rename to Where/WhereUI/SnapshotTests/SwiftDataInspectorSnapshotTests.swift index 8d7dbb46..306422d7 100644 --- a/Where/WhereUI/SnapshotTests/AppFlowSnapshotTests.swift +++ b/Where/WhereUI/SnapshotTests/SwiftDataInspectorSnapshotTests.swift @@ -6,24 +6,13 @@ import Testing import WhereCore @testable import WhereUI -/// Image snapshots for the app-flow surfaces: launch splash, onboarding, the -/// root scene, and the DEBUG SwiftData inspector (recorded against a live, -/// seeded in-memory store). +/// Image snapshot for the DEBUG generic `SwiftDataInspector` surface (a +/// third-party `SwiftDataInspector` view, so no WhereUI `SnapshotProviding` +/// conformance — the inline overload is used), recorded against a live, seeded +/// in-memory store. @MainActor @Suite(.snapshots(record: .missing)) -struct AppFlowSnapshotTests { - @Test func launchSplash() async { - await assertSnapshots(of: LaunchSplashView.self) - } - - @Test func onboarding() async { - await assertSnapshots(of: OnboardingView.self) - } - - @Test func root() async { - await assertSnapshots(of: RootView.self) - } - +struct SwiftDataInspectorSnapshotTests { @Test func swiftDataInspector() async throws { let services = PreviewSupport.previewServices() // Seed one real row so the inspector renders live content, not an empty diff --git a/Where/WhereUI/SnapshotTests/TodayCircularAccessoryViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/TodayCircularAccessoryViewSnapshotTests.swift new file mode 100644 index 00000000..4001a17e --- /dev/null +++ b/Where/WhereUI/SnapshotTests/TodayCircularAccessoryViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `TodayCircularAccessoryView`; the matrix is declared via +/// `SnapshotProviding` in `TodayAccessoryViews.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct TodayCircularAccessoryViewSnapshotTests { + @Test func todayCircularAccessory() async { + await assertSnapshots(of: TodayCircularAccessoryView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/TodayInlineAccessoryViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/TodayInlineAccessoryViewSnapshotTests.swift new file mode 100644 index 00000000..a425d767 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/TodayInlineAccessoryViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `TodayInlineAccessoryView`; the matrix is declared via +/// `SnapshotProviding` in `TodayAccessoryViews.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct TodayInlineAccessoryViewSnapshotTests { + @Test func todayInlineAccessory() async { + await assertSnapshots(of: TodayInlineAccessoryView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/TodayWidgetViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/TodayWidgetViewSnapshotTests.swift new file mode 100644 index 00000000..b5ce45d7 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/TodayWidgetViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `TodayWidgetView`; the matrix is declared via +/// `SnapshotProviding` in `TodayWidgetView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct TodayWidgetViewSnapshotTests { + @Test func todayWidget() async { + await assertSnapshots(of: TodayWidgetView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/WidgetSnapshotTests.swift b/Where/WhereUI/SnapshotTests/WidgetSnapshotTests.swift deleted file mode 100644 index 7821b46e..00000000 --- a/Where/WhereUI/SnapshotTests/WidgetSnapshotTests.swift +++ /dev/null @@ -1,29 +0,0 @@ -import SnapshotKitTesting -import Testing -@testable import WhereUI - -/// Image snapshots for the widget entry views and lock-screen accessories, each -/// declared via `SnapshotProviding` (see `WidgetSnapshots.swift` in WhereUI). -@MainActor -@Suite(.snapshots(record: .missing)) -struct WidgetSnapshotTests { - @Test func todayWidget() async { - await assertSnapshots(of: TodayWidgetView.self) - } - - @Test func yearTotalsWidget() async { - await assertSnapshots(of: YearTotalsWidgetView.self) - } - - @Test func todayInlineAccessory() async { - await assertSnapshots(of: TodayInlineAccessoryView.self) - } - - @Test func todayCircularAccessory() async { - await assertSnapshots(of: TodayCircularAccessoryView.self) - } - - @Test func yearTotalsRectangularAccessory() async { - await assertSnapshots(of: YearTotalsRectangularAccessoryView.self) - } -} diff --git a/Where/WhereUI/SnapshotTests/YearTotalsRectangularAccessoryViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/YearTotalsRectangularAccessoryViewSnapshotTests.swift new file mode 100644 index 00000000..ca55d3e4 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/YearTotalsRectangularAccessoryViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `YearTotalsRectangularAccessoryView`; the matrix is +/// declared via `SnapshotProviding` in `YearTotalsRectangularAccessoryView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct YearTotalsRectangularAccessoryViewSnapshotTests { + @Test func yearTotalsRectangularAccessory() async { + await assertSnapshots(of: YearTotalsRectangularAccessoryView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/YearTotalsWidgetViewSnapshotTests.swift b/Where/WhereUI/SnapshotTests/YearTotalsWidgetViewSnapshotTests.swift new file mode 100644 index 00000000..a3af1ab6 --- /dev/null +++ b/Where/WhereUI/SnapshotTests/YearTotalsWidgetViewSnapshotTests.swift @@ -0,0 +1,13 @@ +import SnapshotKitTesting +import Testing +@testable import WhereUI + +/// Image snapshots for `YearTotalsWidgetView`; the matrix is declared via +/// `SnapshotProviding` in `YearTotalsWidgetView.swift`. +@MainActor +@Suite(.snapshots(record: .missing)) +struct YearTotalsWidgetViewSnapshotTests { + @Test func yearTotalsWidget() async { + await assertSnapshots(of: YearTotalsWidgetView.self) + } +} diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/appIcon.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/AppIconViewSnapshotTests/appIcon.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.FullYear_fullHeight.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.FullYear_fullHeight.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.FullYear_fullHeight.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.FullYear_fullHeight.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/calendar.WithData_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/CalendarViewSnapshotTests/calendar.WithData_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.WithAudit_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.WithAudit_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.WithAudit_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.WithAudit_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.WithAudit_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.WithAudit_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/dayRelabel.WithAudit_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DayRelabelViewSnapshotTests/dayRelabel.WithAudit_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/debugLogViewer.DebugLogViewer_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DebugLogViewerSnapshotTests/debugLogViewer.DebugLogViewer_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/debugLogViewer.DebugLogViewer_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DebugLogViewerSnapshotTests/debugLogViewer.DebugLogViewer_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/debugLogViewer.DebugLogViewer_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DebugLogViewerSnapshotTests/debugLogViewer.DebugLogViewer_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/debugLogViewer.DebugLogViewer_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DebugLogViewerSnapshotTests/debugLogViewer.DebugLogViewer_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerOverlay.Collapsed_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperOverlaySnapshotTests/developerOverlay.Collapsed_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerOverlay.Collapsed_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperOverlaySnapshotTests/developerOverlay.Collapsed_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerOverlay.Collapsed_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperOverlaySnapshotTests/developerOverlay.Collapsed_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerOverlay.Collapsed_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperOverlaySnapshotTests/developerOverlay.Collapsed_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerTools.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperToolsViewSnapshotTests/developerTools.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerTools.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperToolsViewSnapshotTests/developerTools.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerTools.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperToolsViewSnapshotTests/developerTools.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/developerTools.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperToolsViewSnapshotTests/developerTools.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/flightDayDetail.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/FlightDayDetailViewSnapshotTests/flightDayDetail.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.SlowLaunchCaption_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.SlowLaunchCaption_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.SlowLaunchCaption_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.SlowLaunchCaption_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.SlowLaunchCaption_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.SlowLaunchCaption_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/launchSplash.SlowLaunchCaption_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LaunchSplashViewSnapshotTests/launchSplash.SlowLaunchCaption_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Empty_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Empty_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Empty_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Empty_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Empty_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Empty_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Empty_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Empty_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Failed_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Failed_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Failed_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Failed_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Failed_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Failed_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Failed_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Failed_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/loggedDays.Loaded_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/LoggedDaysViewSnapshotTests/loggedDays.Loaded_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.AddWithCancel_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.AddWithCancel_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.AddWithCancel_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.AddWithCancel_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.AddWithCancel_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.AddWithCancel_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.AddWithCancel_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.AddWithCancel_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.Add_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.Add_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditAuthoritative_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditAuthoritative_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditAuthoritative_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditAuthoritative_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditAuthoritative_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditAuthoritative_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditAuthoritative_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditAuthoritative_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditPlain_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditPlain_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditPlain_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditPlain_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditPlain_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditPlain_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/manualDay.EditPlain_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ManualDayViewSnapshotTests/manualDay.EditPlain_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/onboarding.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/OnboardingViewSnapshotTests/onboarding.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/presenceTimeline.WithData_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PresenceTimelineViewSnapshotTests/presenceTimeline.WithData_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.ElsewhereOnly_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.ElsewhereOnly_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.ElsewhereOnly_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.ElsewhereOnly_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.ElsewhereOnly_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.ElsewhereOnly_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.ElsewhereOnly_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.ElsewhereOnly_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.Loaded_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.Loaded_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.MissingDays_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.MissingDays_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.MissingDays_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.MissingDays_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.MissingDays_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.MissingDays_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/primary.MissingDays_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/PrimaryViewSnapshotTests/primary.MissingDays_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Empty_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Empty_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Empty_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Empty_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Empty_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Empty_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Empty_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Empty_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Failed_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Failed_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Failed_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Failed_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Failed_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Failed_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Failed_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Failed_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Loaded_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Loaded_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Unavailable_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Unavailable_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Unavailable_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Unavailable_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Unavailable_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Unavailable_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/recentActivity.Unavailable_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RecentActivitySummaryViewSnapshotTests/recentActivity.Unavailable_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionDays.WithData_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionDaysViewSnapshotTests/regionDays.WithData_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionMap.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionMapViewSnapshotTests/regionMap.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionMap.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionMapViewSnapshotTests/regionMap.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionMap.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RegionMapViewSnapshotTests/regionMap.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/regionMap.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RegionMapViewSnapshotTests/regionMap.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.Empty_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.Empty_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.Empty_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.Empty_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.Empty_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.Empty_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.Empty_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.Empty_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/resolution.WithIssues_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/ResolutionViewSnapshotTests/resolution.WithIssues_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/root.LoggedIn_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RootViewSnapshotTests/root.LoggedIn_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/root.LoggedIn_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RootViewSnapshotTests/root.LoggedIn_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/root.LoggedIn_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/RootViewSnapshotTests/root.LoggedIn_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/root.LoggedIn_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/RootViewSnapshotTests/root.LoggedIn_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/secondary.Loaded_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SecondaryViewSnapshotTests/secondary.Loaded_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPad_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPad_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_rtl.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_rtl.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/ScreenSnapshotTests/settings.Default_iPhone_rtl.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SettingsViewSnapshotTests/settings.Default_iPhone_rtl.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SwiftDataInspectorSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SwiftDataInspectorSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/SwiftDataInspectorSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/AppFlowSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/SwiftDataInspectorSnapshotTests/swiftDataInspector.SwiftDataInspector_iPhone_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Empty.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Empty.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Empty.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Empty.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Empty_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Empty_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Empty_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Empty_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Regions.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Regions.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Regions.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Regions.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Regions_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Regions_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayCircularAccessory.Regions_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayCircularAccessoryViewSnapshotTests/todayCircularAccessory.Regions_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Empty.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Empty.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Empty.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Empty.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Empty_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Empty_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Empty_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Empty_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Regions.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Regions.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Regions.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Regions.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Regions_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Regions_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayInlineAccessory.Regions_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayInlineAccessoryViewSnapshotTests/todayInlineAccessory.Regions_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.Empty.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.Empty.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.Empty.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.Empty.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.Empty_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.Empty_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.Empty_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.Empty_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.MultiRegion.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.MultiRegion.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.MultiRegion.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.MultiRegion.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.MultiRegion_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.MultiRegion_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.MultiRegion_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.MultiRegion_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/todayWidget.SingleRegion_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/TodayWidgetViewSnapshotTests/todayWidget.SingleRegion_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Empty.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Empty.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Empty.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Empty.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Empty_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Empty_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Empty_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Empty_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Ranked.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Ranked.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Ranked.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Ranked.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Ranked_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Ranked_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsRectangularAccessory.Ranked_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsRectangularAccessoryViewSnapshotTests/yearTotalsRectangularAccessory.Ranked_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Empty.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Empty.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Empty.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Empty.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Empty_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Empty_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Empty_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Empty_dark.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_accessibility.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_accessibility.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_accessibility.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_accessibility.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_ax5.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_ax5.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_ax5.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_ax5.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_contrast.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_contrast.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_contrast.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_contrast.png diff --git a/Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_dark.png b/Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_dark.png similarity index 100% rename from Where/WhereUI/SnapshotTests/__Snapshots__/WidgetSnapshotTests/yearTotalsWidget.Ranked_dark.png rename to Where/WhereUI/SnapshotTests/__Snapshots__/YearTotalsWidgetViewSnapshotTests/yearTotalsWidget.Ranked_dark.png From 1454a7deb496bf87cb3ea52f36bee81bc618d0a9 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:42:34 -0700 Subject: [PATCH 4/8] Hide the snapshot date-picker stand-in behind a WhereDatePicker wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SettingsView and ManualDayView each read \.isCapturingSnapshot and branched between a live DatePicker and SnapshotDatePickerStandIn inline — leaking snapshot-environment checks into product UI. Introduce WhereDatePicker, a compact date/time picker that makes that choice internally (mapping onto DatePicker's in: range overloads for the live path), with SnapshotDatePickerStandIn demoted to a fileprivate detail of its file. Both product views now use WhereDatePicker and no longer import the capture flag. Renders identically — ManualDayView and SettingsView snapshot suites pass with no reference changes. Closes review comments on product code branching on the snapshot flag / applying the wrapper-type pattern. Plan to-do: wheredatepicker. --- .../Sources/Manual/ManualDayView.swift | 64 +++---- .../Sources/Settings/SettingsView.swift | 38 ++--- .../Shared/SnapshotDatePickerStandIn.swift | 78 --------- .../Sources/Shared/WhereDatePicker.swift | 158 ++++++++++++++++++ 4 files changed, 191 insertions(+), 147 deletions(-) delete mode 100644 Where/WhereUI/Sources/Shared/SnapshotDatePickerStandIn.swift create mode 100644 Where/WhereUI/Sources/Shared/WhereDatePicker.swift diff --git a/Where/WhereUI/Sources/Manual/ManualDayView.swift b/Where/WhereUI/Sources/Manual/ManualDayView.swift index 16ef22ba..311236be 100644 --- a/Where/WhereUI/Sources/Manual/ManualDayView.swift +++ b/Where/WhereUI/Sources/Manual/ManualDayView.swift @@ -33,7 +33,6 @@ struct ManualDayView: View { let showsCancelButton: Bool @Environment(\.dismiss) private var dismiss - @Environment(\.isCapturingSnapshot) private var isCapturingSnapshot /// Mode-specific editable state, each case carrying *exactly* the fields that /// mode needs — so add-only inputs (dates, span) can't be read in edit and @@ -174,52 +173,35 @@ struct ManualDayView: View { } } - /// Snapshot captures substitute each compact picker's value capsule with a - /// deterministic stand-in of the same row layout: the live capsule's date - /// format depends on the real-world date, so no reference image containing - /// it is stable across days (see `SnapshotDatePickerStandIn`). + /// `WhereDatePicker` renders a deterministic stand-in under snapshot capture + /// (the live compact capsule's date format depends on the real-world date, + /// so no reference image containing it is stable across days) — the capture + /// handling stays inside the wrapper, not here. @ViewBuilder private func datePickers(_ add: AddFields) -> some View { @Bindable var add = add switch add.dateSpan { case .singleDay: - if isCapturingSnapshot { - SnapshotDatePickerStandIn( - title: Strings.manualDay, - selection: .date(add.startDate), - ) - } else { - DatePicker( - Strings.manualDay, - selection: $add.startDate, - in: ...Date(), - displayedComponents: .date, - ) - } + WhereDatePicker( + Strings.manualDay, + selection: $add.startDate, + latest: Date(), + displayedComponents: .date, + ) case .range: - if isCapturingSnapshot { - SnapshotDatePickerStandIn( - title: Strings.manualFrom, - selection: .date(add.startDate), - ) - SnapshotDatePickerStandIn( - title: Strings.manualThrough, - selection: .date(add.endDate), - ) - } else { - DatePicker( - Strings.manualFrom, - selection: $add.startDate, - in: ...Date(), - displayedComponents: .date, - ) - DatePicker( - Strings.manualThrough, - selection: $add.endDate, - in: add.startDate ... Date(), - displayedComponents: .date, - ) - } + WhereDatePicker( + Strings.manualFrom, + selection: $add.startDate, + latest: Date(), + displayedComponents: .date, + ) + WhereDatePicker( + Strings.manualThrough, + selection: $add.endDate, + earliest: add.startDate, + latest: Date(), + displayedComponents: .date, + ) } } diff --git a/Where/WhereUI/Sources/Settings/SettingsView.swift b/Where/WhereUI/Sources/Settings/SettingsView.swift index 4e80126a..68f185e0 100644 --- a/Where/WhereUI/Sources/Settings/SettingsView.swift +++ b/Where/WhereUI/Sources/Settings/SettingsView.swift @@ -24,10 +24,6 @@ struct SettingsView: View { @Environment(WhereSession.self) private var session @Environment(\.openURL) private var openURL @Environment(\.lifecycleRunner) private var runner - /// Snapshot captures substitute the compact time pickers' value capsules - /// with a deterministic stand-in — the live capsule's rendering depends on - /// real-world clock state (see `SnapshotDatePickerStandIn`). - @Environment(\.isCapturingSnapshot) private var isCapturingSnapshot @State private var showClearConfirmation = false @State private var showResetConfirmation = false @@ -223,18 +219,11 @@ struct SettingsView: View { } if reminders.remindersEnabled { - if isCapturingSnapshot { - SnapshotDatePickerStandIn( - title: Strings.settingsReminderTime, - selection: .timeOfDay(reminders.reminderTimeOfDay), - ) - } else { - DatePicker( - Strings.settingsReminderTime, - selection: $reminders.reminderTimeOfDay, - displayedComponents: .hourAndMinute, - ) - } + WhereDatePicker( + Strings.settingsReminderTime, + selection: $reminders.reminderTimeOfDay, + displayedComponents: .hourAndMinute, + ) if !reminders.notificationsAuthorized { Button { @@ -266,18 +255,11 @@ struct SettingsView: View { } if reminders.summaryEnabled { - if isCapturingSnapshot { - SnapshotDatePickerStandIn( - title: Strings.settingsSummaryTime, - selection: .timeOfDay(reminders.summaryTimeOfDay), - ) - } else { - DatePicker( - Strings.settingsSummaryTime, - selection: $reminders.summaryTimeOfDay, - displayedComponents: .hourAndMinute, - ) - } + WhereDatePicker( + Strings.settingsSummaryTime, + selection: $reminders.summaryTimeOfDay, + displayedComponents: .hourAndMinute, + ) if !reminders.notificationsAuthorized { Button { diff --git a/Where/WhereUI/Sources/Shared/SnapshotDatePickerStandIn.swift b/Where/WhereUI/Sources/Shared/SnapshotDatePickerStandIn.swift deleted file mode 100644 index f5782fb0..00000000 --- a/Where/WhereUI/Sources/Shared/SnapshotDatePickerStandIn.swift +++ /dev/null @@ -1,78 +0,0 @@ -import SnapshotKit -import SwiftUI - -/// Deterministic stand-in for a compact `DatePicker` under snapshot capture. -/// -/// The live compact picker's value capsule renders relative to the real-world -/// date: it reserves its width from *today's* date in the medium format and -/// falls back to a short numeric format ("7/15/26") whenever the selection's -/// medium string doesn't fit that reservation — so the same pinned selection -/// renders differently depending on the day the test runs, and no settle -/// window can stabilize it. Captures substitute this row instead: the same -/// title + trailing-capsule layout, with the selection rendered in a fixed -/// format and locale so the image is a pure function of the selected value. -/// Only the system-drawn value capsule is substituted — the row title and -/// surrounding Form chrome stay real — per the `\.isCapturingSnapshot` -/// carve-out (see SnapshotKit's `SnapshotCaptureFlag`). -struct SnapshotDatePickerStandIn: View { - /// The capsule's content — a calendar date or a time of day — each with a - /// fixed format and locale so rendering can't depend on the wall clock. - enum Selection { - case date(Date) - case timeOfDay(Date) - } - - let title: String - let selection: Selection - - var body: some View { - LabeledContent(title) { - Text(formattedSelection) - .foregroundStyle(.primary) - // Mimics the compact picker's system capsule chrome — fixed - // system-control geometry, not themed stylesheet tokens. - .padding(.horizontal, 11) - .padding(.vertical, 6) - .background(Color(.tertiarySystemFill), in: .capsule) - } - } - - private var formattedSelection: String { - switch selection { - case let .date(date): - date.formatted(Self.dateStyle) - case let .timeOfDay(date): - date.formatted(Self.timeStyle) - } - } - - /// The medium date the live picker prefers ("Jul 15, 2026"), now with a - /// fixed locale and no dependence on today's capsule-width reservation. - private static let dateStyle = Date.FormatStyle( - date: .abbreviated, - time: .omitted, - locale: Locale(identifier: "en_US"), - ) - - /// Shortened time ("8:00 PM") in the same fixed locale. - private static let timeStyle = Date.FormatStyle( - date: .omitted, - time: .shortened, - locale: Locale(identifier: "en_US"), - ) -} - -#if DEBUG - #Preview { - Form { - SnapshotDatePickerStandIn( - title: "Day", - selection: .date(PreviewSupport.referenceNow), - ) - SnapshotDatePickerStandIn( - title: "Remind me at", - selection: .timeOfDay(PreviewSupport.referenceNow), - ) - } - } -#endif diff --git a/Where/WhereUI/Sources/Shared/WhereDatePicker.swift b/Where/WhereUI/Sources/Shared/WhereDatePicker.swift new file mode 100644 index 00000000..cd15db8d --- /dev/null +++ b/Where/WhereUI/Sources/Shared/WhereDatePicker.swift @@ -0,0 +1,158 @@ +import SnapshotKit +import SwiftUI + +/// A compact `DatePicker` for Where's forms that renders a deterministic +/// stand-in under snapshot capture instead of the live system picker. +/// +/// The live compact picker's value capsule renders relative to the real-world +/// date, so no reference image containing it is stable across days (see +/// ``SnapshotDatePickerStandIn``). Views use `WhereDatePicker` rather than +/// reading `\.isCapturingSnapshot` and branching themselves — the capture +/// handling, and the stand-in, stay a private detail here, so product code +/// carries no snapshot-environment checks. +struct WhereDatePicker: View { + let title: String + @Binding var selection: Date + /// Optional inclusive selectable bounds, mapped onto `DatePicker`'s `in:` + /// range overloads. `nil` means unbounded on that end. + var earliest: Date? + var latest: Date? + let displayedComponents: DatePickerComponents + + @Environment(\.isCapturingSnapshot) private var isCapturingSnapshot + + init( + _ title: String, + selection: Binding, + earliest: Date? = nil, + latest: Date? = nil, + displayedComponents: DatePickerComponents, + ) { + self.title = title + _selection = selection + self.earliest = earliest + self.latest = latest + self.displayedComponents = displayedComponents + } + + var body: some View { + if isCapturingSnapshot { + SnapshotDatePickerStandIn(title: title, selection: standInSelection) + } else { + livePicker + } + } + + @ViewBuilder + private var livePicker: some View { + if let earliest, let latest { + DatePicker( + title, + selection: $selection, + in: earliest ... latest, + displayedComponents: displayedComponents, + ) + } else if let latest { + DatePicker( + title, + selection: $selection, + in: ...latest, + displayedComponents: displayedComponents, + ) + } else if let earliest { + DatePicker( + title, + selection: $selection, + in: earliest..., + displayedComponents: displayedComponents, + ) + } else { + DatePicker(title, selection: $selection, displayedComponents: displayedComponents) + } + } + + /// A capsule showing the date for a `.date` picker, or the time of day for a + /// `.hourAndMinute` one. + private var standInSelection: SnapshotDatePickerStandIn.Selection { + displayedComponents.contains(.date) ? .date(selection) : .timeOfDay(selection) + } +} + +/// Deterministic stand-in for a compact `DatePicker` under snapshot capture — +/// a private detail of ``WhereDatePicker``. +/// +/// The live compact picker's value capsule renders relative to the real-world +/// date: it reserves its width from *today's* date in the medium format and +/// falls back to a short numeric format ("7/15/26") whenever the selection's +/// medium string doesn't fit that reservation — so the same pinned selection +/// renders differently depending on the day the test runs, and no settle +/// window can stabilize it. Captures substitute this row instead: the same +/// title + trailing-capsule layout, with the selection rendered in a fixed +/// format and locale so the image is a pure function of the selected value. +/// Only the system-drawn value capsule is substituted — the row title and +/// surrounding Form chrome stay real — per the `\.isCapturingSnapshot` +/// carve-out (see SnapshotKit's `SnapshotCaptureFlag`). +private struct SnapshotDatePickerStandIn: View { + /// The capsule's content — a calendar date or a time of day — each with a + /// fixed format and locale so rendering can't depend on the wall clock. + enum Selection { + case date(Date) + case timeOfDay(Date) + } + + let title: String + let selection: Selection + + var body: some View { + LabeledContent(title) { + Text(formattedSelection) + .foregroundStyle(.primary) + // Mimics the compact picker's system capsule chrome — fixed + // system-control geometry, not themed stylesheet tokens. + .padding(.horizontal, 11) + .padding(.vertical, 6) + .background(Color(.tertiarySystemFill), in: .capsule) + } + } + + private var formattedSelection: String { + switch selection { + case let .date(date): + date.formatted(Self.dateStyle) + case let .timeOfDay(date): + date.formatted(Self.timeStyle) + } + } + + /// The medium date the live picker prefers ("Jul 15, 2026"), now with a + /// fixed locale and no dependence on today's capsule-width reservation. + private static let dateStyle = Date.FormatStyle( + date: .abbreviated, + time: .omitted, + locale: Locale(identifier: "en_US"), + ) + + /// Shortened time ("8:00 PM") in the same fixed locale. + private static let timeStyle = Date.FormatStyle( + date: .omitted, + time: .shortened, + locale: Locale(identifier: "en_US"), + ) +} + +#if DEBUG + #Preview { + Form { + WhereDatePicker( + "Day", + selection: .constant(PreviewSupport.referenceNow), + displayedComponents: .date, + ) + WhereDatePicker( + "Remind me at", + selection: .constant(PreviewSupport.referenceNow), + displayedComponents: .hourAndMinute, + ) + } + } +#endif From efc72a60a405dd2dd0831bac50bc91098a1d09af Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:46:04 -0700 Subject: [PATCH 5/8] Isolate RegionMapView's capture branch; clarify LaunchSplash's motion flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RegionMapView read \.isCapturingSnapshot and branched between the live MapKit Map and the stand-in inside its own body helper. Move that choice into a private RegionOutlinesMap subview so the screen no longer reads the capture flag at all — it just renders the substrate, unaware which one drew. The stand-in's rendering is unchanged (regionMap references untouched); the live-Map path gains a dedicated hosting test under the fold-in step. LaunchSplashView: document why it holds both motionIsStatic (Reduce Motion or capture — freezes the never-settling pulse) and isCapturingSnapshot (gates the wall-clock caption timer, which Reduce Motion users must still get), answering the review question, and extract RadarPingBackground's phase-clock computation into a fileprivate TimelineViewDefaultContext.radarPhaseClock(capturingSnapshot:) extension. RegionMap + LaunchSplash snapshot suites pass unchanged. Plan to-do: map-splash. --- .../Sources/Developer/RegionMapView.swift | 67 ++++++++++++------- .../Sources/Launch/LaunchSplashView.swift | 23 ++++++- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/Where/WhereUI/Sources/Developer/RegionMapView.swift b/Where/WhereUI/Sources/Developer/RegionMapView.swift index 913e1236..1c567651 100644 --- a/Where/WhereUI/Sources/Developer/RegionMapView.swift +++ b/Where/WhereUI/Sources/Developer/RegionMapView.swift @@ -26,7 +26,6 @@ public struct RegionMapView: View { @State private var cameraPosition: MapCameraPosition = .automatic @Environment(\.stylesheet) private var stylesheet - @Environment(\.isCapturingSnapshot) private var isCapturingSnapshot @Environment(\.regionStyles) private var regionStyles /// Public so the standalone `RegionViewer` app (a separate module) can @@ -79,32 +78,12 @@ public struct RegionMapView: View { } } - /// Snapshot captures substitute the live `Map` with a deterministic - /// stand-in of identical layout: MapKit's tile/label loading is - /// asynchronous and cache/network-dependent, so no settle window can make - /// the real substrate pixel-stable. The view's own overlays (the region - /// polygons) still render for real — only the tile substrate is replaced — - /// per the `\.isCapturingSnapshot` carve-out for externally-loaded, - /// non-deterministic content (see SnapshotKit's `SnapshotCaptureFlag`). private func map(for outlines: [RegionOutline]) -> some View { - Group { - if isCapturingSnapshot { - SnapshotMapStandIn( - outlines: outlines, - region: Self.enclosingRegion(of: outlines), - color: color(for:), - ) - } else { - Map(position: $cameraPosition) { - ForEach(outlines) { outline in - MapPolygon(coordinates: outline.coordinates.clLocationCoordinates) - .foregroundStyle(color(for: outline).opacity(0.25)) - .stroke(color(for: outline), lineWidth: 1.5) - } - } - .mapStyle(.standard(pointsOfInterest: .excludingAll)) - } - } + RegionOutlinesMap( + outlines: outlines, + cameraPosition: $cameraPosition, + color: color(for:), + ) .frame(maxHeight: .infinity) .accessibilityLabel(Strings.regionMapMapAccessibility) } @@ -281,6 +260,42 @@ public struct RegionMapView: View { } } +/// The map surface for ``RegionMapView``: the live MapKit `Map`, or — under +/// snapshot capture — a deterministic stand-in of identical layout. Owning the +/// `\.isCapturingSnapshot` branch here keeps the capture check out of +/// `RegionMapView` itself: the screen just renders this, unaware which substrate +/// it drew. MapKit's tile/label loading is asynchronous and cache/network- +/// dependent, so no settle window can make the real substrate pixel-stable; the +/// view's own overlays (the region polygons) still render for real in the +/// stand-in — only the tile substrate is replaced — per the +/// `\.isCapturingSnapshot` carve-out (see SnapshotKit's `SnapshotCaptureFlag`). +private struct RegionOutlinesMap: View { + let outlines: [RegionOutline] + @Binding var cameraPosition: MapCameraPosition + let color: (RegionOutline) -> Color + + @Environment(\.isCapturingSnapshot) private var isCapturingSnapshot + + var body: some View { + if isCapturingSnapshot { + SnapshotMapStandIn( + outlines: outlines, + region: RegionMapView.enclosingRegion(of: outlines), + color: color, + ) + } else { + Map(position: $cameraPosition) { + ForEach(outlines) { outline in + MapPolygon(coordinates: outline.coordinates.clLocationCoordinates) + .foregroundStyle(color(outline).opacity(0.25)) + .stroke(color(outline), lineWidth: 1.5) + } + } + .mapStyle(.standard(pointsOfInterest: .excludingAll)) + } + } +} + /// Deterministic stand-in for ``RegionMapView``'s live `Map` under snapshot /// capture: the same outlines, drawn with the same fill/stroke styling over a /// flat substrate, framed by the same enclosing-region math as the live diff --git a/Where/WhereUI/Sources/Launch/LaunchSplashView.swift b/Where/WhereUI/Sources/Launch/LaunchSplashView.swift index 979c3ef8..18ecb4a7 100644 --- a/Where/WhereUI/Sources/Launch/LaunchSplashView.swift +++ b/Where/WhereUI/Sources/Launch/LaunchSplashView.swift @@ -35,6 +35,12 @@ import SwiftUI /// deterministically. struct LaunchSplashView: View { @Environment(\.accessibilityReduceMotion) private var reduceMotion + // Two distinct questions, deliberately not merged: + // • `motionIsStatic` (Reduce Motion *or* capture) gates never-settling + // motion — the pulse — which must freeze in both cases. + // • `isCapturingSnapshot` alone gates the wall-clock caption timer below: + // Reduce Motion users still get the caption (just without the fade), so + // the timer can't key off `motionIsStatic` — only a capture skips it. @Environment(\.isCapturingSnapshot) private var isCapturingSnapshot @MotionIsStatic private var motionIsStatic @Environment(\.stylesheet) private var stylesheet @@ -172,11 +178,13 @@ private struct RadarPingBackground: View { private let maxOpacity: Double = 0.32 var body: some View { + // `motionIsStatic` pauses the clock (no ticks under Reduce Motion or + // capture); `isCapturingSnapshot` additionally pins the phase, since a + // paused `TimelineView` still reports its wall-clock pause instant — + // which would leak run-dependent ring radii/opacities into the capture. TimelineView(.animation(paused: motionIsStatic)) { timeline in Canvas { context, size in - let now = isCapturingSnapshot - ? 0 - : timeline.date.timeIntervalSinceReferenceDate + let now = timeline.radarPhaseClock(capturingSnapshot: isCapturingSnapshot) let center = CGPoint(x: size.width / 2, y: size.height / 2) let maxRadius = max(size.width, size.height) * 0.75 for index in 0 ..< ringCount { @@ -206,6 +214,15 @@ private struct RadarPingBackground: View { } } +extension TimelineViewDefaultContext { + /// The radar rings' animation-phase clock: the wall-clock time normally, or + /// a pinned constant under snapshot capture so the rings freeze at a + /// deterministic phase (see `RadarPingBackground`). + fileprivate func radarPhaseClock(capturingSnapshot: Bool) -> Double { + capturingSnapshot ? 0 : date.timeIntervalSinceReferenceDate + } +} + #if DEBUG extension LaunchSplashView: SnapshotProviding { static var snapshots: [SnapshotCase] { From e2491d7ce32d0f568543e6146eaaf5241329a6f6 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:49:21 -0700 Subject: [PATCH 6/8] Bridge isCapturingSnapshot the Broadway way; confirm MotionIsStatic; drop dead enum The capture flag was a pure UITraitBridgedEnvironmentKey, so a SwiftUI-set value (the preview cutsheet setting .environment for isCapturingSnapshot) paid a UITraitCollection round-trip / first-frame lag. Adopt Broadway BContext+SwiftUI pattern: a pure-SwiftUI EnvironmentKey read first, falling back to the trait-bridged value, with the setter mirroring into both. SwiftUI-set values now propagate synchronously; the test pipeline traitOverrides path still reaches SwiftUI via the fallback, and the WhereUI cross-boundary probe still exercises the bridged key. Verified: SnapshotKitTestingTests (pipeline path), SnapshotCaptureFlagProbeTests (cross-boundary), and motion-frozen captures (launchSplash, recentActivity) all pass. Also document that MotionIsStatic nested @Environment reads resolve (it is a DynamicProperty), and delete the unused empty enum SnapshotKit namespace file (SnapshotKitTesting.swift stays; its @_exported imports are load-bearing). Plan to-do: bridging. --- .../Sources/SnapshotCaptureFlag.swift | 28 +++++++++++++++++-- Shared/SnapshotKit/Sources/SnapshotKit.swift | 19 ------------- .../Sources/Shared/MotionIsStatic.swift | 7 +++++ 3 files changed, 32 insertions(+), 22 deletions(-) delete mode 100644 Shared/SnapshotKit/Sources/SnapshotKit.swift diff --git a/Shared/SnapshotKit/Sources/SnapshotCaptureFlag.swift b/Shared/SnapshotKit/Sources/SnapshotCaptureFlag.swift index 7938646a..ae7345e7 100644 --- a/Shared/SnapshotKit/Sources/SnapshotCaptureFlag.swift +++ b/Shared/SnapshotKit/Sources/SnapshotCaptureFlag.swift @@ -32,6 +32,18 @@ private struct IsCapturingSnapshotKey: UITraitBridgedEnvironmentKey { } } +/// A pure-SwiftUI capture flag set by SwiftUI-native callers (the preview +/// cutsheet's `.environment(\.isCapturingSnapshot, true)`, or any `.environment` +/// override). Because it's an ordinary `EnvironmentKey` — not trait-bridged — it +/// propagates synchronously through the SwiftUI tree with no `UITraitCollection` +/// round-trip or first-frame lag. `nil` means "no SwiftUI ancestor set one", so +/// the accessor falls back to the UIKit-bridged value. This mirrors Broadway's +/// `BContext+SwiftUI` bridging, and is why the capture pipeline's +/// `traitOverrides`-set value (UIKit) still reaches SwiftUI via the fallback. +private struct SwiftUIIsCapturingSnapshotKey: EnvironmentKey { + static let defaultValue: Bool? = nil +} + extension EnvironmentValues { /// `true` while `SnapshotKitTesting` captures this view for a snapshot test, /// and in the ``SnapshotProviding/snapshotPreviews`` cutsheet (previews @@ -53,7 +65,7 @@ extension EnvironmentValues { /// Keep the placeholder honest: the view's own chrome (markers, overlays, /// legends, row titles) must still render for real; only the /// nondeterministic element is substituted (see the Where app's - /// `RegionMapView` and `SnapshotDatePickerStandIn`). + /// `RegionMapView` and `WhereDatePicker`). /// /// The same determinism rationale covers **wall-clock timers that flip /// visible state**: whether such a timer has fired by capture time races @@ -62,8 +74,18 @@ extension EnvironmentValues { /// each state then gets its own snapshot case (see the Where app's launch /// splash, whose slow-launch caption shows iff its `previewShowsCaption` /// seam says so). Everything else must render real content. + /// + /// A SwiftUI-set value (the preview cutsheet, or any `.environment` + /// override) is read synchronously from a pure-SwiftUI key; with none set, + /// it falls back to the value bridged from the nearest UIKit ancestor's + /// trait collection (how the test pipeline's `traitOverrides` reaches + /// SwiftUI). Writing mirrors into both so a SwiftUI-set flag also reaches + /// nested UIKit. public var isCapturingSnapshot: Bool { - get { self[IsCapturingSnapshotKey.self] } - set { self[IsCapturingSnapshotKey.self] = newValue } + get { self[SwiftUIIsCapturingSnapshotKey.self] ?? self[IsCapturingSnapshotKey.self] } + set { + self[SwiftUIIsCapturingSnapshotKey.self] = newValue + self[IsCapturingSnapshotKey.self] = newValue + } } } diff --git a/Shared/SnapshotKit/Sources/SnapshotKit.swift b/Shared/SnapshotKit/Sources/SnapshotKit.swift deleted file mode 100644 index dd83db5b..00000000 --- a/Shared/SnapshotKit/Sources/SnapshotKit.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// SnapshotKit.swift -// SnapshotKit -// - -/// SnapshotKit is the generic, shippable half of the snapshot-testing framework. -/// -/// It owns the appearance *matrix*: a ``SnapshotConfiguration`` describing one -/// rendering variant (color scheme, Dynamic Type, contrast, device frame, and -/// whether it is a standard or accessibility capture), the presets and -/// `combinations(...)` that expand into a matrix, the ``SnapshotProviding`` -/// protocol a component adopts to declare its variants, and the SwiftUI preview -/// *cutsheet* that renders them in Xcode. -/// -/// It imports only SwiftUI / Foundation / UIKit — never the test-only snapshot -/// comparison engine — so a UI module can drive its `#Preview`s from the exact -/// configurations its snapshot tests assert against. The comparison + capture -/// pipeline lives in the sibling `SnapshotKitTesting` module. See `README.md`. -public enum SnapshotKit {} diff --git a/Where/WhereUI/Sources/Shared/MotionIsStatic.swift b/Where/WhereUI/Sources/Shared/MotionIsStatic.swift index f1764b29..c79f7c87 100644 --- a/Where/WhereUI/Sources/Shared/MotionIsStatic.swift +++ b/Where/WhereUI/Sources/Shared/MotionIsStatic.swift @@ -18,6 +18,13 @@ import SwiftUI /// guard !motionIsStatic else { return } /// withAnimation(.easeInOut.repeatForever()) { pulsing = true } /// ``` +/// +/// `@Environment` reads work here because the wrapper is a `DynamicProperty`: +/// SwiftUI walks a view's `DynamicProperty` members (including nested ones) and +/// populates their environment before `body`, so the two reads resolve exactly +/// as they would on the view itself. Proven end-to-end by the `launchSplash.*` +/// captures (the pulse/radar freeze only if this reads the capture flag) and by +/// `WhereUISnapshotTests.SnapshotCaptureFlagProbeTests`. @propertyWrapper struct MotionIsStatic: DynamicProperty { @Environment(\.accessibilityReduceMotion) private var reduceMotion From 89af9b353c427c2d90619c4e07f4643d869b5bd4 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:51:35 -0700 Subject: [PATCH 7/8] Document the snapshot pipeline's host-window, settle, and caret decisions Answer the review questions on SnapshotKitTesting with in-code rationale (no behavior change): - hostKeyWindow(): note it is the window StuffTestHost stamps with isMainTestHostWindow (the guaranteed root we set up), not merely the current key window, so it is stable across transient key-window changes. - Settle stability compares quarter-res samples byte-exact, deliberately unlike the final image compare tolerance: this loop asks has rendering stopped changing (the low-res sample already absorbs sub-pixel jitter), and a tolerance would let a slow drift read as settled. - hideTextInputCursors walks the tree targeting only text inputs rather than clearing the root tint once: tintColor inherits, so a clear root tint would also blank every accent-tinted control (buttons, links, toggles) and change the image. (The SafeAreaInsetsSwizzling verification landed as SafeAreaCompositionTests in the SnapshotKitTesting bundle.) Plan to-do: pipeline-questions. --- .../Sources/SnapshotImageRendering.swift | 4 ++++ .../Sources/SnapshotRenderingSupport.swift | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/Shared/SnapshotKitTesting/Sources/SnapshotImageRendering.swift b/Shared/SnapshotKitTesting/Sources/SnapshotImageRendering.swift index ae070a53..3d2f6296 100644 --- a/Shared/SnapshotKitTesting/Sources/SnapshotImageRendering.swift +++ b/Shared/SnapshotKitTesting/Sources/SnapshotImageRendering.swift @@ -96,6 +96,10 @@ private func renderSnapshotImageLocked( onReadyToSnapshot: (@MainActor () async -> Void)?, ) async -> UIImage { func capture() async -> UIImage { + // `hostKeyWindow()` is the specific window `StuffTestHost` stamps with + // `isMainTestHostWindow` — the guaranteed root window we set up, not + // merely whatever window happens to be key. So this is stable regardless + // of any transient key-window changes during a capture. guard let window = hostKeyWindow(), let hostRoot = window.rootViewController else { preconditionFailure( "SnapshotKitTesting requires the StuffTestHost key window. Run snapshot tests in a hosted bundle.", diff --git a/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift b/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift index d4fc3a58..a29d1cfe 100644 --- a/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift +++ b/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift @@ -86,6 +86,13 @@ func settleContent( } CATransaction.performWithoutAnimation(view.layoutIfNeeded) let sample = view.renderedContentSample() + // Byte-exact on purpose — not the tolerance the final image compare uses. + // The final compare answers "does this match the reference?", where + // sub-pixel/gamut noise warrants a perceptual threshold. This loop answers + // a different question — "has rendering *stopped changing*?" — and the + // quarter-resolution sample already absorbs sub-pixel jitter, so exact + // equality is the right settled signal. A tolerance here would let a slow, + // still-drifting animation read as settled between adjacent samples. if sample != nil, sample == anchorSample { stablePasses += 1 } else { @@ -152,6 +159,12 @@ func drainInFlightAnimations(timeout: TimeInterval = 1) -> Bool { extension UIView { /// Clears the tint color of every text input in the tree so the blinking caret /// doesn't flake captures. Not restored — capture hosts are transient. + /// + /// It walks the tree and targets only `UITextField`/`UITextView` rather than + /// clearing the tint once at the root: `tintColor` inherits, so a clear root + /// tint would also blank every control that draws with the accent tint — + /// buttons, links, toggles, `Label` glyphs — silently changing the captured + /// image. Only the text inputs (whose caret *is* the tint) may be cleared. @MainActor func hideTextInputCursors() { recursiveForEach(UITextField.self) { $0.tintColor = .clear } From 73cd1e5a52f8459522ae312842dd7c35818f8cc1 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 20 Jul 2026 20:57:39 -0700 Subject: [PATCH 8/8] Docs + TODOs: reflect the snapshot restructure; file the CalendarView smell - SnapshotKitTesting/AGENTS: replace the now-false 'no dedicated test bundle' note with SnapshotKitTestingTests (pixel-probe pipeline regressions, in the main Stuff-iOS-Tests scheme). - SnapshotKit/AGENTS: describe isCapturingSnapshot as the Broadway-style hybrid (synchronous SwiftUI key + trait-bridged fallback). - WhereUI/AGENTS + README: matrices now declared in each view's own file (cutsheet via Self.snapshotPreviews), one FooSnapshotTests per view with per-view __Snapshots__ dirs; drop the stale 'bold text' matrix mention. - root AGENTS: note SnapshotKitTestingTests runs in the normal test job (no LFS), unlike the image-reference bundles. - Where/TODOs: file the CalendarView capture-time scroll-skip smell; mark the onboarding-leak and preview/cutsheet-claim findings resolved; note the pinned-instant de-duplication and why the matrix-gap cases stay deferred (local reference recording risks CI drift). Regenerated CLAUDE.md via ./sync-agents (gitignored). Plan to-do: todo-and-docs. --- AGENTS.md | 2 +- Shared/SnapshotKit/AGENTS.md | 10 +++++++--- Shared/SnapshotKitTesting/AGENTS.md | 16 ++++++++++++++-- Where/TODOs.md | 9 +++++---- Where/WhereUI/AGENTS.md | 24 ++++++++++++++---------- Where/WhereUI/README.md | 8 +++++--- 6 files changed, 46 insertions(+), 23 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 92d9377c..fc7a8a64 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -65,7 +65,7 @@ by `./sync-agents`. `AGENTS.md` says what it is and how it may be used. - Add SPM library targets in `Package.swift` and wire apps/tests in `Project.swift` (see existing `unitTests` helper). A new module also ships a root `README.md` and `AGENTS.md` — see [Per-module docs](#per-module-docs). - **CI scheme**: CI runs the explicit shared **Stuff-iOS-Tests** scheme (all test bundles) rather than the autogenerated `Stuff-Workspace` scheme. New test bundles must be added to the `Stuff-iOS-Tests` scheme in `Project.swift` or CI won't run them. -- **Snapshot test bundles are the exception**: image snapshot bundles (currently **WhereUISnapshotTests**) are slow and LFS-backed, so each runs via its own standalone scheme (declared in `Project.swift`, e.g. `WhereUISnapshotTests`) and a dedicated CI `snapshot` job — deliberately **not** in `Stuff-iOS-Tests`. Reference images under any `__Snapshots__/` directory are stored in **Git LFS** (see `.gitattributes`); the CI job checks out with `lfs: true`. The framework halves live in `Shared/SnapshotKit` (shippable matrix + previews) and `Shared/SnapshotKitTesting` (test-only capture/compare pipeline). +- **Snapshot test bundles are the exception**: image snapshot bundles (currently **WhereUISnapshotTests**) are slow and LFS-backed, so each runs via its own standalone scheme (declared in `Project.swift`, e.g. `WhereUISnapshotTests`) and a dedicated CI `snapshot` job — deliberately **not** in `Stuff-iOS-Tests`. Reference images under any `__Snapshots__/` directory are stored in **Git LFS** (see `.gitattributes`); the CI job checks out with `lfs: true`. The framework halves live in `Shared/SnapshotKit` (shippable matrix + previews) and `Shared/SnapshotKitTesting` (test-only capture/compare pipeline). The pipeline's own regression tests are a *separate* bundle, **SnapshotKitTestingTests**, which pixel-probes captures (no LFS references) and so runs in the normal `Stuff-iOS-Tests` scheme / `test` job — only the image-reference bundles above take the standalone-scheme + `snapshot`-job route. - **Never double-link a package product into a test bundle that already gets it through a dynamic-framework dependency.** Xcode's default SPM integration (how `Package.local` is wired here) embeds a product's code into *every* image that links it. **WhereUI** is a dynamic framework that statically embeds its own dependencies (WhereCore, BroadwayCore/BroadwayUI, LifecycleKit, LogViewerUI, SwiftDataInspector, …), so a `*Tests` bundle that depends on **WhereUI** *and* re-lists one of those in `extraPackageProducts` ends up with a **second copy** of it. When the shared **StuffTestHost** loads several `.xctest` bundles into one process, that leaves duplicate **type metadata** for the module, and any *type-keyed runtime lookup that crosses the WhereUI boundary* — SwiftUI `EnvironmentKey`s, `UITraitBridgedEnvironmentKey` bridging, the type-keyed `BTraits`/`BThemes`/`BStylesheets` containers — silently resolves against the wrong copy and returns the default (the writer stores under one copy's key *type*, the reader looks it up under another's). It only reproduces in the **full multi-bundle scheme** (not isolated `tuist test WhereUITests` runs) and is papered over by newer Xcode linkers, so it is brutal to diagnose (it cost ~2 hours once). **Depend on such products only transitively via `WhereUI`; keep them out of `extraPackageProducts`.** `WhereStylesheetTests.resolvesTraitAwareTokensFromTheBroadwayRoot` is the regression guard — it exercises a `\.stylesheet` (→ `\.bContext`) read across the boundary and fails if a duplicate copy returns. ## Deployment diff --git a/Shared/SnapshotKit/AGENTS.md b/Shared/SnapshotKit/AGENTS.md index ccaadf44..2f39917e 100644 --- a/Shared/SnapshotKit/AGENTS.md +++ b/Shared/SnapshotKit/AGENTS.md @@ -38,9 +38,13 @@ Complements the root [`AGENTS.md`](../../AGENTS.md) — read that first. deterministic — externally-loaded substrates, system controls that render relative to wall-clock state, wall-clock timers that flip visible state (skipped under capture; an explicit per-case seam pins each state) — may - substitute a placeholder of identical layout. It is a UIKit trait bridge - (not `@Entry`) so it reaches SwiftUI through the re-hosting the capture - pipeline does. + substitute a placeholder of identical layout. It is a **hybrid** accessor + (like Broadway's `BContext+SwiftUI`): a pure-SwiftUI `EnvironmentKey` read + first — set synchronously by the preview cutsheet / any `.environment` + override, no `UITraitCollection` round-trip — falling back to a + `UITraitBridgedEnvironmentKey` (not `@Entry`), which is how the test + pipeline's `traitOverrides` value reaches SwiftUI through the re-hosting the + capture does. The setter mirrors into both. - **Design-system-agnostic.** SnapshotKit never imports Broadway/WhereUI; the Broadway root wrap is a consumer concern (`WhereUI`'s `whereSnapshot(...)`). diff --git a/Shared/SnapshotKitTesting/AGENTS.md b/Shared/SnapshotKitTesting/AGENTS.md index cacbc9ff..689f1549 100644 --- a/Shared/SnapshotKitTesting/AGENTS.md +++ b/Shared/SnapshotKitTesting/AGENTS.md @@ -77,5 +77,17 @@ Complements the root [`AGENTS.md`](../../AGENTS.md) — read that first. ## Testing -No dedicated test bundle; exercised by every `*SnapshotTests` bundle that calls -`assertSnapshots` (currently `WhereUISnapshotTests`). +`SnapshotKitTestingTests` (`Tests/`, wired in `Project.swift`, in the +`Stuff-iOS-Tests` scheme) owns the pipeline's own regression tests: async-content +settle, concurrent-capture serialization, duplicate-identifier detection, +tile-and-stitch / full-content sizing, the pre-capture hook, the same-image +capture-flag surface, and safe-area composition (the swizzle zeroes the captured +root while an interior `safeAreaInset` still composes). They render through +`renderSnapshotImage` (so they need the `StuffTestHost` key window) but assert on +probed pixels via the `@_spi(Testing)` `PixelSample`/`probePixel` API rather than +LFS reference images — so the bundle is fast, has no `__Snapshots__/`, and runs +in the main `test` job, not the snapshot job. The matrixed image assertions +themselves are still exercised by consumer bundles (currently +`WhereUISnapshotTests`); the WhereUI↔bundle cross-boundary flag probe stays there +(`SnapshotCaptureFlagProbeTests`), since only a WhereUI-defined view can detect a +duplicate-`SnapshotKit` split. diff --git a/Where/TODOs.md b/Where/TODOs.md index 08653a04..39bbc9ae 100644 --- a/Where/TODOs.md +++ b/Where/TODOs.md @@ -52,10 +52,9 @@ This feels like it might result in a cleaner "pipeline-esque" code layout, and a - Move test only code behind @_spi - Add comments to strings in xcstrings files - Can we code-gen the strings.swift file somehow so we're not referencing the string keys manually? -- fix: The Onboarding snapshot fixture leaks real `UserDefaults` — `WhereUI/Sources/Preview/AppFlowSnapshots.swift` builds `WhereModel(services:)`, whose default is `WherePreferences(store: UserDefaults.standard)`. Rendering doesn't currently depend on it, but it contradicts PreviewSupport's "none of it touches disk" contract and the pre-onboarded fix in the same PR. Fix: inject `WherePreferences(store: InMemoryKeyValueStore())` (or add a `PreviewSupport.onboardingModel()`). (From the July 2026 snapshot-testing PR review.) -- refactor: Duplicated pinned-instant fixtures — the magic `1_770_000_000` appears in both `WidgetSnapshots.swift` and `AppFlowSnapshotTests.swift`, and `WidgetSnapshots` hand-rolls a `widgetSnapshot(...)` helper while `PreviewSupport.sampleWidgetSnapshot` (which still defaults `day: .now`) sits unused by the conformances. Fix: centralize one pinned instant on `PreviewSupport` and default `sampleWidgetSnapshot(day:)` to it — and when picking it, prefer an instant safely away from midnight in both UTC and the pinned Pacific zone (the current one is 02:40 UTC / Feb 1 evening Pacific, right on a day boundary). (From the July 2026 snapshot-testing PR review.) -- docs: WhereUI doc claims outrun reality — `WhereUI/AGENTS.md` and `README.md` say the `SnapshotProviding` conformance "also drives the `#Preview` cutsheets", but no `#Preview` in WhereUI renders `snapshotPreviews`; the per-view previews remain bespoke (e.g. `PrimaryView.swift`). The README also lists "bold text" in the matrix, but no case uses the `legibilityWeight` axis. Adopt the cutsheet in at least the conformant views' previews, or soften the claims. (From the July 2026 snapshot-testing PR review.) -- test: Snapshot matrix gaps — `PrimaryView`'s empty state has a preview but no snapshot case (the only pin on it is accidentally via the known-wrong `root.LoggedIn`), and `RecentActivitySummaryView.loading` — the sole user of `AppIconActivityIndicator` — has no case, so that view's `@MotionIsStatic` pinning is the one motion adoption with zero capture coverage (`TypewriterText` is proven by `recentActivity.Loaded`; the radar/pulse by `launchSplash.*`). (From the July 2026 snapshot-testing PR review.) +- refactor: Remove `CalendarYearGrid`'s capture-time scroll skip. `scrollToCurrentMonth` guards on `\.isCapturingSnapshot` so a capture pins the deterministic top-of-year state instead of a nondeterministic scroll landing (`WhereUI/Sources/Primary/CalendarView.swift`). It's the one remaining product-code read of the snapshot flag that isn't a substituted stand-in — a smell (product behavior forking on "are we snapshotting"). Prefer making the scroll itself deterministic under capture (or driving the capture from a pre-scrolled fixture) so the guard can go. Not from the snapshot PR originally; noted during its review. (From the July 2026 snapshot-testing PR review.) +- refactor: Duplicated pinned-instant fixtures — *mostly resolved* in the July 2026 review follow-up: `WidgetSnapshots.swift` is gone (widget matrices moved into the view files and now use `PreviewSupport.sampleWidgetSnapshot`, which defaults `day:` to the new pinned `PreviewSupport.referenceWidgetDay`). Remaining nicety, deferred: the pinned instant is still `1_770_000_000` (02:40 UTC / Feb 1 evening Pacific, near a day boundary); moving it safely off midnight was skipped to avoid re-recording the widget references. (From the July 2026 snapshot-testing PR review.) +- test: Snapshot matrix gaps — *deferred*: `PrimaryView`'s empty state, `RecentActivitySummaryView.loading` (the sole user of `AppIconActivityIndicator`, so its `@MotionIsStatic` pinning is the one motion adoption without direct capture coverage), and `ManualDayView`'s range-mode add have no snapshot case. Adding them needs new reference images recorded locally, which risks diverging from CI's macOS renderer (a hair-width local drift already surfaces on `resolution.Empty` — see the review-cleanup PR), so this is held until it can be recorded in the reference environment. (From the July 2026 snapshot-testing PR review.) ## Deferred snapshot-test flakiness Known nondeterminism in `WhereUISnapshotTests`, accepted for now — scattered @@ -94,3 +93,5 @@ re-recording: ## P2s (Nice to have) - refactor: Clean up and centralize loggers into a logging module — added the `LogKit` facade (`WhereLog.channel`) and a DEBUG-only in-app log viewer (`LogViewerUI`, Settings → Developer → Logs) +- fix: The Onboarding snapshot fixture leaked real `UserDefaults`. (Resolved in the July 2026 review-cleanup PR: the conformance — now in `OnboardingView.swift` — builds `PreviewSupport.onboardingModel()`, which uses `WherePreferences(store: InMemoryKeyValueStore())`, honoring the no-disk contract.) +- docs: WhereUI docs claimed the `SnapshotProviding` conformance drove the `#Preview` cutsheets when no `#Preview` actually rendered `snapshotPreviews`. (Resolved in the July 2026 review-cleanup PR: each conformance moved into its view file and its `#Preview` now renders `Self.snapshotPreviews`, so previews and image tests share one declaration. The stale "bold text" matrix mention was softened in the WhereUI docs — no case uses the `legibilityWeight` axis yet.) diff --git a/Where/WhereUI/AGENTS.md b/Where/WhereUI/AGENTS.md index 24023469..bae00cf4 100644 --- a/Where/WhereUI/AGENTS.md +++ b/Where/WhereUI/AGENTS.md @@ -137,15 +137,19 @@ required previews) live in the feature [`Where/AGENTS.md`](../AGENTS.md). Screens, widgets, and app-flow surfaces are pinned as matrixed image snapshots in the `WhereUISnapshotTests` bundle ([`SnapshotTests/`](SnapshotTests)) — that -bundle, not hosting smoke tests, owns "does this screen render". Each view -declares its matrix once via a `SnapshotProviding` conformance in -[`Sources/Preview/`](Sources/Preview) (`ScreenSnapshots.swift`, -`WidgetSnapshots.swift`, `AppFlowSnapshots.swift`), which also drives the -`#Preview` cutsheets. The bundle runs in its own `WhereUISnapshotTests` scheme -and CI job, deliberately outside `Stuff-iOS-Tests` (see `Project.swift`). To -re-record a reference, delete the PNG under `SnapshotTests/__Snapshots__/` -(LFS-tracked) and run the scheme — the suites record `.missing`, and a -recording run fails by design so it can't pass as green. (Bulk re-records -after an intentional UI change can instead forward +bundle, not hosting smoke tests, owns "does this screen render". **Each view +declares its matrix once, in its own source file**, via a `SnapshotProviding` +conformance under `#if DEBUG` whose `#Preview` renders `Self.snapshotPreviews` — +so one declaration drives both the Xcode cutsheet and the image tests (the +`whereSnapshot(...)` helper + config presets live in +[`Sources/Preview/WhereSnapshot.swift`](Sources/Preview/WhereSnapshot.swift)). +The test bundle is **one `FooSnapshotTests` suite per view**, each in its own +file calling `assertSnapshots(of: FooView.self)`, so each view's references sit +in their own `__Snapshots__//` directory. The bundle runs in +its own `WhereUISnapshotTests` scheme and CI job, deliberately outside +`Stuff-iOS-Tests` (see `Project.swift`). To re-record a reference, delete the PNG +under `SnapshotTests/__Snapshots__/` (LFS-tracked) and run the scheme — the +suites record `.missing`, and a recording run fails by design so it can't pass as +green. (Bulk re-records after an intentional UI change can instead forward `TEST_RUNNER_SNAPSHOT_RECORD=failed` — see the [SnapshotKitTesting README](../../Shared/SnapshotKitTesting/README.md#recording).) diff --git a/Where/WhereUI/README.md b/Where/WhereUI/README.md index 22708df6..e3b64740 100644 --- a/Where/WhereUI/README.md +++ b/Where/WhereUI/README.md @@ -132,11 +132,13 @@ the on-disk/CloudKit store). Internal types are reached via How screens *look* is pinned separately: every top-level screen, widget, and app-flow surface has matrixed image snapshots (light/dark, Dynamic Type, -iPhone/iPad, contrast, right-to-left, bold text, VoiceOver annotations) in +iPhone/iPad, contrast, right-to-left, VoiceOver annotations) in [`SnapshotTests/`](SnapshotTests) (`WhereUISnapshotTests`), with reference images under `SnapshotTests/__Snapshots__/` in Git LFS. Each view declares its -matrix via a `SnapshotProviding` conformance in -[`Sources/Preview/`](Sources/Preview), shared with its `#Preview` cutsheet. The +matrix via a `SnapshotProviding` conformance **in its own source file**, shared +with its `#Preview` cutsheet (`Self.snapshotPreviews`); the test bundle is one +`FooSnapshotTests` suite per view, so each view's references live in their own +`__Snapshots__/` directory. The bundle has its own scheme and CI job; to re-record after an intentional UI change, forward the record mode into the test process (see the [SnapshotKitTesting README](../../Shared/SnapshotKitTesting/README.md#recording)