Prefire basic implementation (#1743)

* prefire basic implementation

force the unit tests to run on iPhone 14

skipping plugin validation

archive artifacts

better workflow

removed the OS restriction

lfs

custom stencil

new test file

deleting

* git lfs

* lfs

* test

* customised the stencil to support our internal protocol

* for now we can remove the OS check from the stencil

* added a delay

* tests have been moved

* improvement

* recommit

* perceptual precision lowered

* updated snapshot testing and selected also iOS version

* added ios version control
This commit is contained in:
Mauro
2023-09-20 14:07:18 +02:00
committed by GitHub
parent faad37c803
commit 341b177e23
20 changed files with 509 additions and 16 deletions
+173
View File
@@ -0,0 +1,173 @@
// Generated using Sourcery 2.0.1 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all
// swiftformat:disable all
import XCTest
import SwiftUI
import Prefire
@testable import SnapshotTesting
#if canImport(AccessibilitySnapshot)
import AccessibilitySnapshot
#endif
@testable import ElementX
class PreviewTests: XCTestCase {
private let deviceConfig: ViewImageConfig = .iPhoneX
private let simulatorDevice = "iPhone14"
private let requiredOSVersion = 16
override func setUp() {
super.setUp()
checkEnvironments()
UIView.setAnimationsEnabled(false)
}
func test_timelineItemStyler() {
for preview in TimelineItemStyler_Previews._allPreviews {
assertSnapshots(matching: preview)
}
}
// MARK: Private
private func assertSnapshots(matching preview: _Preview, testName: String = #function) {
let isScreen = preview.layout == .device
let device = preview.device?.snapshotDevice() ?? deviceConfig
var delay: TimeInterval = 1.0
var precision: Float = 0.99
let view = preview.content
.onPreferenceChange(DelayPreferenceKey.self) { delay = $0 }
.onPreferenceChange(PrecisionPreferenceKey.self) { precision = $0 }
let matchingView = isScreen ? AnyView(view) : AnyView(view
.frame(width: device.size?.width)
.fixedSize(horizontal: false, vertical: true)
)
assertSnapshot(
matching: matchingView,
as: .prefireImage(precision: { precision }, duration: { delay }, layout: isScreen ? .device(config: device) : .sizeThatFits),
named: preview.displayName,
testName: testName
)
#if canImport(AccessibilitySnapshot)
let vc = UIHostingController(rootView: matchingView)
vc.view.frame = UIScreen.main.bounds
assertSnapshot(
matching: vc,
as: .wait(for: delay, on: .accessibilityImage(showActivationPoints: .always)),
named: preview.displayName.map { $0 + ".accessibility" },
testName: testName
)
#endif
}
/// Check environments to avoid problems with snapshots on different devices or OS.
private func checkEnvironments() {
let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]
let osVersion = ProcessInfo().operatingSystemVersion
guard deviceModel?.contains(simulatorDevice) ?? false else {
fatalError("Switch to using \(simulatorDevice) for these tests.")
}
guard osVersion.majorVersion == requiredOSVersion else {
fatalError("Switch to iOS \(requiredOSVersion) for these tests.")
}
}
}
// MARK: - SnapshotTesting + Extensions
private extension PreviewDevice {
func snapshotDevice() -> ViewImageConfig? {
switch rawValue {
case "iPhone 14", "iPhone 13", "iPhone 12", "iPhone 11", "iPhone 10":
return .iPhoneX
case "iPhone 6", "iPhone 6s", "iPhone 7", "iPhone 8":
return .iPhone8
case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 8 Plus":
return .iPhone8Plus
case "iPhone SE (1st generation)", "iPhone SE (2nd generation)":
return .iPhoneSe
default: return nil
}
}
}
private extension Snapshotting where Value: SwiftUI.View, Format == UIImage {
static func prefireImage(
drawHierarchyInKeyWindow: Bool = false,
precision: @escaping () -> Float,
duration: @escaping () -> TimeInterval,
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<UIImage>(pathExtension: "png", diffing: .prefireImage(precision: precision, scale: traits.displayScale))
.asyncPullback { view in
var config = config
let controller: UIViewController
if config.size != nil {
controller = UIHostingController(rootView: view)
} else {
let hostingController = UIHostingController(rootView: view)
let maxSize = CGSize.zero
config.size = hostingController.sizeThatFits(in: maxSize)
controller = hostingController
}
return Async<UIImage> { callback in
let strategy = snapshotView(
config: config,
drawHierarchyInKeyWindow: drawHierarchyInKeyWindow,
traits: traits,
view: controller.view,
viewController: controller
)
let duration = duration()
if duration != .zero {
let expectation = XCTestExpectation(description: "Wait")
DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
expectation.fulfill()
}
_ = XCTWaiter.wait(for: [expectation], timeout: duration + 1)
}
strategy.run(callback)
}
}
}
}
private extension Diffing where Value == UIImage {
static func prefireImage(precision: @escaping () -> Float, scale: CGFloat?) -> Diffing {
lazy var originalDiffing = Diffing.image(precision: precision(), perceptualPrecision: 0.98, scale: scale)
return Diffing(
toData: { originalDiffing.toData($0) },
fromData: { originalDiffing.fromData($0) },
diff: { originalDiffing.diff($0, $1) }
)
}
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c935c6529a9f9a63915c3cab80dc9fc7df8723db6258c4d8c445df7c84296e65
size 110159
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ebec20c376958c8a4b10a4055f15963a27ed744e0ac594aae803b0e56c6477a2
size 108424
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7f84bcc4acb59ef1a6fb5893b0840b32e3011e6a1e66004b65650ab30321b7f8
size 97748
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b2f89b01650704e45b0c9a57c67f7fbe4cf583299b6d0392b4d79c22725a3f7
size 132101
+7
View File
@@ -28,9 +28,14 @@ targets:
UnitTests:
type: bundle.unit-test
platform: iOS
buildToolPlugins:
- plugin: PrefireTestsPlugin
package: Prefire
dependencies:
- target: ElementX
- package: SnapshotTesting
info:
path: ../SupportingFiles/Info.plist
@@ -44,6 +49,8 @@ targets:
sources:
- path: ../Sources
excludes:
- "**/__Snapshots__/**"
- path: ../SupportingFiles
- path: ../../ElementX/Sources/Other/InfoPlistReader.swift
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/Unit