-
Notifications
You must be signed in to change notification settings - Fork 629
SnapshotTesting 2.0 #1003
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
SnapshotTesting 2.0 #1003
Conversation
Status Update✅ Recent Successes
📋 Remaining Tasks
|
- macOS 15.5 - iPhone 16 - OS 18.5 - Apple Watch Series 10 (46mm) - watchOS 11.5 - visionOS 2.5 - Apple TV 4K (3rd generation) - tvOS 18.5 - iPad Pro 13-inc (M4) - iPadOS 18.5
📦 Wrapping Up Contribution I’m wrapping up my contribution to this PR. The pending items related to documentation (.docc) and the migration guide were not included in this delivery. If there’s interest, I’d be happy to continue that work in a separate PR — since it involves multiple steps and decisions about structure and format, I believe that would make more sense. For now, I consider the inline code documentation to be sufficient in covering the main concepts. ✅ Testing and Compatibility I compiled and ran tests on the following platforms and devices:
🙏 Appreciation I’ve learned a lot over the past few months and I’m really glad I had the opportunity to contribute. Thank you for the space, patience, and feedback. I hope to collaborate more with the library in the future. I completely understand if this PR doesn’t move forward given its scope. Still, I’m available to evolve whatever is necessary. Thank you so much! 🙌 |
@stephencelis @mbrandonw, this is ready for review! 👀 |
This is a preview of what I've been working on over the past few months.
It all started with #760, #742 and #973. I began by testing the proposed solution but soon realized it didn’t fully address my needs. There were, in fact, two key problems:
UIWindow
.wait
, there was no guarantee views were fully rendered before snapshots were taken.Solving the First Problem: Delay Support
Adding delays programmatically can be done in multiple ways, but the existing SnapshotTesting architecture made it difficult to inject delays mid-flow. To resolve this, I restructured the core logic of the
Snapshotting
API, inspired by Swift’s functional programming paradigms.I split the
Async
type into two distinct components:Sync
: For synchronous operations within the same execution context.Async
: For asynchronous workflows using Swift’sasync/await
.Building on functional pipelines (input → processing → output), I redesigned
Snapshotting
to enforce a clear transformation chain:Each step in this pipeline processes input and passes the result to the next, enabling modular and composable snapshot logic.
Solving the Second Problem: Reliable View Rendering
This challenge required deeper exploration of UIKit’s lifecycle. The existing
UIWindow
initialization (init()
) was outdated—though not officially deprecated—since the introduction ofUISceneDelegate
. To ensure compatibility with both UIKit and SwiftUI, I updated the implementation to useUIWindow(windowScene:)
.This change resolved rendering inconsistencies, particularly for
UINavigationController
andNavigationStack
. Additionally, I discovered that relying onkeyWindow
(now deprecated) was unnecessary, as the new approach works seamlessly with or without scene delegate support.Key Improvements & Learnings
async/await
,Sendable
, and Swift Package Manager (SPM) compatibility.SnapshotTesting
: Adapters for integrating with Swift’s new Testing framework.XCSnapshotTesting
: Core snapshot logic (e.g., rendering pipelines, environment configuration).XC...
naming convention, this layer ensures compatibility with Swift Testing’s test runner.SnapshotEnvironment
andSnapshotEnvironmentKey
to pass contextual parameters (e.g., delays, platform-specific configs).@available
) to ease migration.Remaining Tasks
UIWindow
sizing requirements.Final Notes
This PR is a draft, and I welcome feedback or suggestions. Given the scope of the refactoring, I completely understand if the project maintainers decide not to merge it.
What began as an attempt to fix a delay issue evolved into a complete overhaul. Regardless of the outcome, I’m deeply grateful to the community for the foundation and the opportunity to contribute over these months.
Thank you for your time and consideration! 🙏
P.S. Contributions to address the remaining tasks are highly encouraged!