Skip to content

Commit 472017f

Browse files
committed
Support visionOS
1 parent c097f95 commit 472017f

File tree

181 files changed

+408
-244
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+408
-244
lines changed

.github/workflows/ci.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ jobs:
1313
strategy:
1414
matrix:
1515
xcode:
16-
- "14.3.1"
16+
- "15.3"
1717

18-
name: macOS 13 (Xcode ${{ matrix.xcode }})
19-
runs-on: macos-13
18+
name: macOS 14 (Xcode ${{ matrix.xcode }})
19+
runs-on: macos-14
2020
steps:
2121
- uses: actions/checkout@v3
2222
- name: Select Xcode ${{ matrix.xcode }}
@@ -28,7 +28,7 @@ jobs:
2828
strategy:
2929
matrix:
3030
swift:
31-
- "5.7"
31+
- "5.9.1"
3232

3333
name: Ubuntu (Swift ${{ matrix.swift }})
3434
runs-on: ubuntu-20.04

Makefile

+9-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test-ios:
1616
set -o pipefail && \
1717
xcodebuild test \
1818
-scheme SnapshotTesting \
19-
-destination platform="iOS Simulator,name=iPhone 11 Pro Max,OS=13.3"
19+
-destination platform="iOS Simulator,name=iPhone 15 Pro Max,OS=17.4"
2020

2121
test-swift:
2222
swift test
@@ -25,7 +25,13 @@ test-tvos:
2525
set -o pipefail && \
2626
xcodebuild test \
2727
-scheme SnapshotTesting \
28-
-destination platform="tvOS Simulator,name=Apple TV 4K,OS=13.3"
28+
-destination platform="tvOS Simulator,name=Apple TV 4K,OS=17.4"
29+
30+
test-visionos:
31+
set -o pipefail && \
32+
xcodebuild test \
33+
-scheme SnapshotTesting \
34+
-destination platform="visionOS Simulator,name=Apple Vision Pro,OS=1.1"
2935

3036
format:
3137
swift format \
@@ -34,4 +40,4 @@ format:
3440
--recursive \
3541
./Package.swift ./Sources ./Tests
3642

37-
test-all: test-linux test-macos test-ios
43+
test-all: test-linux test-macos test-ios test-visionos

Package.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.7
1+
// swift-tools-version:5.9
22

33
import PackageDescription
44

