diff --git a/Sources/SnapshotTestingStitch/ConditionalTypes.swift b/Sources/SnapshotTestingStitch/ConditionalTypes.swift new file mode 100644 index 0000000..aad3eb2 --- /dev/null +++ b/Sources/SnapshotTestingStitch/ConditionalTypes.swift @@ -0,0 +1,13 @@ +#if canImport(UIKit) +import UIKit +public typealias Image = UIImage +public typealias Color = UIColor +public typealias Font = UIFont +public typealias ViewController = UIViewController +#elseif canImport(AppKit) +import AppKit +public typealias Image = NSImage +public typealias Color = NSColor +public typealias Font = NSFont +public typealias ViewController = NSViewController +#endif diff --git a/Sources/SnapshotTestingStitch/Snapshotting.swift b/Sources/SnapshotTestingStitch/Snapshotting.swift index d35e124..3f94dd9 100644 --- a/Sources/SnapshotTestingStitch/Snapshotting.swift +++ b/Sources/SnapshotTestingStitch/Snapshotting.swift @@ -1,8 +1,8 @@ -import UIKit +import CoreGraphics import SnapshotTesting import SnapshotTestingHEIC -public extension Snapshotting where Format == UIImage { +public extension Snapshotting where Format == Image { /// Stitches multiple visual snapshot strategies into a single image asset. /// /// - Parameters: @@ -66,7 +66,7 @@ public extension Snapshotting where Format == UIImage { /// - Parameters: /// - tasks: The tasks which should be carried out, in the order that they should be displayed. /// Tasks can include a title which will be displayed above their respectful image, - /// allowing for easier identification. Any strategy can be used as long as the output format is UIImage. + /// allowing for easier identification. Any strategy can be used as long as the output format is Image. /// Tasks can can also contain a configuration block which allows for you to modify /// the value just before it's snapshot is taken. /// - style: The style configuration which allows for you to customise the appearance of the output image, @@ -83,7 +83,7 @@ public extension Snapshotting where Format == UIImage { perceptualPrecision: Float = 1, format: ImageFormat = .png ) -> Snapshotting { - let internalStrategy: Snapshotting + let internalStrategy: Snapshotting switch format { case .png: @@ -96,12 +96,12 @@ public extension Snapshotting where Format == UIImage { pathExtension: internalStrategy.pathExtension, diffing: internalStrategy.diffing ) { value in - Async { callback in + Async { callback in // Fail fast: Ensure we have tasks to complete, otherwise return an empty image. // // An empty image will render an error as part of the SnapshotTesting flow. guard tasks.isEmpty == false else { - callback(UIImage()) + callback(Image()) return } @@ -109,7 +109,7 @@ public extension Snapshotting where Format == UIImage { let dispatchGroup = DispatchGroup() // Create an array to store the final outputs to be stitched - var values = [(index: Int, title: String?, output: UIImage)]() + var values = [(index: Int, title: String?, output: Image)]() // Loop over each of the user-provided strategies, snapshot them, // store the output, and update the dispatch group. @@ -128,7 +128,7 @@ public extension Snapshotting where Format == UIImage { // Once all strategies have been completed... dispatchGroup.notify(queue: .main) { // Sort values based on input order - let sortedValues: [(String?, UIImage)] = values + let sortedValues: [(String?, Image)] = values .sorted(by: { lhs, rhs in lhs.index < rhs.index }) .map { result in (result.title, result.output) } diff --git a/Sources/SnapshotTestingStitch/StitchStyle.swift b/Sources/SnapshotTestingStitch/StitchStyle.swift index 2a4afa3..695f466 100644 --- a/Sources/SnapshotTestingStitch/StitchStyle.swift +++ b/Sources/SnapshotTestingStitch/StitchStyle.swift @@ -1,14 +1,14 @@ -import UIKit +import CoreGraphics public struct StitchStyle { /// How large should the font size be for the optional titles which appear above each stitched image? public let fontSize: CGFloat /// What color should the title text be? - public let titleColor: UIColor + public let titleColor: Color /// What color should the border be which surrounds each individual stitched image? - public let borderColor: UIColor + public let borderColor: Color /// How thick should the border be which surrounds each individual stitched image? public let borderWidth: CGFloat @@ -23,7 +23,7 @@ public struct StitchStyle { public let titleSpacing: CGFloat /// What color should the background of the image be? - public let backgroundColor: UIColor + public let backgroundColor: Color /// Creates a defintion of how a stitched snapshot should be presented. /// @@ -40,13 +40,13 @@ public struct StitchStyle { /// - backgroundColor: What color should the background of the image be? public init( fontSize: CGFloat = 20, - titleColor: UIColor = .white, - borderColor: UIColor = .red, + titleColor: Color = .white, + borderColor: Color = .red, borderWidth: CGFloat = 5, itemSpacing: CGFloat = 32, framePadding: CGFloat = 32, titleSpacing: CGFloat = 32, - backgroundColor: UIColor = .black + backgroundColor: Color = .black ) { assert(borderWidth >= 0, "The provided border width should be a positive integer, or zero if you do not want a border to be displayed.") assert(itemSpacing >= 0, "The provided item spacing should be a positive integer.") diff --git a/Sources/SnapshotTestingStitch/Stitcher.swift b/Sources/SnapshotTestingStitch/Stitcher.swift index f115ed3..d7ca505 100644 --- a/Sources/SnapshotTestingStitch/Stitcher.swift +++ b/Sources/SnapshotTestingStitch/Stitcher.swift @@ -1,10 +1,16 @@ +import CoreGraphics + +#if canImport(UIKit) import UIKit +#elseif canImport(AppKit) +import AppKit +#endif struct ImageStitcher { + let inputs: [(title: String?, image: Image)] - let inputs: [(title: String?, image: UIImage)] - func stitch(style: StitchStyle) -> UIImage { + func stitch(style: StitchStyle) -> Image { // Check whether or not any inputs contain a valid title let allTitles = inputs @@ -88,7 +94,7 @@ struct ImageStitcher { paragraphStyle.alignment = .center let titleAttributes: [NSAttributedString.Key: Any] = [ - .font: UIFont.systemFont(ofSize: style.fontSize), + .font: Font.systemFont(ofSize: style.fontSize), .paragraphStyle: paragraphStyle, .foregroundColor: style.titleColor ] @@ -116,7 +122,7 @@ struct ImageStitcher { context.fill(CGRect(origin: .zero, size: size)) } - func calculateImageSize(images: [UIImage], includeTitles: Bool, style: StitchStyle) -> CGSize { + func calculateImageSize(images: [Image], includeTitles: Bool, style: StitchStyle) -> CGSize { let largestHeight = images .map { $0.size.height } .max() diff --git a/Tests/SnapshotTestingStitchTests/SnapshotTestingStitch.swift b/Tests/SnapshotTestingStitchTests/SnapshotTestingStitch.swift index 537f924..73d3fae 100644 --- a/Tests/SnapshotTestingStitchTests/SnapshotTestingStitch.swift +++ b/Tests/SnapshotTestingStitchTests/SnapshotTestingStitch.swift @@ -80,7 +80,7 @@ final class SnapshotTestingStitchTests: XCTestCase { func test_withNoStrategies() { // You actually get a compiler warning for ambiguity by default, so you have to go through some loops to pass // literally nothing through. - let tasks: [Snapshotting] = [] + let tasks: [Snapshotting] = [] assertSnapshot( matching: createTestView(), diff --git a/Tests/SnapshotTestingStitchTests/SnapshotTestingStitchHEIC.swift b/Tests/SnapshotTestingStitchTests/SnapshotTestingStitchHEIC.swift index 1f19b56..db3ed82 100644 --- a/Tests/SnapshotTestingStitchTests/SnapshotTestingStitchHEIC.swift +++ b/Tests/SnapshotTestingStitchTests/SnapshotTestingStitchHEIC.swift @@ -86,7 +86,7 @@ final class SnapshotTestingStitchHEICTests: XCTestCase { func test_withNoStrategies() { // You actually get a compiler warning for ambiguity by default, so you have to go through some loops to pass // literally nothing through. - let tasks: [Snapshotting] = [] + let tasks: [Snapshotting] = [] assertSnapshot( matching: createTestView(),