diff --git a/Package.swift b/Package.swift index ea792a43d603a5905da0fd777ad6a9d45cf29d91..5147b8311f3b2000c25f32b5fc5706c6fa290ea9 100644 --- a/Package.swift +++ b/Package.swift @@ -746,7 +746,9 @@ let package = Package( ), .target( name: "ReportingFeature", - dependencies: [] + dependencies: [ + .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"), + ] ), ] ) diff --git a/Sources/ReportingFeature/MakeAppScreenshot.swift b/Sources/ReportingFeature/MakeAppScreenshot.swift new file mode 100644 index 0000000000000000000000000000000000000000..7d44af879f35d792685f3e278cc6ce9c044d8a07 --- /dev/null +++ b/Sources/ReportingFeature/MakeAppScreenshot.swift @@ -0,0 +1,53 @@ +import Foundation +import UIKit +import XCTestDynamicOverlay + +public struct MakeAppScreenshot { + public enum Error: Swift.Error, Equatable { + case unableToGetForegroundWindowScene + case unableToGetKeyWindow + } + + public var run: () throws -> UIImage + + public func callAsFunction() throws -> UIImage { + try run() + } +} + +extension MakeAppScreenshot { + public static let live = MakeAppScreenshot { + let scene: UIWindowScene? = UIApplication.shared.connectedScenes + .filter { $0.activationState == .foregroundActive } + .compactMap { $0 as? UIWindowScene } + .first + + guard let scene = scene else { + throw Error.unableToGetForegroundWindowScene + } + + let window: UIWindow? = scene.windows.first(where: \.isKeyWindow) + + guard let keyWindow = window else { + throw Error.unableToGetKeyWindow + } + + let rendererFormat = UIGraphicsImageRendererFormat() + rendererFormat.scale = scene.screen.scale + + let renderer = UIGraphicsImageRenderer( + bounds: keyWindow.bounds, + format: rendererFormat + ) + + return renderer.image { ctx in + keyWindow.layer.render(in: ctx.cgContext) + } + } +} + +extension MakeAppScreenshot { + public static let unimplemented = MakeAppScreenshot( + run: XCTUnimplemented("\(Self.self)") + ) +}