@@ -9,6 +9,7 @@ let package = Package(
99
.macOS(.v10_15),
1010
.tvOS(.v13),
1111
.watchOS(.v6),
12+
.visionOS(.v1),
1213
],
1314
products: [
1415
.library(

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,7 @@ targets: [
215215
collections from a single simulator.
216216
- **First-class Xcode support.** Image differences are captured as XCTest attachments. Text
217217
differences are rendered in inline error messages.
218-
- **Supports any platform that supports Swift.** Write snapshot tests for iOS, Linux, macOS, and
219-
tvOS.
218+
- **Supports any platform that supports Swift.** Write snapshot tests for iOS, Linux, macOS, tvOS and visionOS.
220219
- **SceneKit, SpriteKit, and WebKit support.** Most snapshot testing libraries don't support these
221220
view subclasses.
222221
- **`Codable` support**. Snapshot encodable data structures into their JSON and property list

Sources/SnapshotTesting/AssertSnapshot.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ public func verifySnapshot<Value, Format>(
347347
let data = try Data(contentsOf: snapshotFileUrl)
348348
let reference = snapshotting.diffing.fromData(data)
349349

350-
#if os(iOS) || os(tvOS)
350+
#if os(iOS) || os(tvOS) || os(visionOS)
351351
// If the image generation fails for the diffable part and the reference was empty, use the reference
352352
if let localDiff = diffable as? UIImage,
353353
let refImage = reference as? UIImage,

Sources/SnapshotTesting/Common/Internal.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
typealias Image = NSImage
44
typealias ImageView = NSImageView
55
typealias View = NSView
6-
#elseif os(iOS) || os(tvOS)
6+
#elseif os(iOS) || os(tvOS) || os(visionOS)
77
import UIKit
88
typealias Image = UIImage
99
typealias ImageView = UIImageView

Sources/SnapshotTesting/Common/View.swift

+42-15
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
#if os(iOS) || os(macOS) || os(tvOS)
1+
#if os(iOS) || os(macOS) || os(tvOS) || os(visionOS)
22
#if os(macOS)
33
import Cocoa
44
#endif
55
import SceneKit
66
import SpriteKit
7-
#if os(iOS) || os(tvOS)
7+
#if os(iOS) || os(tvOS) || os(visionOS)
88
import UIKit
99
#endif
10-
#if os(iOS) || os(macOS)
10+
#if os(iOS) || os(macOS) || os(visionOS)
1111
import WebKit
1212
#endif
1313

14-
#if os(iOS) || os(tvOS)
14+
#if os(iOS) || os(tvOS) || os(visionOS)
1515
public struct ViewImageConfig: Sendable {
1616
public enum Orientation {
1717
case landscape
@@ -499,6 +499,12 @@
499499
size: .init(width: 3840, height: 2160),
500500
traits: .init()
501501
)
502+
#elseif os(visionOS)
503+
public static let visionPro = ViewImageConfig(
504+
safeArea: .zero,
505+
size: .init(width: 2700, height: 1360),
506+
traits: .init()
507+
)
502508
#endif
503509
}
504510

@@ -804,6 +810,21 @@
804810
)
805811
#elseif os(tvOS)
806812
// TODO
813+
#elseif os(visionOS)
814+
public static let visionPro = UITraitCollection(
815+
traitsFrom: [
816+
.init(userInterfaceIdiom: .vision),
817+
.init(horizontalSizeClass: .regular),
818+
.init(verticalSizeClass: .regular),
819+
.init(displayScale: 2.0),
820+
.init(userInterfaceStyle: .dark),
821+
.init(layoutDirection: .leftToRight),
822+
.init(forceTouchCapability: .unavailable),
823+
.init(preferredContentSizeCategory: .large),
824+
.init(accessibilityContrast: .normal),
825+
.init(userInterfaceLevel: .base),
826+
]
827+
)
807828
#endif
808829
}
809830
#endif
@@ -819,7 +840,7 @@
819840
imageView.frame = view.frame
820841
#if os(macOS)
821842
view.superview?.addSubview(imageView, positioned: .above, relativeTo: view)
822-
#elseif os(iOS) || os(tvOS)
843+
#elseif os(iOS) || os(tvOS) || os(visionOS)
823844
view.superview?.insertSubview(imageView, aboveSubview: view)
824845
#endif
825846
callback(imageView)
@@ -850,26 +871,26 @@
850871
let cgImage = inWindow { skView.texture(from: skView.scene!)!.cgImage() }
851872
#if os(macOS)
852873
let image = Image(cgImage: cgImage, size: skView.bounds.size)
853-
#elseif os(iOS) || os(tvOS)
874+
#elseif os(iOS) || os(tvOS) || os(visionOS)
854875
let image = Image(cgImage: cgImage)
855876
#endif
856877
return Async(value: image)
857878
} else {
858879
fatalError("Taking SKView snapshots requires macOS 10.11 or greater")
859880
}
860881
}
861-
#if os(iOS) || os(macOS)
882+
#if os(iOS) || os(macOS) || os(visionOS)
862883
if let wkWebView = self as? WKWebView {
863884
return Async<Image> { callback in
864885
let work = {
865-
if #available(iOS 11.0, macOS 10.13, *) {
886+
if #available(iOS 11.0, macOS 10.13, visionOS 1.0, *) {
866887
inWindow {
867888
guard wkWebView.frame.width != 0, wkWebView.frame.height != 0 else {
868889
callback(Image())
869890
return
870891
}
871892
let configuration = WKSnapshotConfiguration()
872-
if #available(iOS 13, macOS 10.15, *) {
893+
if #available(iOS 13, macOS 10.15, visionOS 1.0, *) {
873894
configuration.afterScreenUpdates = false
874895
}
875896
wkWebView.takeSnapshot(with: configuration) { image, _ in
@@ -879,6 +900,8 @@
879900
} else {
880901
#if os(iOS)
881902
fatalError("Taking WKWebView snapshots requires iOS 11.0 or greater")
903+
#elseif os(visionOS)
904+
fatalError("Taking WKWebView snapshots requires visionOS 1.0 or greater")
882905
#elseif os(macOS)
883906
fatalError("Taking WKWebView snapshots requires macOS 10.13 or greater")
884907
#endif
@@ -903,7 +926,7 @@
903926
#endif
904927
return nil
905928
}
906-
#if os(iOS) || os(tvOS)
929+
#if os(iOS) || os(tvOS) || os(visionOS)
907930
func asImage() -> Image {
908931
let renderer = UIGraphicsImageRenderer(bounds: bounds)
909932
return renderer.image { rendererContext in
@@ -913,7 +936,7 @@
913936
#endif
914937
}
915938

916-
#if os(iOS) || os(tvOS)
939+
#if os(iOS) || os(tvOS) || os(visionOS)
917940
extension UIApplication {
918941
static var sharedIfAvailable: UIApplication? {
919942
let sharedSelector = NSSelectorFromString("sharedApplication")
@@ -1011,7 +1034,7 @@
10111034

10121035
func renderer(bounds: CGRect, for traits: UITraitCollection) -> UIGraphicsImageRenderer {
10131036
let renderer: UIGraphicsImageRenderer
1014-
if #available(iOS 11.0, tvOS 11.0, *) {
1037+
if #available(iOS 11.0, tvOS 11.0, visionOS 1.0, *) {
10151038
renderer = UIGraphicsImageRenderer(bounds: bounds, format: .init(for: traits))
10161039
} else {
10171040
renderer = UIGraphicsImageRenderer(bounds: bounds)
@@ -1076,10 +1099,14 @@
10761099

10771100
private func getKeyWindow() -> UIWindow? {
10781101
var window: UIWindow?
1079-
if #available(iOS 13.0, *) {
1102+
if #available(iOS 13.0, visionOS 1.0, *) {
10801103
window = UIApplication.sharedIfAvailable?.windows.first { $0.isKeyWindow }
10811104
} else {
1082-
window = UIApplication.sharedIfAvailable?.keyWindow
1105+
#if os(visionOS)
1106+
window = UIApplication.sharedIfAvailable?.windows.first { $0.isKeyWindow }
1107+
#else
1108+
window = UIApplication.sharedIfAvailable?.keyWindow
1109+
#endif
10831110
}
10841111
return window
10851112
}
@@ -1112,7 +1139,7 @@
11121139
fatalError("init(coder:) has not been implemented")
11131140
}
11141141

1115-
@available(iOS 11.0, *)
1142+
@available(iOS 11.0, visionOS 1.0, *)
11161143
override var safeAreaInsets: UIEdgeInsets {
11171144
#if os(iOS)
11181145
let removeTopInset =

Sources/SnapshotTesting/Snapshotting/Any.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ extension Snapshotting where Format == String {
4646
}
4747
}
4848

49-
@available(macOS 10.13, watchOS 4.0, tvOS 11.0, *)
49+
@available(macOS 10.13, watchOS 4.0, tvOS 11.0, iOS 11.0, visionOS 1.0, *)
5050
extension Snapshotting where Format == String {
5151
/// A snapshot strategy for comparing any structure based on their JSON representation.
5252
public static var json: Snapshotting {

Sources/SnapshotTesting/Snapshotting/CALayer.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
}
4141
}
4242
}
43-
#elseif os(iOS) || os(tvOS)
43+
#elseif os(iOS) || os(tvOS) || os(visionOS)
4444
import UIKit
4545

4646
extension Snapshotting where Value == CALayer, Format == UIImage {

Sources/SnapshotTesting/Snapshotting/CGPath.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
}
5050
}
5151
}
52-
#elseif os(iOS) || os(tvOS)
52+
#elseif os(iOS) || os(tvOS) || os(visionOS)
5353
import UIKit
5454

5555
extension Snapshotting where Value == CGPath, Format == UIImage {
@@ -75,7 +75,7 @@
7575
).pullback { path in
7676
let bounds = path.boundingBoxOfPath
7777
let format: UIGraphicsImageRendererFormat
78-
if #available(iOS 11.0, tvOS 11.0, *) {
78+
if #available(iOS 11.0, tvOS 11.0, visionOS 1.0, *) {
7979
format = UIGraphicsImageRendererFormat.preferred()
8080
} else {
8181
format = UIGraphicsImageRendererFormat.default()
@@ -91,8 +91,8 @@
9191
}
9292
#endif
9393

94-
#if os(macOS) || os(iOS) || os(tvOS)
95-
@available(iOS 11.0, OSX 10.13, tvOS 11.0, *)
94+
#if os(macOS) || os(iOS) || os(tvOS) || os(visionOS)
95+
@available(iOS 11.0, OSX 10.13, tvOS 11.0, visionOS 1.0, *)
9696
extension Snapshotting where Value == CGPath, Format == String {
9797
/// A snapshot strategy for comparing bezier paths based on element descriptions.
9898
public static var elementsDescription: Snapshotting {

Sources/SnapshotTesting/Snapshotting/Encodable.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extension Snapshotting where Value: Encodable, Format == String {
1616
/// "name" : "Blobby"
1717
/// }
1818
/// ```
19-
@available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *)
19+
@available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, visionOS 1.0, *)
2020
public static var json: Snapshotting {
2121
let encoder = JSONEncoder()
2222
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]

Sources/SnapshotTesting/Snapshotting/SceneKit.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#if os(iOS) || os(macOS) || os(tvOS)
1+
#if os(iOS) || os(macOS) || os(tvOS) || os(visionOS)
22
import SceneKit
33
#if os(macOS)
44
import Cocoa
5-
#elseif os(iOS) || os(tvOS)
5+
#elseif os(iOS) || os(tvOS) || os(visionOS)
66
import UIKit
77
#endif
88

@@ -23,7 +23,7 @@
2323
return .scnScene(precision: precision, perceptualPrecision: perceptualPrecision, size: size)
2424
}
2525
}
26-
#elseif os(iOS) || os(tvOS)
26+
#elseif os(iOS) || os(tvOS) || os(visionOS)
2727
extension Snapshotting where Value == SCNScene, Format == UIImage {
2828
/// A snapshot strategy for comparing SceneKit scenes based on pixel equality.
2929
///

Sources/SnapshotTesting/Snapshotting/SpriteKit.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#if os(iOS) || os(macOS) || os(tvOS)
1+
#if os(iOS) || os(macOS) || os(tvOS) || os(visionOS)
22
import SpriteKit
33
#if os(macOS)
44
import Cocoa
5-
#elseif os(iOS) || os(tvOS)
5+
#elseif os(iOS) || os(tvOS) || os(visionOS)
66
import UIKit
77
#endif
88

@@ -23,7 +23,7 @@
2323
return .skScene(precision: precision, perceptualPrecision: perceptualPrecision, size: size)
2424
}
2525
}
26-
#elseif os(iOS) || os(tvOS)
26+
#elseif os(iOS) || os(tvOS) || os(visionOS)
2727
extension Snapshotting where Value == SKScene, Format == UIImage {
2828
/// A snapshot strategy for comparing SpriteKit scenes based on pixel equality.
2929
///

Sources/SnapshotTesting/Snapshotting/SwiftUIView.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
/// The size constraint for a snapshot (similar to `PreviewLayout`).
66
public enum SwiftUISnapshotLayout {
7-
#if os(iOS) || os(tvOS)
7+
#if os(iOS) || os(tvOS) || os(visionOS)
88
/// Center the view in a device container described by`config`.
99
case device(config: ViewImageConfig)
1010
#endif
@@ -14,8 +14,8 @@
1414
case sizeThatFits
1515
}
1616

17-
#if os(iOS) || os(tvOS)
18-
@available(iOS 13.0, tvOS 13.0, *)
17+
#if os(iOS) || os(tvOS) || os(visionOS)
18+
@available(iOS 13.0, tvOS 13.0, visionOS 1.0, *)
1919
extension Snapshotting where Value: SwiftUI.View, Format == UIImage {
2020

2121
/// A snapshot strategy for comparing SwiftUI Views based on pixel equality.
@@ -48,7 +48,7 @@
4848
let config: ViewImageConfig
4949

5050
switch layout {
51-
#if os(iOS) || os(tvOS)
51+
#if os(iOS) || os(tvOS) || os(visionOS)
5252
case let .device(config: deviceConfig):
5353
config = deviceConfig
5454
#endif

0 commit comments

Comments
 (0)