|
| 1 | +// |
| 2 | +// SwiftUIView.swift |
| 3 | +// |
| 4 | +// Created by Emanuel Cunha on 20/05/2023 |
| 5 | +// |
| 6 | + |
| 7 | +#if canImport(SwiftUI) |
| 8 | +import Foundation |
| 9 | +import SwiftUI |
| 10 | +@testable import SnapshotTesting |
| 11 | + |
| 12 | +#if os(iOS) || os(tvOS) |
| 13 | +@available(iOS 13.0, tvOS 13.0, *) |
| 14 | +public extension Snapshotting where Value: SwiftUI.View, Format == UIImage { |
| 15 | + |
| 16 | + /// A snapshot strategy for comparing views based on pixel equality. |
| 17 | + static var imageHEIC: Snapshotting { |
| 18 | + return .imageHEIC() |
| 19 | + } |
| 20 | + |
| 21 | + /// A snapshot strategy for comparing SwiftUI Views based on pixel equality. |
| 22 | + /// |
| 23 | + /// - Parameters: |
| 24 | + /// - drawHierarchyInKeyWindow: Utilize the simulator's key window in order to render `UIAppearance` and `UIVisualEffect`s. This option requires a host application for your tests and will _not_ work for framework test targets. |
| 25 | + /// - precision: The percentage of pixels that must match. |
| 26 | + /// - perceptualPrecision: The percentage a pixel must match the source pixel to be considered a match. [98-99% mimics the precision of the human eye.](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) |
| 27 | + /// - layout: A view layout override. |
| 28 | + /// - traits: A trait collection override. |
| 29 | + /// - compressionQuality: The desired compression quality to use when writing to an image destination. |
| 30 | + static func imageHEIC( |
| 31 | + drawHierarchyInKeyWindow: Bool = false, |
| 32 | + precision: Float = 1, |
| 33 | + perceptualPrecision: Float = 1, |
| 34 | + layout: SwiftUISnapshotLayout = .sizeThatFits, |
| 35 | + traits: UITraitCollection = .init(), |
| 36 | + compressionQuality: CompressionQuality = .lossless |
| 37 | + ) -> Snapshotting { |
| 38 | + let config: ViewImageConfig |
| 39 | + |
| 40 | + switch layout { |
| 41 | +#if os(iOS) || os(tvOS) |
| 42 | + case let .device(config: deviceConfig): |
| 43 | + config = deviceConfig |
| 44 | +#endif |
| 45 | + case .sizeThatFits: |
| 46 | + config = .init(safeArea: .zero, size: nil, traits: traits) |
| 47 | + case let .fixed(width: width, height: height): |
| 48 | + let size = CGSize(width: width, height: height) |
| 49 | + config = .init(safeArea: .zero, size: size, traits: traits) |
| 50 | + } |
| 51 | + |
| 52 | + return SimplySnapshotting.imageHEIC( |
| 53 | + precision: precision, |
| 54 | + perceptualPrecision: perceptualPrecision, |
| 55 | + scale: traits.displayScale, |
| 56 | + compressionQuality: compressionQuality |
| 57 | + ).asyncPullback { view in |
| 58 | + var config = config |
| 59 | + |
| 60 | + let controller: UIViewController |
| 61 | + |
| 62 | + if config.size != nil { |
| 63 | + controller = UIHostingController.init( |
| 64 | + rootView: view |
| 65 | + ) |
| 66 | + } else { |
| 67 | + let hostingController = UIHostingController.init(rootView: view) |
| 68 | + |
| 69 | + let maxSize = CGSize(width: 0.0, height: 0.0) |
| 70 | + config.size = hostingController.sizeThatFits(in: maxSize) |
| 71 | + |
| 72 | + controller = hostingController |
| 73 | + } |
| 74 | + |
| 75 | + return snapshotView( |
| 76 | + config: config.size.map { .init(safeArea: config.safeArea, size: $0, traits: config.traits) } ?? config, |
| 77 | + drawHierarchyInKeyWindow: false, |
| 78 | + traits: traits, |
| 79 | + view: controller.view, |
| 80 | + viewController: controller |
| 81 | + ) |
| 82 | + } |
| 83 | + } |
| 84 | +} |
| 85 | +#endif |
| 86 | +#endif |
0 commit comments