diff --git a/Sources/SnapshotTesting/Common/View.swift b/Sources/SnapshotTesting/Common/View.swift index 111f6af29..f6d2dfe18 100644 --- a/Sources/SnapshotTesting/Common/View.swift +++ b/Sources/SnapshotTesting/Common/View.swift @@ -926,6 +926,48 @@ } } +//<<<<<<< HEAD +// if size.width == 0 || size.height == 0 { +// // Try to call sizeToFit() if the view still has invalid size +// view.sizeToFit() +// view.setNeedsLayout() +// view.layoutIfNeeded() +// } +// +// return dispose +//} +// +//func snapshotView( +// config: ViewImageConfig, +// drawHierarchyInKeyWindow: Bool, +// traits: UITraitCollection, +// view: UIView, +// viewController: UIViewController, +// delay: Double? = nil +// ) +// -> Async { +// let initialFrame = view.frame +// let dispose = prepareView( +// config: config, +// drawHierarchyInKeyWindow: drawHierarchyInKeyWindow, +// traits: traits, +// view: view, +// viewController: viewController +// ) +// // NB: Avoid safe area influence. +// if config.safeArea == .zero { view.frame.origin = .init(x: offscreen, y: offscreen) } +// +// return (view.snapshot ?? Async { callback in +// addImagesForRenderedViews(view).sequence().delay(by: delay).run { views in +// callback( +// renderer(bounds: view.bounds, for: traits).image { ctx in +// if drawHierarchyInKeyWindow { +// view.drawHierarchy(in: view.bounds, afterScreenUpdates: true) +// } else { +// view.layer.render(in: ctx.cgContext) +// } +// } +//======= func prepareView( config: ViewImageConfig, drawHierarchyInKeyWindow: Bool, @@ -970,7 +1012,8 @@ drawHierarchyInKeyWindow: Bool, traits: UITraitCollection, view: UIView, - viewController: UIViewController + viewController: UIViewController, + delay: Double? = nil ) -> Async { @@ -988,7 +1031,7 @@ return (view.snapshot ?? Async { callback in - addImagesForRenderedViews(view).sequence().run { views in + addImagesForRenderedViews(view).sequence().delay(by: delay).run { views in callback( renderer(bounds: view.bounds, for: traits).image { ctx in if drawHierarchyInKeyWindow { diff --git a/Sources/SnapshotTesting/Extensions/Async+Delay.swift b/Sources/SnapshotTesting/Extensions/Async+Delay.swift new file mode 100644 index 000000000..89f817a3f --- /dev/null +++ b/Sources/SnapshotTesting/Extensions/Async+Delay.swift @@ -0,0 +1,20 @@ +import Foundation + +extension Async { + /// Delays Async `run` block + /// - Parameter timeInterval: Optional duration for Async to wait before running `run` + /// - Returns: Delayed `Async` unless no duration was provided then returns original `Async` + func delay(by timeInterval: TimeInterval?) -> Async { + guard let timeInterval = timeInterval else { + return self + } + + return Async { callback in + run { value in + DispatchQueue.main.asyncAfter(deadline: .now() + timeInterval) { + callback(value) + } + } + } + } +} diff --git a/Sources/SnapshotTesting/Snapshotting/UIViewController.swift b/Sources/SnapshotTesting/Snapshotting/UIViewController.swift index b08b8bf59..27fbbc0e9 100644 --- a/Sources/SnapshotTesting/Snapshotting/UIViewController.swift +++ b/Sources/SnapshotTesting/Snapshotting/UIViewController.swift @@ -7,6 +7,7 @@ return .image() } + /// A snapshot strategy for comparing view controller views based on pixel equality. /// /// - Parameters: @@ -18,12 +19,14 @@ /// human eye. /// - size: A view size override. /// - traits: A trait collection override. + /// - delay: A time in seconds, for how long to wait before making snapshot public static func image( on config: ViewImageConfig, precision: Float = 1, perceptualPrecision: Float = 1, size: CGSize? = nil, - traits: UITraitCollection = .init() + traits: UITraitCollection = .init(), + delay: Double? = nil ) -> Snapshotting { @@ -37,7 +40,8 @@ drawHierarchyInKeyWindow: false, traits: traits, view: viewController.view, - viewController: viewController + viewController: viewController, + delay: delay ) } } diff --git a/Tests/SnapshotTestingTests/DelayTests.swift b/Tests/SnapshotTestingTests/DelayTests.swift new file mode 100644 index 000000000..3978df280 --- /dev/null +++ b/Tests/SnapshotTestingTests/DelayTests.swift @@ -0,0 +1,63 @@ +import XCTest +@testable import SnapshotTesting + +class DelayTests: XCTestCase { + func testDelayViewDidLoad() { + let sut = DelayedViewController() + + assertSnapshot(matching: sut, as: .image(on: .iPhone13, delay: 2)) + } + func testViewDidLoad() { + let sut = DelayedViewController() + + assertSnapshot(matching: sut, as: .image(on: .iPhone13)) + } + func testWaitViewDidLoad() { + let sut = DelayedViewController() + + assertSnapshot(matching: sut, as: .wait(for: 2, on: .image(on: .iPhone13))) + } +} + +private final class DelayedViewController: UIViewController { + + private lazy var topLabel = UILabel() + private lazy var bottomLabel = UILabel() + + override func viewDidLoad() { + super.viewDidLoad() + + setupUI() + + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + self.topLabel.text = "Goodbye viewDidLoad" + } + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + self.bottomLabel.text = "Goodbye viewDidAppear" + } + } + + private func setupUI() { + view.backgroundColor = .white + + topLabel.text = "Hello viewDidLoad" + bottomLabel.text = "Hello viewDidAppear" + topLabel.translatesAutoresizingMaskIntoConstraints = false + bottomLabel.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(topLabel) + view.addSubview(bottomLabel) + + NSLayoutConstraint.activate([ + topLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), + topLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor), + bottomLabel.topAnchor.constraint(equalTo: topLabel.bottomAnchor), + bottomLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor) + ]) + } +} diff --git a/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testDelayViewDidLoad.1.png b/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testDelayViewDidLoad.1.png new file mode 100644 index 000000000..4264f3509 Binary files /dev/null and b/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testDelayViewDidLoad.1.png differ diff --git a/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testViewDidLoad.1.png b/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testViewDidLoad.1.png new file mode 100644 index 000000000..533664f86 Binary files /dev/null and b/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testViewDidLoad.1.png differ diff --git a/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testWaitViewDidLoad.1.png b/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testWaitViewDidLoad.1.png new file mode 100644 index 000000000..533664f86 Binary files /dev/null and b/Tests/SnapshotTestingTests/__Snapshots__/DelayTests/testWaitViewDidLoad.1.png differ