forked from pointfreeco/swift-snapshot-testing
/
SwiftUIView.swift
85 lines (74 loc) 路 2.97 KB
/
SwiftUIView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#if canImport(SwiftUI)
import Foundation
import SwiftUI
/// The size constraint for a snapshot (similar to `PreviewLayout`).
public enum SwiftUISnapshotLayout {
#if os(iOS) || os(tvOS)
/// Center the view in a device container described by`config`.
case device(config: ViewImageConfig)
#endif
/// Center the view in a fixed size container.
case fixed(width: CGFloat, height: CGFloat)
/// Fit the view to the ideal size that fits its content.
case sizeThatFits
}
#if os(iOS) || os(tvOS)
@available(iOS 13.0, tvOS 13.0, *)
extension Snapshotting where Value: SwiftUI.View, Format == UIImage {
/// A snapshot strategy for comparing SwiftUI Views based on pixel equality.
public static var image: Snapshotting {
return .image()
}
/// A snapshot strategy for comparing SwiftUI Views based on pixel equality.
///
/// - Parameters:
/// - 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.
/// - precision: The percentage of pixels that must match.
/// - 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)
/// - layout: A view layout override.
/// - traits: A trait collection override.
public static func image(
drawHierarchyInKeyWindow: Bool = false,
precision: Float = 1,
perceptualPrecision: Float = 1,
layout: SwiftUISnapshotLayout = .sizeThatFits,
traits: UITraitCollection = .init()
)
-> Snapshotting {
let config: ViewImageConfig
switch layout {
#if os(iOS) || os(tvOS)
case let .device(config: deviceConfig):
config = deviceConfig
#endif
case .sizeThatFits:
config = .init(safeArea: .zero, size: nil, traits: traits)
case let .fixed(width: width, height: height):
let size = CGSize(width: width, height: height)
config = .init(safeArea: .zero, size: size, traits: traits)
}
return SimplySnapshotting.image(precision: precision, perceptualPrecision: perceptualPrecision, scale: traits.displayScale).asyncPullback { view in
var config = config
let controller: UIViewController
if config.size != nil {
controller = UIHostingController.init(
rootView: view
)
} else {
let hostingController = UIHostingController.init(rootView: view)
let maxSize = CGSize(width: 0.0, height: 0.0)
config.size = hostingController.sizeThatFits(in: maxSize)
controller = hostingController
}
return snapshotView(
config: config,
drawHierarchyInKeyWindow: drawHierarchyInKeyWindow,
traits: traits,
view: controller.view,
viewController: controller
)
}
}
}
#endif
#endif