diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..f89b663 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..197702b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**/__Snapshots__/**/*.png \ No newline at end of file diff --git a/.prefire.yml b/.prefire.yml new file mode 100644 index 0000000..9608991 --- /dev/null +++ b/.prefire.yml @@ -0,0 +1,2 @@ +test_configuration: + template_file_path: custom_template.stencil \ No newline at end of file diff --git a/DesignSystem/.swiftpm/xcode/xcuserdata/rodrigofernandez.xcuserdatad/xcschemes/xcschememanagement.plist b/DesignSystem/.swiftpm/xcode/xcuserdata/rodrigofernandez.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..431e5ba --- /dev/null +++ b/DesignSystem/.swiftpm/xcode/xcuserdata/rodrigofernandez.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + DesignSystem.xcscheme_^#shared#^_ + + orderHint + 1 + + + + diff --git a/SampleWorkshopApp.xcodeproj/project.pbxproj b/SampleWorkshopApp.xcodeproj/project.pbxproj index 2bbd500..5723088 100644 --- a/SampleWorkshopApp.xcodeproj/project.pbxproj +++ b/SampleWorkshopApp.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 7ED0894B2F3B50BC0009DAB3 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 7ED0894A2F3B50BC0009DAB3 /* SnapshotTesting */; }; + 7ED089512F3B531E0009DAB3 /* Prefire in Frameworks */ = {isa = PBXBuildFile; productRef = 7ED089502F3B531E0009DAB3 /* Prefire */; }; + 7ED089712F3B5AE00009DAB3 /* Prefire in Frameworks */ = {isa = PBXBuildFile; productRef = 7ED089702F3B5AE00009DAB3 /* Prefire */; }; A74FDA202F3A2674000A32F5 /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = A74FDA212F3A2674000A32F5 /* DesignSystem */; }; /* End PBXBuildFile section */ @@ -18,19 +21,11 @@ remoteGlobalIDString = A74FD9E82F3A2672000A32F5; remoteInfo = SampleWorkshopApp; }; - A74FDA012F3A2673000A32F5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = A74FD9E12F3A2672000A32F5 /* Project object */; - proxyType = 1; - remoteGlobalIDString = A74FD9E82F3A2672000A32F5; - remoteInfo = SampleWorkshopApp; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ A74FD9E92F3A2672000A32F5 /* SampleWorkshopApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleWorkshopApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; A74FD9F62F3A2673000A32F5 /* SampleWorkshopAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleWorkshopAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - A74FDA002F3A2673000A32F5 /* SampleWorkshopAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleWorkshopAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ @@ -56,6 +51,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7ED089712F3B5AE00009DAB3 /* Prefire in Frameworks */, A74FDA202F3A2674000A32F5 /* DesignSystem in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -64,25 +60,28 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A74FD9FD2F3A2673000A32F5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( + 7ED089512F3B531E0009DAB3 /* Prefire in Frameworks */, + 7ED0894B2F3B50BC0009DAB3 /* SnapshotTesting in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 7ED0894F2F3B531E0009DAB3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; A74FD9E02F3A2672000A32F5 = { isa = PBXGroup; children = ( A74FD9EB2F3A2672000A32F5 /* SampleWorkshopApp */, A74FD9F92F3A2673000A32F5 /* SampleWorkshopAppTests */, A74FDA032F3A2673000A32F5 /* SampleWorkshopAppUITests */, + 7ED0894F2F3B531E0009DAB3 /* Frameworks */, A74FD9EA2F3A2672000A32F5 /* Products */, ); sourceTree = ""; @@ -92,7 +91,6 @@ children = ( A74FD9E92F3A2672000A32F5 /* SampleWorkshopApp.app */, A74FD9F62F3A2673000A32F5 /* SampleWorkshopAppTests.xctest */, - A74FDA002F3A2673000A32F5 /* SampleWorkshopAppUITests.xctest */, ); name = Products; sourceTree = ""; @@ -118,6 +116,7 @@ name = SampleWorkshopApp; packageProductDependencies = ( A74FDA212F3A2674000A32F5 /* DesignSystem */, + 7ED089702F3B5AE00009DAB3 /* Prefire */, ); productName = SampleWorkshopApp; productReference = A74FD9E92F3A2672000A32F5 /* SampleWorkshopApp.app */; @@ -134,6 +133,7 @@ buildRules = ( ); dependencies = ( + 7ED0894E2F3B52EE0009DAB3 /* PBXTargetDependency */, A74FD9F82F3A2673000A32F5 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( @@ -141,34 +141,13 @@ ); name = SampleWorkshopAppTests; packageProductDependencies = ( + 7ED0894A2F3B50BC0009DAB3 /* SnapshotTesting */, + 7ED089502F3B531E0009DAB3 /* Prefire */, ); productName = SampleWorkshopAppTests; productReference = A74FD9F62F3A2673000A32F5 /* SampleWorkshopAppTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - A74FD9FF2F3A2673000A32F5 /* SampleWorkshopAppUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = A74FDA102F3A2673000A32F5 /* Build configuration list for PBXNativeTarget "SampleWorkshopAppUITests" */; - buildPhases = ( - A74FD9FC2F3A2673000A32F5 /* Sources */, - A74FD9FD2F3A2673000A32F5 /* Frameworks */, - A74FD9FE2F3A2673000A32F5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - A74FDA022F3A2673000A32F5 /* PBXTargetDependency */, - ); - fileSystemSynchronizedGroups = ( - A74FDA032F3A2673000A32F5 /* SampleWorkshopAppUITests */, - ); - name = SampleWorkshopAppUITests; - packageProductDependencies = ( - ); - productName = SampleWorkshopAppUITests; - productReference = A74FDA002F3A2673000A32F5 /* SampleWorkshopAppUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -186,10 +165,6 @@ CreatedOnToolsVersion = 16.4; TestTargetID = A74FD9E82F3A2672000A32F5; }; - A74FD9FF2F3A2673000A32F5 = { - CreatedOnToolsVersion = 16.4; - TestTargetID = A74FD9E82F3A2672000A32F5; - }; }; }; buildConfigurationList = A74FD9E42F3A2672000A32F5 /* Build configuration list for PBXProject "SampleWorkshopApp" */; @@ -203,6 +178,8 @@ minimizedProjectReferenceProxies = 1; packageReferences = ( A74FDA222F3A2674000A32F5 /* XCLocalSwiftPackageReference "DesignSystem" */, + 7ED089492F3B50BC0009DAB3 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */, + 7ED0894C2F3B52DA0009DAB3 /* XCRemoteSwiftPackageReference "Prefire" */, ); preferredProjectObjectVersion = 77; productRefGroup = A74FD9EA2F3A2672000A32F5 /* Products */; @@ -211,7 +188,6 @@ targets = ( A74FD9E82F3A2672000A32F5 /* SampleWorkshopApp */, A74FD9F52F3A2673000A32F5 /* SampleWorkshopAppTests */, - A74FD9FF2F3A2673000A32F5 /* SampleWorkshopAppUITests */, ); }; /* End PBXProject section */ @@ -231,13 +207,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - A74FD9FE2F3A2673000A32F5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -255,25 +224,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - A74FD9FC2F3A2673000A32F5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - A74FD9F82F3A2673000A32F5 /* PBXTargetDependency */ = { + 7ED0894E2F3B52EE0009DAB3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = A74FD9E82F3A2672000A32F5 /* SampleWorkshopApp */; - targetProxy = A74FD9F72F3A2673000A32F5 /* PBXContainerItemProxy */; + productRef = 7ED0894D2F3B52EE0009DAB3 /* PrefireTestsPlugin */; }; - A74FDA022F3A2673000A32F5 /* PBXTargetDependency */ = { + A74FD9F82F3A2673000A32F5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = A74FD9E82F3A2672000A32F5 /* SampleWorkshopApp */; - targetProxy = A74FDA012F3A2673000A32F5 /* PBXContainerItemProxy */; + targetProxy = A74FD9F72F3A2673000A32F5 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -487,38 +448,6 @@ }; name = Release; }; - A74FDA112F3A2673000A32F5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.SampleWorkshopAppUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = SampleWorkshopApp; - }; - name = Debug; - }; - A74FDA122F3A2673000A32F5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.SampleWorkshopAppUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = SampleWorkshopApp; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -549,15 +478,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - A74FDA102F3A2673000A32F5 /* Build configuration list for PBXNativeTarget "SampleWorkshopAppUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A74FDA112F3A2673000A32F5 /* Debug */, - A74FDA122F3A2673000A32F5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ @@ -567,7 +487,46 @@ }; /* End XCLocalSwiftPackageReference section */ +/* Begin XCRemoteSwiftPackageReference section */ + 7ED089492F3B50BC0009DAB3 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/tdrhq/swift-snapshot-testing"; + requirement = { + kind = exactVersion; + version = "1.18.6-sb"; + }; + }; + 7ED0894C2F3B52DA0009DAB3 /* XCRemoteSwiftPackageReference "Prefire" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/BarredEwe/Prefire.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.4.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + /* Begin XCSwiftPackageProductDependency section */ + 7ED0894A2F3B50BC0009DAB3 /* SnapshotTesting */ = { + isa = XCSwiftPackageProductDependency; + package = 7ED089492F3B50BC0009DAB3 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */; + productName = SnapshotTesting; + }; + 7ED0894D2F3B52EE0009DAB3 /* PrefireTestsPlugin */ = { + isa = XCSwiftPackageProductDependency; + package = 7ED0894C2F3B52DA0009DAB3 /* XCRemoteSwiftPackageReference "Prefire" */; + productName = "plugin:PrefireTestsPlugin"; + }; + 7ED089502F3B531E0009DAB3 /* Prefire */ = { + isa = XCSwiftPackageProductDependency; + package = 7ED0894C2F3B52DA0009DAB3 /* XCRemoteSwiftPackageReference "Prefire" */; + productName = Prefire; + }; + 7ED089702F3B5AE00009DAB3 /* Prefire */ = { + isa = XCSwiftPackageProductDependency; + package = 7ED0894C2F3B52DA0009DAB3 /* XCRemoteSwiftPackageReference "Prefire" */; + productName = Prefire; + }; A74FDA212F3A2674000A32F5 /* DesignSystem */ = { isa = XCSwiftPackageProductDependency; productName = DesignSystem; diff --git a/SampleWorkshopApp.xcodeproj/project.xcworkspace/xcuserdata/rodrigofernandez.xcuserdatad/UserInterfaceState.xcuserstate b/SampleWorkshopApp.xcodeproj/project.xcworkspace/xcuserdata/rodrigofernandez.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..557d604 Binary files /dev/null and b/SampleWorkshopApp.xcodeproj/project.xcworkspace/xcuserdata/rodrigofernandez.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/SampleWorkshopApp.xcodeproj/xcuserdata/rodrigofernandez.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/SampleWorkshopApp.xcodeproj/xcuserdata/rodrigofernandez.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..053c4f2 --- /dev/null +++ b/SampleWorkshopApp.xcodeproj/xcuserdata/rodrigofernandez.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/SampleWorkshopApp.xcodeproj/xcuserdata/rodrigofernandez.xcuserdatad/xcschemes/xcschememanagement.plist b/SampleWorkshopApp.xcodeproj/xcuserdata/rodrigofernandez.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..5f612eb --- /dev/null +++ b/SampleWorkshopApp.xcodeproj/xcuserdata/rodrigofernandez.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + SampleWorkshopApp.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/SampleWorkshopApp/AboutView.swift b/SampleWorkshopApp/AboutView.swift index 787fd83..026a85f 100644 --- a/SampleWorkshopApp/AboutView.swift +++ b/SampleWorkshopApp/AboutView.swift @@ -78,14 +78,14 @@ struct AboutView: View { } } -#Preview("Light") { +#Preview("About_Light") { NavigationStack { AboutView() } .preferredColorScheme(.light) } -#Preview("Dark") { +#Preview("About_Dark") { NavigationStack { AboutView() } diff --git a/SampleWorkshopApp/SupportChatView.swift b/SampleWorkshopApp/SupportChatView.swift index cff5488..09d1b3f 100644 --- a/SampleWorkshopApp/SupportChatView.swift +++ b/SampleWorkshopApp/SupportChatView.swift @@ -7,6 +7,7 @@ import SwiftUI import DesignSystem +import Prefire struct ChatMessage: Identifiable { let id = UUID() @@ -101,12 +102,14 @@ extension SupportChatView { ] } -#Preview("Light") { +#Preview("SupportChatView_Light") { SupportChatView(messages: SupportChatView.sampleMessages) .preferredColorScheme(.light) + .prefireIgnored() } -#Preview("Dark") { +#Preview("SupportChatView_Dark") { SupportChatView(messages: SupportChatView.sampleMessages) .preferredColorScheme(.dark) + .prefireIgnored() } diff --git a/SampleWorkshopAppTests/custom_template.stencil b/SampleWorkshopAppTests/custom_template.stencil new file mode 100644 index 0000000..9207ccd --- /dev/null +++ b/SampleWorkshopAppTests/custom_template.stencil @@ -0,0 +1,210 @@ +// swiftlint:disable all +// swiftformat:disable all + +import XCTest +import SwiftUI +import Prefire +{% for import in argument.imports %} +import {{ import }} +{% endfor %} +{% if argument.mainTarget %} +@testable import {{ argument.mainTarget }} +{% endif %} +{% for import in argument.testableImports %} +@testable import {{ import }} +{% endfor %} +import SnapshotTesting +#if canImport(AccessibilitySnapshot) + import AccessibilitySnapshot +#endif + +@MainActor class {PREVIEW_FILE_NAME}Tests: XCTestCase, Sendable { + private var simulatorDevice: String?{% if argument.simulatorDevice %} = "{{ argument.simulatorDevice|default:nil }}"{% endif %} + private var requiredOSVersion: Int?{% if argument.simulatorOSVersion %} = {{ argument.simulatorOSVersion }}{% endif %} + private let snapshotDevices: [String]{% if argument.snapshotDevices %} = {{ argument.snapshotDevices|split:"|" }}{% else %} = []{% endif %} +#if os(iOS) + private let deviceConfig: DeviceConfig = ViewImageConfig.iPhoneX.deviceConfig +#elseif os(tvOS) + private let deviceConfig: DeviceConfig = ViewImageConfig.tv.deviceConfig +#endif + + + {% if argument.file %} + + private var file: StaticString { .init(stringLiteral: "{{ argument.file }}") } + {% endif %} + + @MainActor override func setUp() async throws { + try await super.setUp() + + checkEnvironments() + UIView.setAnimationsEnabled(false) + } + + // MARK: - PreviewProvider + + {% for type in types.types where type.implements.PrefireProvider or type.based.PrefireProvider or type|annotated:"PrefireProvider" %} + func test_{{ type.name|lowerFirstLetter|replace:"_Previews", "" }}() { + for preview in {{ type.name }}._allPreviews { + assertSnapshots(for: PrefireSnapshot(preview, device: preview.device?.snapshotDevice() ?? deviceConfig)) + } + } + {%- if not forloop.last %} + + {% endif %} + {% endfor %} + {% if argument.previewsMacrosDict %} + // MARK: - Macros + + {% for macroModel in argument.previewsMacrosDict %} + func test_{{ macroModel.componentTestName }}_Preview() { + {% if macroModel.properties %} + struct PreviewWrapper{{ macroModel.componentTestName }}: SwiftUI.View { + {{ macroModel.properties }} + var body: some View { + {{ macroModel.body|indent:12 }} + } + } + let preview = PreviewWrapper{{ macroModel.componentTestName }}.init + {% else %} + let preview = { + {{ macroModel.body|indent:8 }} + } + {% endif %} + {% if macroModel.isScreen == 1 %} + let isScreen = true + {% else %} + let isScreen = false + {% endif %} + assertSnapshots(for: PrefireSnapshot(preview, name: "{{ macroModel.displayName }}", isScreen: isScreen, device: deviceConfig)) + } + {%- if not forloop.last %} + + {% endif %} + {% endfor %} + {% endif %} + // MARK: Private + + private func assertSnapshots(for prefireSnapshot: PrefireSnapshot) -> String? { + guard !snapshotDevices.isEmpty else { + return assertSnapshot(for: prefireSnapshot) + } + + for deviceName in snapshotDevices { + var snapshot = prefireSnapshot + guard let device: DeviceConfig = PreviewDevice(rawValue: deviceName).snapshotDevice() else { + fatalError("Unknown device name from configuration file: \(deviceName)") + } + + snapshot.name = "\(prefireSnapshot.name)-\(deviceName)" + snapshot.device = device + + // Ignore specific device safe area + snapshot.device.safeArea = .zero + + // Ignore specific device display scale + snapshot.traits = UITraitCollection(displayScale: 2.0) + + assertSnapshot(for: snapshot) + } + + return nil + } + + private func assertSnapshot(for prefireSnapshot: PrefireSnapshot) -> String? { + let (previewView, preferences) = prefireSnapshot.loadViewWithPreferences() + + let failure = verifySnapshot( + of: previewView, + as: .wait( + for: preferences.delay, + on: .image( + precision: preferences.precision, + perceptualPrecision: preferences.perceptualPrecision, + layout: prefireSnapshot.isScreen ? .device(config: prefireSnapshot.device.imageConfig) : .sizeThatFits, + traits: prefireSnapshot.traits + ) + ), + record: preferences.record{% if argument.file %}, + file: file{% endif %}, + testName: prefireSnapshot.name + ) + + #if canImport(AccessibilitySnapshot) + let vc = UIHostingController(rootView: previewView) + vc.view.frame = UIScreen.main.bounds + + SnapshotTesting.assertSnapshot( + matching: vc, + as: .wait(for: preferences.delay, on: .accessibilityImage(showActivationPoints: .always)){% if argument.file %}, + record: preferences.record, + file: file{% endif %}, + testName: prefireSnapshot.name + ".accessibility" + ) + #endif + return failure + } + + /// Check environments to avoid problems with snapshots on different devices or OS. + private func checkEnvironments() { + if let simulatorDevice, let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { + guard deviceModel.contains(simulatorDevice) else { + fatalError("Switch to using \(simulatorDevice) for these tests. (You are using \(deviceModel))") + } + } + + if let requiredOSVersion { + let osVersion = ProcessInfo().operatingSystemVersion + guard osVersion.majorVersion == requiredOSVersion else { + fatalError("Switch to iOS \(requiredOSVersion) for these tests. (You are using \(osVersion))") + } + } + } +} + +// MARK: - SnapshotTesting + Extensions + +private extension DeviceConfig { + var imageConfig: ViewImageConfig { ViewImageConfig(safeArea: safeArea, size: size, traits: traits) } +} + +private extension ViewImageConfig { + var deviceConfig: DeviceConfig { DeviceConfig(safeArea: safeArea, size: size, traits: traits) } +} + +private extension PreviewDevice { + func snapshotDevice() -> ViewImageConfig? { + switch rawValue { + #if os(iOS) + case "iPhone 16 Pro Max", "iPhone 15 Pro Max", "iPhone 14 Pro Max", "iPhone 13 Pro Max", "iPhone 12 Pro Max": + return .iPhone13ProMax + case "iPhone 16 Pro", "iPhone 15 Pro", "iPhone 14 Pro", "iPhone 13 Pro", "iPhone 12 Pro": + return .iPhone13Pro + case "iPhone 16", "iPhone 15", "iPhone 14", "iPhone 13", "iPhone 12", "iPhone 11", "iPhone 10", "iPhone X": + return .iPhoneX + case "iPhone 6", "iPhone 6s", "iPhone 7", "iPhone 8", "iPhone SE (2nd generation)", "iPhone SE (3rd generation)": + return .iPhone8 + case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 8 Plus": + return .iPhone8Plus + case "iPhone SE (1st generation)": + return .iPhoneSe + case "iPad": + return .iPad10_2 + case "iPad Mini": + return .iPadMini + case "iPad Pro 11": + return .iPadPro11 + case "iPad Pro 12.9": + return .iPadPro12_9 + #elseif os(tvOS) + case "Apple TV": + return .tv + #endif + default: return nil + } + } + + func snapshotDevice() -> DeviceConfig? { + (self.snapshotDevice())?.deviceConfig + } +} \ No newline at end of file