diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2dff456 --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +# Makefile for HoneyDue KMM — wraps the long-form commands you actually +# use every day. If you find yourself copy/pasting a command twice, it +# belongs here. +# +# Quick reference +# --------------- +# make verify-snapshots # fast; run on every PR, CI runs this +# make record-snapshots # slow; regenerate baselines after UI change +# make optimize-goldens # rarely needed — record-snapshots runs this +# +.PHONY: help record-snapshots verify-snapshots optimize-goldens \ + record-ios record-android verify-ios verify-android + +help: + @echo "HoneyDue KMM — common tasks" + @echo "" + @echo " make verify-snapshots Verify iOS + Android parity goldens (CI gate)" + @echo " make record-snapshots Regenerate iOS + Android goldens + optimize" + @echo " make optimize-goldens Run the PNG optimizer across both directories" + @echo "" + @echo " make verify-ios Verify just the iOS gallery" + @echo " make verify-android Verify just the Android gallery" + @echo " make record-ios Regenerate just the iOS gallery" + @echo " make record-android Regenerate just the Android gallery" + @echo "" + +# ---- Parity gallery (combined) ---- + +# Regenerate every parity-gallery golden (iOS + Android) and shrink the +# output PNGs. Slow (~3 min); run after intentional UI changes only. +record-snapshots: + @./scripts/record_snapshots.sh + +# Verify current UI matches committed goldens. Fast (~1 min). PR gate. +verify-snapshots: + @./scripts/verify_snapshots.sh + +# Optimize every PNG golden in-place (idempotent). Usually invoked +# automatically by record-snapshots; exposed here for one-off cleanup. +optimize-goldens: + @./scripts/optimize_goldens.sh + +# ---- Parity gallery (single platform) ---- + +record-ios: + @./scripts/record_snapshots.sh --ios-only + +record-android: + @./scripts/record_snapshots.sh --android-only + +verify-ios: + @./scripts/verify_snapshots.sh --ios-only + +verify-android: + @./scripts/verify_snapshots.sh --android-only diff --git a/iosApp/HoneyDueTests/SnapshotGalleryTests.swift b/iosApp/HoneyDueTests/SnapshotGalleryTests.swift index 4f006be..b0323a7 100644 --- a/iosApp/HoneyDueTests/SnapshotGalleryTests.swift +++ b/iosApp/HoneyDueTests/SnapshotGalleryTests.swift @@ -25,9 +25,26 @@ // // Recording goldens // ----------------- -// Set `isRecording = true` in `setUp()`, run the target, then flip back to -// `false` before committing. CI fails the build if a screen diverges from -// its golden by more than the precision threshold. +// Preferred: `make record-snapshots` (or `./scripts/record_snapshots.sh +// --ios-only`). The script exports `SNAPSHOT_TESTING_RECORD=1` in the +// xcodebuild env, deletes the old `__Snapshots__/SnapshotGalleryTests` +// directory, runs the target, then invokes the shared PNG optimizer. +// +// Manual override: set the `SNAPSHOT_TESTING_RECORD` env var to `1` in +// the Xcode scheme's Test action (Edit Scheme → Test → Arguments → +// Environment Variables) and re-run the test target. CI fails the +// build if a screen diverges from its golden by more than the +// precision threshold. +// +// Rendering scale +// --------------- +// We force `displayScale: 2.0` on every snapshot. The iPhone 15 / +// iPhone 13 simulators default to the device's native 3x, which on a +// full-screen gradient-heavy SwiftUI view produced 800–1000 KB PNGs +// per image. @2x halves the linear dimensions (2.25x fewer pixels) and +// is still plenty to catch layout regressions. Combined with +// `scripts/optimize_goldens.sh` (zopflipng / pngcrush) this keeps us +// under the 150 KB per-image budget enforced by CI. // @preconcurrency import SnapshotTesting @@ -39,8 +56,14 @@ import ComposeApp @MainActor final class SnapshotGalleryTests: XCTestCase { - // Flip to true locally, run the scheme, revert, commit. - private static let recordMode: SnapshotTestingConfiguration.Record = .missing + // Record mode is driven by the `SNAPSHOT_TESTING_RECORD` env var so + // `scripts/record_snapshots.sh` can flip it without mutating this file. + // When the var is unset/empty we only write missing goldens (`.missing`) + // so local dev runs never silently overwrite committed PNGs. + private static var recordMode: SnapshotTestingConfiguration.Record { + let env = ProcessInfo.processInfo.environment["SNAPSHOT_TESTING_RECORD"] ?? "" + return (env == "1" || env.lowercased() == "true") ? .all : .missing + } override func invokeTest() { withSnapshotTesting(record: Self.recordMode) { @@ -63,6 +86,12 @@ final class SnapshotGalleryTests: XCTestCase { private static let pixelPrecision: Float = 0.97 private static let perceptualPrecision: Float = 0.95 + /// Force @2x rendering regardless of the simulator device's native + /// `displayScale`. See the class-level "Rendering scale" comment for + /// rationale. 2.0 keeps PNGs under the size budget without sacrificing + /// the structural detail our parity gallery cares about. + private static let forcedDisplayScale: CGFloat = 2.0 + private func snap( _ name: String, file: StaticString = #filePath, @@ -80,7 +109,10 @@ final class SnapshotGalleryTests: XCTestCase { precision: Self.pixelPrecision, perceptualPrecision: Self.perceptualPrecision, layout: .device(config: .iPhone13), - traits: .init(userInterfaceStyle: .light) + traits: .init(traitsFrom: [ + UITraitCollection(userInterfaceStyle: .light), + UITraitCollection(displayScale: Self.forcedDisplayScale), + ]) ), named: "\(name)_light", file: file, @@ -93,7 +125,10 @@ final class SnapshotGalleryTests: XCTestCase { precision: Self.pixelPrecision, perceptualPrecision: Self.perceptualPrecision, layout: .device(config: .iPhone13), - traits: .init(userInterfaceStyle: .dark) + traits: .init(traitsFrom: [ + UITraitCollection(userInterfaceStyle: .dark), + UITraitCollection(displayScale: Self.forcedDisplayScale), + ]) ), named: "\(name)_dark", file: file, diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_dark.png index fc09435..3eeb3d5 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_light.png index 5f00ec2..a429c65 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_residence_empty.add_residence_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_dark.png index 0eae98d..ff8896d 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_light.png index f444d14..b29f6aa 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_empty.add_task_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_dark.png index 2a54c3e..36edde7 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_light.png index d0732bc..9fab222 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_add_task_with_residence_empty.add_task_with_residence_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_dark.png index 5cba41f..050ff62 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_light.png index 1a74219..6ae5c73 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_all_tasks_empty.all_tasks_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_dark.png index 8c5078d..53b6b4f 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_light.png index 586dff5..57b0458 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_contractors_list_empty.contractors_list_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_dark.png index 16b0e71..30ede82 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_light.png index 2a94243..474f92d 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_documents_warranties_empty.documents_warranties_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_dark.png index 9fd0cbd..3c32e1f 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_light.png index 1b2da73..d516483 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_feature_comparison_empty.feature_comparison_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_dark.png index 35373d4..2a48bc0 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_light.png index f34c1e4..e1a5202 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_forgot_password_empty.forgot_password_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_dark.png index 0cb3bd5..3837384 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_light.png index fae8b76..2e5e3c3 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_join_residence_empty.join_residence_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_dark.png index 720f28e..0a3ce4a 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_light.png index 0fea715..037e376 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_login_empty.login_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_dark.png index 6a236d0..434201a 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_light.png index c870ff2..c1a54b5 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_notification_preferences_empty.notification_preferences_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_dark.png index 3f3bac6..739613b 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_light.png index 35b8d5f..408e2b0 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_create_account_empty.onboarding_create_account_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_dark.png index bdc45fa..3e1f6c2 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_light.png index b0f33e6..4ff9914 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_first_task_empty.onboarding_first_task_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_dark.png index 0abfbaf..410fadc 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_light.png index 0a0f07b..296520e 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_join_residence_empty.onboarding_join_residence_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_dark.png index c7f93c7..11a0b74 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_light.png index b7395ac..737e92e 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_name_residence_empty.onboarding_name_residence_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_dark.png index 8259ae9..2d7743d 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_light.png index f1ef01b..67efbe8 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_subscription_empty.onboarding_subscription_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_dark.png index 5296830..006a781 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_light.png index ff0cec6..983d6ad 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_value_props_empty.onboarding_value_props_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_dark.png index 9b721c3..a53a87c 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_light.png index a29c93c..2f250d6 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_verify_email_empty.onboarding_verify_email_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_dark.png index 46b5524..9fe2ba1 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_light.png index 8cab6e7..19e855b 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_onboarding_welcome_empty.onboarding_welcome_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_dark.png index 4a549c8..d9961be 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_light.png index e2286e5..d0a2127 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_edit_empty.profile_edit_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_dark.png index bdcc338..700b036 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_light.png index 209d868..16ec7dc 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_profile_tab_empty.profile_tab_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_dark.png index 5179e23..4933151 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_light.png index 0559956..f8ac607 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_register_empty.register_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_dark.png index 9e25b6a..db980d9 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_light.png index 0e5e891..5d70dc0 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_reset_password_empty.reset_password_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_dark.png index 5cba41f..050ff62 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_light.png index 1a74219..6ae5c73 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_residences_list_empty.residences_list_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_dark.png index 646c061..79b314c 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_light.png index c266f44..9ca3cce 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_suggestions_empty.task_suggestions_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_dark.png index 1f7f821..9689a0b 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_light.png index 8f86ee3..e2f4b22 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_task_templates_browser_empty.task_templates_browser_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_dark.png index 2a91c0b..a88b8e9 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_light.png index a30255c..94281f8 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_theme_selection_empty.theme_selection_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_dark.png index 59627c8..d6e3c88 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_light.png index addd861..18a1e1e 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_email_empty.verify_email_empty_light.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_dark.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_dark.png index 7c9ae6a..e2a68ee 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_dark.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_dark.png differ diff --git a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_light.png b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_light.png index 8f1f21a..c0c7195 100644 Binary files a/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_light.png and b/iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests/test_verify_reset_code_empty.verify_reset_code_empty_light.png differ diff --git a/scripts/optimize_goldens.sh b/scripts/optimize_goldens.sh new file mode 100755 index 0000000..34b180f --- /dev/null +++ b/scripts/optimize_goldens.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# +# optimize_goldens.sh — recursively optimize PNG goldens in-place. +# +# Runs after each `record` pass for both iOS and Android parity galleries. +# Removes unnecessary PNG chunks (textual metadata, ancillary palette +# entries) and re-encodes the image with a better DEFLATE strategy so the +# image bytes on disk drop by 15–40% without touching a single pixel. +# +# Dependencies +# ------------ +# zopflipng (preferred — brute-force DEFLATE, best compression) +# pngcrush (fallback — faster, smaller savings) +# +# Install on macOS: +# brew install zopfli pngcrush +# +# The script never fails if the tools are missing: it warns and exits 0, +# leaving the goldens untouched. CI's size-gate will still fail loudly if +# the PNGs would bust the 150 KB budget. +# +# Usage +# ----- +# ./scripts/optimize_goldens.sh # default dirs (iOS + Android) +# ./scripts/optimize_goldens.sh path1 path2 # specific dirs only +# +# Idempotent — re-running on already-optimized PNGs is a no-op. +# +set -euo pipefail + +DIRS=("$@") +if [ ${#DIRS[@]} -eq 0 ]; then + DIRS=( + "iosApp/HoneyDueTests/__Snapshots__" + "composeApp/src/androidUnitTest/roborazzi" + ) +fi + +tool="" +if command -v zopflipng >/dev/null 2>&1; then + tool="zopflipng" +elif command -v pngcrush >/dev/null 2>&1; then + tool="pngcrush" +else + echo "WARNING: neither zopflipng nor pngcrush is installed — skipping PNG optimization." + echo " Install with: brew install zopfli pngcrush" + exit 0 +fi + +echo "optimize_goldens: using ${tool}" + +count=0 +saved=0 +for dir in "${DIRS[@]}"; do + if [ ! -d "$dir" ]; then + continue + fi + while IFS= read -r -d '' png; do + before=$(stat -f%z "$png" 2>/dev/null || stat -c%s "$png") + if [ "$tool" = "zopflipng" ]; then + # -y : overwrite without prompt + # --lossy_transparent : allow color rewrite under alpha=0 for extra savings + zopflipng -y --lossy_transparent "$png" "$png" >/dev/null 2>&1 || true + else + # -ow : overwrite-in-place; -q : quiet + pngcrush -q -ow "$png" >/dev/null 2>&1 || true + fi + after=$(stat -f%z "$png" 2>/dev/null || stat -c%s "$png") + saved=$((saved + before - after)) + count=$((count + 1)) + done < <(find "$dir" -name '*.png' -print0) +done + +if [ "$count" -eq 0 ]; then + echo "optimize_goldens: no PNGs found in: ${DIRS[*]}" + exit 0 +fi + +# Print a human-readable summary. `bc` is standard on macOS / most linuxes. +mb=$(echo "scale=2; $saved/1048576" | bc) +printf "optimize_goldens: %d PNGs processed, saved %.2f MB (%s)\n" "$count" "$mb" "$tool" diff --git a/scripts/record_snapshots.sh b/scripts/record_snapshots.sh new file mode 100755 index 0000000..e1f5793 --- /dev/null +++ b/scripts/record_snapshots.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# +# record_snapshots.sh — regenerate every parity-gallery golden in one pass. +# +# Use this after an intentional UI change (new color token, redesigned +# layout, etc.) so the committed baseline matches the new look. Reviewers +# see the PNG diff alongside your code change in the PR — that dual-diff +# is the whole point of the parity gallery. +# +# Usage +# ----- +# ./scripts/record_snapshots.sh # iOS + Android +# ./scripts/record_snapshots.sh --ios-only +# ./scripts/record_snapshots.sh --android-only +# +# Pipeline +# -------- +# 1. (Android) `./gradlew :composeApp:recordRoborazziDebug` +# 2. (iOS) Delete iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests, +# set SNAPSHOT_TESTING_RECORD=1, run xcodebuild test for +# SnapshotGalleryTests. The env var is read by +# SnapshotGalleryTests.swift to flip SnapshotTesting.record +# between `.missing` (default — safe) and `.all` (overwrite). +# 3. Run `scripts/optimize_goldens.sh` across both golden directories to +# shrink the fresh PNGs. +# +set -euo pipefail + +cd "$(dirname "$0")/.." +ROOT="$(pwd)" + +platform="both" +for arg in "$@"; do + case "$arg" in + --ios-only) platform="ios" ;; + --android-only) platform="android" ;; + -h|--help) + sed -n '3,18p' "$0" + exit 0 + ;; + *) + echo "usage: $0 [--ios-only|--android-only]" >&2 + exit 1 + ;; + esac +done + +# ---------- Android ---------- +if [ "$platform" = "both" ] || [ "$platform" = "android" ]; then + echo "==> Recording Android goldens…" + ./gradlew :composeApp:recordRoborazziDebug +fi + +# ---------- iOS ---------- +if [ "$platform" = "both" ] || [ "$platform" = "ios" ]; then + echo "==> Recording iOS goldens…" + rm -rf iosApp/HoneyDueTests/__Snapshots__/SnapshotGalleryTests + ( + cd iosApp + # SNAPSHOT_TESTING_RECORD=1 flips SnapshotTesting.isRecording to + # `.all` (see SnapshotGalleryTests.swift). + SNAPSHOT_TESTING_RECORD=1 xcodebuild test \ + -project honeyDue.xcodeproj \ + -scheme HoneyDue \ + -destination "${IOS_SIM_DESTINATION:-platform=iOS Simulator,name=iPhone 17,OS=latest}" \ + -only-testing:HoneyDueTests/SnapshotGalleryTests \ + 2>&1 | tail -30 + ) +fi + +# ---------- Optimize ---------- +echo "==> Optimizing PNGs…" +"$ROOT/scripts/optimize_goldens.sh" + +# ---------- Parity HTML (P4 follow-up) ---------- +if [ -x "$ROOT/scripts/build_parity_gallery.py" ]; then + echo "==> Regenerating parity HTML gallery…" + python3 "$ROOT/scripts/build_parity_gallery.py" +else + echo "==> (parity HTML generator not yet present — skipping)" +fi + +echo "==> Done. Review the PNG diff with your code change before committing." diff --git a/scripts/verify_snapshots.sh b/scripts/verify_snapshots.sh new file mode 100755 index 0000000..1fa6d6e --- /dev/null +++ b/scripts/verify_snapshots.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# +# verify_snapshots.sh — verify every parity-gallery golden matches the +# current code. Use as a pre-commit / CI gate. +# +# Exits non-zero if either platform's gallery drifts from its committed +# baseline. Diff artifacts land under each platform's usual report dir: +# Android: composeApp/build/outputs/roborazzi/ +# iOS: ~/Library/Developer/Xcode/DerivedData/.../HoneyDueTests/ +# +# Usage +# ----- +# ./scripts/verify_snapshots.sh # both platforms +# ./scripts/verify_snapshots.sh --ios-only +# ./scripts/verify_snapshots.sh --android-only +# +set -euo pipefail + +cd "$(dirname "$0")/.." + +platform="both" +for arg in "$@"; do + case "$arg" in + --ios-only) platform="ios" ;; + --android-only) platform="android" ;; + -h|--help) + sed -n '3,14p' "$0" + exit 0 + ;; + *) + echo "usage: $0 [--ios-only|--android-only]" >&2 + exit 1 + ;; + esac +done + +# ---------- Android ---------- +if [ "$platform" = "both" ] || [ "$platform" = "android" ]; then + echo "==> Verifying Android goldens…" + ./gradlew :composeApp:verifyRoborazziDebug +fi + +# ---------- iOS ---------- +if [ "$platform" = "both" ] || [ "$platform" = "ios" ]; then + echo "==> Verifying iOS goldens…" + ( + cd iosApp + xcodebuild test \ + -project honeyDue.xcodeproj \ + -scheme HoneyDue \ + -destination "${IOS_SIM_DESTINATION:-platform=iOS Simulator,name=iPhone 17,OS=latest}" \ + -only-testing:HoneyDueTests/SnapshotGalleryTests \ + 2>&1 | tail -30 + ) +fi + +echo "==> All snapshot checks passed."