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