How to use testNSViewWithLayer method of CancellingWKWebViewNavigationDelegate class

Best Swift-snapshot-testing code snippet using CancellingWKWebViewNavigationDelegate.testNSViewWithLayer

Run Swift-snapshot-testing automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

SnapshotTestingTests.swift

Source: SnapshotTestingTests.swift Github

copy
1import Foundation
2#if canImport(FoundationNetworking)
3import FoundationNetworking
4#endif
5#if canImport(SceneKit)
6import SceneKit
7#endif
8#if canImport(SpriteKit)
9import SpriteKit
10import SwiftUI
11#endif
12#if canImport(WebKit)
13import WebKit
14#endif
15#if canImport(UIKit)
16import UIKit.UIView
17#endif
18import XCTest
19
20@testable import SnapshotTesting
21
22final class SnapshotTestingTests: XCTestCase {
23  override func setUp() {
24    super.setUp()
25    diffTool = "ksdiff"
26//    isRecording = true
27  }
28
29  override func tearDown() {
30    isRecording = false
31    super.tearDown()
32  }
33
34  func testAny() {
35    struct User { let id: Int, name: String, bio: String }
36    let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.")
37    assertSnapshot(matching: user, as: .dump)
38    _assertInlineSnapshot(matching: user, as: .dump, with: """
39    ▿ User
40      - bio: "Blobbed around the world."
41      - id: 1
42      - name: "Blobby"
43    """)
44  }
45
46  @available(macOS 10.13, *)
47  func testAnyAsJson() throws {
48    struct User: Encodable { let id: Int, name: String, bio: String }
49    let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.")
50
51    let data = try JSONEncoder().encode(user)
52    let any = try JSONSerialization.jsonObject(with: data, options: [])
53
54    assertSnapshot(matching: any, as: .json)
55  }
56
57  func testAnySnapshotStringConvertible() {
58    assertSnapshot(matching: "a" as Character, as: .dump, named: "character")
59    assertSnapshot(matching: Data("Hello, world!".utf8), as: .dump, named: "data")
60    assertSnapshot(matching: Date(timeIntervalSinceReferenceDate: 0), as: .dump, named: "date")
61    assertSnapshot(matching: NSObject(), as: .dump, named: "nsobject")
62    assertSnapshot(matching: "Hello, world!", as: .dump, named: "string")
63    assertSnapshot(matching: "Hello, world!".dropLast(8), as: .dump, named: "substring")
64    assertSnapshot(matching: URL(string: "https://www.pointfree.co")!, as: .dump, named: "url")
65    // Inline
66    _assertInlineSnapshot(matching: "a" as Character, as: .dump, with: """
67    - "a"
68    """)
69    _assertInlineSnapshot(matching: Data("Hello, world!".utf8), as: .dump, with: """
70    - 13 bytes
71    """)
72    _assertInlineSnapshot(matching: Date(timeIntervalSinceReferenceDate: 0), as: .dump, with: """
73    - 2001-01-01T00:00:00Z
74    """)
75    _assertInlineSnapshot(matching: NSObject(), as: .dump, with: """
76    - <NSObject>
77    """)
78    _assertInlineSnapshot(matching: "Hello, world!", as: .dump, with: """
79    - "Hello, world!"
80    """)
81    _assertInlineSnapshot(matching: "Hello, world!".dropLast(8), as: .dump, with: """
82    - "Hello"
83    """)
84    _assertInlineSnapshot(matching: URL(string: "https://www.pointfree.co")!, as: .dump, with: """
85    - https://www.pointfree.co
86    """)
87  }
88
89  func testAutolayout() {
90    #if os(iOS)
91    let vc = UIViewController()
92    vc.view.translatesAutoresizingMaskIntoConstraints = false
93    let subview = UIView()
94    subview.translatesAutoresizingMaskIntoConstraints = false
95    vc.view.addSubview(subview)
96    NSLayoutConstraint.activate([
97      subview.topAnchor.constraint(equalTo: vc.view.topAnchor),
98      subview.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor),
99      subview.leftAnchor.constraint(equalTo: vc.view.leftAnchor),
100      subview.rightAnchor.constraint(equalTo: vc.view.rightAnchor),
101      ])
102    assertSnapshot(matching: vc, as: .image)
103    #endif
104  }
105
106  func testDeterministicDictionaryAndSetSnapshots() {
107    struct Person: Hashable { let name: String }
108    struct DictionarySetContainer { let dict: [String: Int], set: Set<Person> }
109    let set = DictionarySetContainer(
110      dict: ["c": 3, "a": 1, "b": 2],
111      set: [.init(name: "Brandon"), .init(name: "Stephen")]
112    )
113    assertSnapshot(matching: set, as: .dump)
114    _assertInlineSnapshot(matching: set, as: .dump, with: """
115    ▿ DictionarySetContainer
116      ▿ dict: 3 key/value pairs
117        ▿ (2 elements)
118          - key: "a"
119          - value: 1
120        ▿ (2 elements)
121          - key: "b"
122          - value: 2
123        ▿ (2 elements)
124          - key: "c"
125          - value: 3
126      ▿ set: 2 members
127        ▿ Person
128          - name: "Brandon"
129        ▿ Person
130          - name: "Stephen"
131    """)
132  }
133
134  func testCaseIterable() {
135    enum Direction: String, CaseIterable {
136      case up, down, left, right
137      var rotatedLeft: Direction {
138        switch self {
139        case .up:    return .left
140        case .down:  return .right
141        case .left:  return .down
142        case .right: return .up
143        }
144      }
145    }
146
147    assertSnapshot(
148      matching: { $0.rotatedLeft },
149      as: Snapshotting<Direction, String>.func(into: .description)
150    )
151  }
152
153  func testCGPath() {
154    #if os(iOS) || os(tvOS) || os(macOS)
155    let path = CGPath.heart
156
157    let osName: String
158    #if os(iOS)
159    osName = "iOS"
160    #elseif os(tvOS)
161    osName = "tvOS"
162    #elseif os(macOS)
163    osName = "macOS"
164    #endif
165
166    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
167      assertSnapshot(matching: path, as: .image, named: osName)
168    }
169
170    if #available(iOS 11.0, OSX 10.13, tvOS 11.0, *) {
171      assertSnapshot(matching: path, as: .elementsDescription, named: osName)
172    }
173    #endif
174  }
175
176  func testData() {
177    let data = Data([0xDE, 0xAD, 0xBE, 0xEF])
178
179    assertSnapshot(matching: data, as: .data)
180  }
181
182  func testEncodable() {
183    struct User: Encodable { let id: Int, name: String, bio: String }
184    let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.")
185
186    if #available(iOS 11.0, macOS 10.13, tvOS 11.0, *) {
187      assertSnapshot(matching: user, as: .json)
188    }
189    assertSnapshot(matching: user, as: .plist)
190  }
191
192  func testMixedViews() {
193//    #if os(iOS) || os(macOS)
194//    // NB: CircleCI crashes while trying to instantiate SKView.
195//    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
196//      let webView = WKWebView(frame: .init(x: 0, y: 0, width: 50, height: 50))
197//      webView.loadHTMLString("🌎", baseURL: nil)
198//
199//      let skView = SKView(frame: .init(x: 50, y: 0, width: 50, height: 50))
200//      let scene = SKScene(size: .init(width: 50, height: 50))
201//      let node = SKShapeNode(circleOfRadius: 15)
202//      node.fillColor = .red
203//      node.position = .init(x: 25, y: 25)
204//      scene.addChild(node)
205//      skView.presentScene(scene)
206//
207//      let view = View(frame: .init(x: 0, y: 0, width: 100, height: 50))
208//      view.addSubview(webView)
209//      view.addSubview(skView)
210//
211//      assertSnapshot(matching: view, as: .image, named: platform)
212//    }
213//    #endif
214  }
215
216  func testMultipleSnapshots() {
217    assertSnapshot(matching: [1], as: .dump)
218    assertSnapshot(matching: [1, 2], as: .dump)
219  }
220
221  func testNamedAssertion() {
222    struct User { let id: Int, name: String, bio: String }
223    let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.")
224    assertSnapshot(matching: user, as: .dump, named: "named")
225  }
226
227  func testNSBezierPath() {
228    #if os(macOS)
229    let path = NSBezierPath.heart
230
231    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
232      assertSnapshot(matching: path, as: .image, named: "macOS")
233    }
234
235    assertSnapshot(matching: path, as: .elementsDescription, named: "macOS")
236    #endif
237  }
238
239  func testNSView() {
240    #if os(macOS)
241    let button = NSButton()
242    button.bezelStyle = .rounded
243    button.title = "Push Me"
244    button.sizeToFit()
245    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
246      assertSnapshot(matching: button, as: .image)
247      assertSnapshot(matching: button, as: .recursiveDescription)
248    }
249    #endif
250  }
251  
252  func testNSViewWithLayer() {
253    #if os(macOS)
254    let view = NSView()
255    view.frame = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0)
256    view.wantsLayer = true
257    view.layer?.backgroundColor = NSColor.green.cgColor
258    view.layer?.cornerRadius = 5
259    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
260      assertSnapshot(matching: view, as: .image)
261      assertSnapshot(matching: view, as: .recursiveDescription)
262    }
263    #endif
264  }
265
266  func testPrecision() {
267    #if os(iOS) || os(macOS) || os(tvOS)
268    #if os(iOS) || os(tvOS)
269    let label = UILabel()
270    #if os(iOS)
271    label.frame = CGRect(origin: .zero, size: CGSize(width: 43.5, height: 20.5))
272    #elseif os(tvOS)
273    label.frame = CGRect(origin: .zero, size: CGSize(width: 98, height: 46))
274    #endif
275    label.backgroundColor = .white
276    #elseif os(macOS)
277    let label = NSTextField()
278    label.frame = CGRect(origin: .zero, size: CGSize(width: 37, height: 16))
279    label.backgroundColor = .white
280    label.isBezeled = false
281    label.isEditable = false
282    #endif
283    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
284      label.text = "Hello."
285      assertSnapshot(matching: label, as: .image(precision: 0.9), named: platform)
286      label.text = "Hello"
287      assertSnapshot(matching: label, as: .image(precision: 0.9), named: platform)
288    }
289    #endif
290  }
291
292  func testSCNView() {
293//    #if os(iOS) || os(macOS) || os(tvOS)
294//    // NB: CircleCI crashes while trying to instantiate SCNView.
295//    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
296//      let scene = SCNScene()
297//
298//      let sphereGeometry = SCNSphere(radius: 3)
299//      sphereGeometry.segmentCount = 200
300//      let sphereNode = SCNNode(geometry: sphereGeometry)
301//      sphereNode.position = SCNVector3Zero
302//      scene.rootNode.addChildNode(sphereNode)
303//
304//      sphereGeometry.firstMaterial?.diffuse.contents = URL(fileURLWithPath: String(#file), isDirectory: false)
305//        .deletingLastPathComponent()
306//        .appendingPathComponent("__Fixtures__/earth.png")
307//
308//      let cameraNode = SCNNode()
309//      cameraNode.camera = SCNCamera()
310//      cameraNode.position = SCNVector3Make(0, 0, 8)
311//      scene.rootNode.addChildNode(cameraNode)
312//
313//      let omniLight = SCNLight()
314//      omniLight.type = .omni
315//      let omniLightNode = SCNNode()
316//      omniLightNode.light = omniLight
317//      omniLightNode.position = SCNVector3Make(10, 10, 10)
318//      scene.rootNode.addChildNode(omniLightNode)
319//
320//      assertSnapshot(
321//        matching: scene,
322//        as: .image(size: .init(width: 500, height: 500)),
323//        named: platform
324//      )
325//    }
326//    #endif
327  }
328
329  func testSKView() {
330//    #if os(iOS) || os(macOS) || os(tvOS)
331//    // NB: CircleCI crashes while trying to instantiate SKView.
332//    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
333//      let scene = SKScene(size: .init(width: 50, height: 50))
334//      let node = SKShapeNode(circleOfRadius: 15)
335//      node.fillColor = .red
336//      node.position = .init(x: 25, y: 25)
337//      scene.addChild(node)
338//
339//      assertSnapshot(
340//        matching: scene,
341//        as: .image(size: .init(width: 50, height: 50)),
342//        named: platform
343//      )
344//    }
345//    #endif
346  }
347
348  func testTableViewController() {
349    #if os(iOS)
350    class TableViewController: UITableViewController {
351      override func viewDidLoad() {
352        super.viewDidLoad()
353        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
354      }
355      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
356        return 10
357      }
358      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
359        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
360        cell.textLabel?.text = "\(indexPath.row)"
361        return cell
362      }
363    }
364    let tableViewController = TableViewController()
365    assertSnapshot(matching: tableViewController, as: .image(on: .iPhoneSe))
366    #endif
367  }
368
369  func testAssertMultipleSnapshot() {
370    #if os(iOS)
371    class TableViewController: UITableViewController {
372      override func viewDidLoad() {
373        super.viewDidLoad()
374        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
375      }
376      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
377        return 10
378      }
379      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
380        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
381        cell.textLabel?.text = "\(indexPath.row)"
382        return cell
383      }
384    }
385    let tableViewController = TableViewController()
386    assertSnapshots(matching: tableViewController, as: ["iPhoneSE-image" : .image(on: .iPhoneSe), "iPad-image" : .image(on: .iPadMini)])
387    assertSnapshots(matching: tableViewController, as: [.image(on: .iPhoneX), .image(on: .iPhoneXsMax)])
388    #endif
389  }
390
391  func testTraits() {
392    #if os(iOS) || os(tvOS)
393    if #available(iOS 11.0, tvOS 11.0, *) {
394      class MyViewController: UIViewController {
395        let topLabel = UILabel()
396        let leadingLabel = UILabel()
397        let trailingLabel = UILabel()
398        let bottomLabel = UILabel()
399
400        override func viewDidLoad() {
401          super.viewDidLoad()
402
403          self.navigationItem.leftBarButtonItem = .init(barButtonSystemItem: .add, target: nil, action: nil)
404
405          self.view.backgroundColor = .white
406
407          self.topLabel.text = "What's"
408          self.leadingLabel.text = "the"
409          self.trailingLabel.text = "point"
410          self.bottomLabel.text = "?"
411
412          self.topLabel.translatesAutoresizingMaskIntoConstraints = false
413          self.leadingLabel.translatesAutoresizingMaskIntoConstraints = false
414          self.trailingLabel.translatesAutoresizingMaskIntoConstraints = false
415          self.bottomLabel.translatesAutoresizingMaskIntoConstraints = false
416
417          self.view.addSubview(self.topLabel)
418          self.view.addSubview(self.leadingLabel)
419          self.view.addSubview(self.trailingLabel)
420          self.view.addSubview(self.bottomLabel)
421
422          NSLayoutConstraint.activate([
423            self.topLabel.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
424            self.topLabel.centerXAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
425            self.leadingLabel.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
426            self.leadingLabel.trailingAnchor.constraint(lessThanOrEqualTo: self.view.safeAreaLayoutGuide.centerXAnchor),
427//            self.leadingLabel.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
428            self.leadingLabel.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor),
429            self.trailingLabel.leadingAnchor.constraint(greaterThanOrEqualTo: self.view.safeAreaLayoutGuide.centerXAnchor),
430            self.trailingLabel.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
431            self.trailingLabel.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor),
432            self.bottomLabel.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
433            self.bottomLabel.centerXAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
434            ])
435        }
436
437        override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
438          super.traitCollectionDidChange(previousTraitCollection)
439          self.topLabel.font = .preferredFont(forTextStyle: .headline, compatibleWith: self.traitCollection)
440          self.leadingLabel.font = .preferredFont(forTextStyle: .body, compatibleWith: self.traitCollection)
441          self.trailingLabel.font = .preferredFont(forTextStyle: .body, compatibleWith: self.traitCollection)
442          self.bottomLabel.font = .preferredFont(forTextStyle: .subheadline, compatibleWith: self.traitCollection)
443          self.view.setNeedsUpdateConstraints()
444          self.view.updateConstraintsIfNeeded()
445        }
446      }
447
448      let viewController = MyViewController()
449
450      #if os(iOS)
451      assertSnapshot(matching: viewController, as: .image(on: .iPhoneSe), named: "iphone-se")
452      assertSnapshot(matching: viewController, as: .image(on: .iPhone8), named: "iphone-8")
453      assertSnapshot(matching: viewController, as: .image(on: .iPhone8Plus), named: "iphone-8-plus")
454      assertSnapshot(matching: viewController, as: .image(on: .iPhoneX), named: "iphone-x")
455      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXr), named: "iphone-xr")
456      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXsMax), named: "iphone-xs-max")
457      assertSnapshot(matching: viewController, as: .image(on: .iPadMini), named: "ipad-mini")
458      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7), named: "ipad-9-7")
459      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2), named: "ipad-10-2")
460      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5), named: "ipad-pro-10-5")
461      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11), named: "ipad-pro-11")
462      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9), named: "ipad-pro-12-9")
463
464      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPhoneSe), named: "iphone-se")
465      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPhone8), named: "iphone-8")
466      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPhone8Plus), named: "iphone-8-plus")
467      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPhoneX), named: "iphone-x")
468      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPhoneXr), named: "iphone-xr")
469      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPhoneXsMax), named: "iphone-xs-max")
470      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPadMini), named: "ipad-mini")
471      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPad9_7), named: "ipad-9-7")
472      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPad10_2), named: "ipad-10-2")
473      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPadPro10_5), named: "ipad-pro-10-5")
474      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPadPro11), named: "ipad-pro-11")
475      assertSnapshot(matching: viewController, as: .recursiveDescription(on: .iPadPro12_9), named: "ipad-pro-12-9")
476
477      assertSnapshot(matching: viewController, as: .image(on: .iPhoneSe(.portrait)), named: "iphone-se")
478      assertSnapshot(matching: viewController, as: .image(on: .iPhone8(.portrait)), named: "iphone-8")
479      assertSnapshot(matching: viewController, as: .image(on: .iPhone8Plus(.portrait)), named: "iphone-8-plus")
480      assertSnapshot(matching: viewController, as: .image(on: .iPhoneX(.portrait)), named: "iphone-x")
481      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXr(.portrait)), named: "iphone-xr")
482      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXsMax(.portrait)), named: "iphone-xs-max")
483      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.landscape)), named: "ipad-mini")
484      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.landscape)), named: "ipad-9-7")
485      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.landscape)), named: "ipad-10-2")
486      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.landscape)), named: "ipad-pro-10-5")
487      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.landscape)), named: "ipad-pro-11")
488      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.landscape)), named: "ipad-pro-12-9")
489
490      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.landscape(splitView: .oneThird))), named: "ipad-mini-33-split-landscape")
491      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.landscape(splitView: .oneHalf))), named: "ipad-mini-50-split-landscape")
492      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.landscape(splitView: .twoThirds))), named: "ipad-mini-66-split-landscape")
493      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.portrait(splitView: .oneThird))), named: "ipad-mini-33-split-portrait")
494      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.portrait(splitView: .twoThirds))), named: "ipad-mini-66-split-portrait")
495
496      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.landscape(splitView: .oneThird))), named: "ipad-9-7-33-split-landscape")
497      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.landscape(splitView: .oneHalf))), named: "ipad-9-7-50-split-landscape")
498      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.landscape(splitView: .twoThirds))), named: "ipad-9-7-66-split-landscape")
499      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.portrait(splitView: .oneThird))), named: "ipad-9-7-33-split-portrait")
500      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.portrait(splitView: .twoThirds))), named: "ipad-9-7-66-split-portrait")
501
502      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.landscape(splitView: .oneThird))), named: "ipad-10-2-split-landscape")
503      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.landscape(splitView: .oneHalf))), named: "ipad-10-2-50-split-landscape")
504      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.landscape(splitView: .twoThirds))), named: "ipad-10-2-66-split-landscape")
505      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.portrait(splitView: .oneThird))), named: "ipad-10-2-33-split-portrait")
506      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.portrait(splitView: .twoThirds))), named: "ipad-10-2-66-split-portrait")
507      
508      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.landscape(splitView: .oneThird))), named: "ipad-pro-10inch-33-split-landscape")
509      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.landscape(splitView: .oneHalf))), named: "ipad-pro-10inch-50-split-landscape")
510      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.landscape(splitView: .twoThirds))), named: "ipad-pro-10inch-66-split-landscape")
511      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.portrait(splitView: .oneThird))), named: "ipad-pro-10inch-33-split-portrait")
512      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.portrait(splitView: .twoThirds))), named: "ipad-pro-10inch-66-split-portrait")
513      
514      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.landscape(splitView: .oneThird))), named: "ipad-pro-11inch-33-split-landscape")
515      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.landscape(splitView: .oneHalf))), named: "ipad-pro-11inch-50-split-landscape")
516      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.landscape(splitView: .twoThirds))), named: "ipad-pro-11inch-66-split-landscape")
517      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.portrait(splitView: .oneThird))), named: "ipad-pro-11inch-33-split-portrait")
518      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.portrait(splitView: .twoThirds))), named: "ipad-pro-11inch-66-split-portrait")
519      
520      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.landscape(splitView: .oneThird))), named: "ipad-pro-12inch-33-split-landscape")
521      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.landscape(splitView: .oneHalf))), named: "ipad-pro-12inch-50-split-landscape")
522      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.landscape(splitView: .twoThirds))), named: "ipad-pro-12inch-66-split-landscape")
523      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.portrait(splitView: .oneThird))), named: "ipad-pro-12inch-33-split-portrait")
524      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.portrait(splitView: .twoThirds))), named: "ipad-pro-12inch-66-split-portrait")
525      
526      assertSnapshot(
527        matching: viewController, as: .image(on: .iPhoneSe(.landscape)), named: "iphone-se-alternative")
528      assertSnapshot(
529        matching: viewController, as: .image(on: .iPhone8(.landscape)), named: "iphone-8-alternative")
530      assertSnapshot(
531        matching: viewController, as: .image(on: .iPhone8Plus(.landscape)), named: "iphone-8-plus-alternative")
532      assertSnapshot(
533        matching: viewController, as: .image(on: .iPhoneX(.landscape)), named: "iphone-x-alternative")
534      assertSnapshot(
535        matching: viewController, as: .image(on: .iPhoneXr(.landscape)), named: "iphone-xr-alternative")
536      assertSnapshot(
537        matching: viewController, as: .image(on: .iPhoneXsMax(.landscape)), named: "iphone-xs-max-alternative")
538      assertSnapshot(
539        matching: viewController, as: .image(on: .iPadMini(.portrait)), named: "ipad-mini-alternative")
540      assertSnapshot(
541        matching: viewController, as: .image(on: .iPad9_7(.portrait)), named: "ipad-9-7-alternative")
542      assertSnapshot(
543        matching: viewController, as: .image(on: .iPad10_2(.portrait)), named: "ipad-10-2-alternative")
544      assertSnapshot(
545        matching: viewController, as: .image(on: .iPadPro10_5(.portrait)), named: "ipad-pro-10-5-alternative")
546      assertSnapshot(
547        matching: viewController, as: .image(on: .iPadPro11(.portrait)), named: "ipad-pro-11-alternative")
548      assertSnapshot(
549        matching: viewController, as: .image(on: .iPadPro12_9(.portrait)), named: "ipad-pro-12-9-alternative")
550
551      allContentSizes.forEach { name, contentSize in
552          assertSnapshot(
553            matching: viewController,
554            as: .image(on: .iPhoneSe, traits: .init(preferredContentSizeCategory: contentSize)),
555            named: "iphone-se-\(name)"
556          )
557      }
558      #elseif os(tvOS)
559      assertSnapshot(
560        matching: viewController, as: .image(on: .tv), named: "tv")
561      assertSnapshot(
562        matching: viewController, as: .image(on: .tv4K), named: "tv4k")
563      #endif
564    }
565    #endif
566  }
567
568  func testTraitsEmbeddedInTabNavigation() {
569    #if os(iOS)
570    if #available(iOS 11.0, *) {
571      class MyViewController: UIViewController {
572        let topLabel = UILabel()
573        let leadingLabel = UILabel()
574        let trailingLabel = UILabel()
575        let bottomLabel = UILabel()
576
577        override func viewDidLoad() {
578          super.viewDidLoad()
579
580          self.navigationItem.leftBarButtonItem = .init(barButtonSystemItem: .add, target: nil, action: nil)
581
582          self.view.backgroundColor = .white
583
584          self.topLabel.text = "What's"
585          self.leadingLabel.text = "the"
586          self.trailingLabel.text = "point"
587          self.bottomLabel.text = "?"
588
589          self.topLabel.translatesAutoresizingMaskIntoConstraints = false
590          self.leadingLabel.translatesAutoresizingMaskIntoConstraints = false
591          self.trailingLabel.translatesAutoresizingMaskIntoConstraints = false
592          self.bottomLabel.translatesAutoresizingMaskIntoConstraints = false
593
594          self.view.addSubview(self.topLabel)
595          self.view.addSubview(self.leadingLabel)
596          self.view.addSubview(self.trailingLabel)
597          self.view.addSubview(self.bottomLabel)
598
599          NSLayoutConstraint.activate([
600            self.topLabel.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
601            self.topLabel.centerXAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
602            self.leadingLabel.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
603            self.leadingLabel.trailingAnchor.constraint(lessThanOrEqualTo: self.view.safeAreaLayoutGuide.centerXAnchor),
604//            self.leadingLabel.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
605            self.leadingLabel.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor),
606            self.trailingLabel.leadingAnchor.constraint(greaterThanOrEqualTo: self.view.safeAreaLayoutGuide.centerXAnchor),
607            self.trailingLabel.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
608            self.trailingLabel.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor),
609            self.bottomLabel.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
610            self.bottomLabel.centerXAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
611            ])
612        }
613
614        override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
615          super.traitCollectionDidChange(previousTraitCollection)
616          self.topLabel.font = .preferredFont(forTextStyle: .headline, compatibleWith: self.traitCollection)
617          self.leadingLabel.font = .preferredFont(forTextStyle: .body, compatibleWith: self.traitCollection)
618          self.trailingLabel.font = .preferredFont(forTextStyle: .body, compatibleWith: self.traitCollection)
619          self.bottomLabel.font = .preferredFont(forTextStyle: .subheadline, compatibleWith: self.traitCollection)
620          self.view.setNeedsUpdateConstraints()
621          self.view.updateConstraintsIfNeeded()
622        }
623      }
624
625      let myViewController = MyViewController()
626      let navController = UINavigationController(rootViewController: myViewController)
627      let viewController = UITabBarController()
628      viewController.setViewControllers([navController], animated: false)
629
630      assertSnapshot(matching: viewController, as: .image(on: .iPhoneSe), named: "iphone-se")
631      assertSnapshot(matching: viewController, as: .image(on: .iPhone8), named: "iphone-8")
632      assertSnapshot(matching: viewController, as: .image(on: .iPhone8Plus), named: "iphone-8-plus")
633      assertSnapshot(matching: viewController, as: .image(on: .iPhoneX), named: "iphone-x")
634      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXr), named: "iphone-xr")
635      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXsMax), named: "iphone-xs-max")
636      assertSnapshot(matching: viewController, as: .image(on: .iPadMini), named: "ipad-mini")
637      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7), named: "ipad-9-7")
638      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2), named: "ipad-10-2")
639      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5), named: "ipad-pro-10-5")
640      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11), named: "ipad-pro-11")
641      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9), named: "ipad-pro-12-9")
642
643      assertSnapshot(matching: viewController, as: .image(on: .iPhoneSe(.portrait)), named: "iphone-se")
644      assertSnapshot(matching: viewController, as: .image(on: .iPhone8(.portrait)), named: "iphone-8")
645      assertSnapshot(matching: viewController, as: .image(on: .iPhone8Plus(.portrait)), named: "iphone-8-plus")
646      assertSnapshot(matching: viewController, as: .image(on: .iPhoneX(.portrait)), named: "iphone-x")
647      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXr(.portrait)), named: "iphone-xr")
648      assertSnapshot(matching: viewController, as: .image(on: .iPhoneXsMax(.portrait)), named: "iphone-xs-max")
649      assertSnapshot(matching: viewController, as: .image(on: .iPadMini(.landscape)), named: "ipad-mini")
650      assertSnapshot(matching: viewController, as: .image(on: .iPad9_7(.landscape)), named: "ipad-9-7")
651      assertSnapshot(matching: viewController, as: .image(on: .iPad10_2(.landscape)), named: "ipad-10-2")
652      assertSnapshot(matching: viewController, as: .image(on: .iPadPro10_5(.landscape)), named: "ipad-pro-10-5")
653      assertSnapshot(matching: viewController, as: .image(on: .iPadPro11(.landscape)), named: "ipad-pro-11")
654      assertSnapshot(matching: viewController, as: .image(on: .iPadPro12_9(.landscape)), named: "ipad-pro-12-9")
655
656      assertSnapshot(
657        matching: viewController, as: .image(on: .iPhoneSe(.landscape)), named: "iphone-se-alternative")
658      assertSnapshot(
659        matching: viewController, as: .image(on: .iPhone8(.landscape)), named: "iphone-8-alternative")
660      assertSnapshot(
661        matching: viewController, as: .image(on: .iPhone8Plus(.landscape)), named: "iphone-8-plus-alternative")
662      assertSnapshot(
663        matching: viewController, as: .image(on: .iPhoneX(.landscape)), named: "iphone-x-alternative")
664      assertSnapshot(
665        matching: viewController, as: .image(on: .iPhoneXr(.landscape)), named: "iphone-xr-alternative")
666      assertSnapshot(
667        matching: viewController, as: .image(on: .iPhoneXsMax(.landscape)), named: "iphone-xs-max-alternative")
668      assertSnapshot(
669        matching: viewController, as: .image(on: .iPadMini(.portrait)), named: "ipad-mini-alternative")
670      assertSnapshot(
671        matching: viewController, as: .image(on: .iPad9_7(.portrait)), named: "ipad-9-7-alternative")
672      assertSnapshot(
673        matching: viewController, as: .image(on: .iPad10_2(.portrait)), named: "ipad-10-2-alternative")
674      assertSnapshot(
675        matching: viewController, as: .image(on: .iPadPro10_5(.portrait)), named: "ipad-pro-10-5-alternative")
676      assertSnapshot(
677        matching: viewController, as: .image(on: .iPadPro11(.portrait)), named: "ipad-pro-11-alternative")
678      assertSnapshot(
679        matching: viewController, as: .image(on: .iPadPro12_9(.portrait)), named: "ipad-pro-12-9-alternative")
680    }
681    #endif
682  }
683
684  func testCollectionViewsWithMultipleScreenSizes() {
685    #if os(iOS)
686
687    final class CollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
688
689      let flowLayout: UICollectionViewFlowLayout = {
690        let layout = UICollectionViewFlowLayout()
691        layout.scrollDirection = .horizontal
692        layout.minimumLineSpacing = 20
693        return layout
694      }()
695
696      lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
697
698      override func viewDidLoad() {
699        super.viewDidLoad()
700
701        view.backgroundColor = .white
702        view.addSubview(collectionView)
703
704        collectionView.backgroundColor = .white
705        collectionView.dataSource = self
706        collectionView.delegate = self
707        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
708        collectionView.translatesAutoresizingMaskIntoConstraints = false
709
710        NSLayoutConstraint.activate([
711          collectionView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
712          collectionView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
713          collectionView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
714          collectionView.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor)
715        ])
716
717        collectionView.reloadData()
718      }
719
720      override func viewDidLayoutSubviews() {
721        super.viewDidLayoutSubviews()
722        collectionView.collectionViewLayout.invalidateLayout()
723      }
724
725      override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
726        super.traitCollectionDidChange(previousTraitCollection)
727        collectionView.collectionViewLayout.invalidateLayout()
728      }
729
730      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
731        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
732        cell.contentView.backgroundColor = .orange
733        return cell
734      }
735
736      func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
737        return 20
738      }
739
740      func collectionView(
741        _ collectionView: UICollectionView,
742        layout collectionViewLayout: UICollectionViewLayout,
743        sizeForItemAt indexPath: IndexPath
744        ) -> CGSize {
745        return CGSize(
746          width: min(collectionView.frame.width - 50, 300),
747          height: collectionView.frame.height
748        )
749      }
750
751    }
752
753    let viewController = CollectionViewController()
754
755    assertSnapshots(matching: viewController, as: [
756      "ipad": .image(on: .iPadPro12_9),
757      "iphoneSe": .image(on: .iPhoneSe),
758      "iphone8": .image(on: .iPhone8),
759      "iphoneMax": .image(on: .iPhoneXsMax)
760    ])
761    #endif
762  }
763
764  func testTraitsWithView() {
765    #if os(iOS)
766    if #available(iOS 11.0, *) {
767      let label = UILabel()
768      label.font = .preferredFont(forTextStyle: .title1)
769      label.adjustsFontForContentSizeCategory = true
770      label.text = "What's the point?"
771
772      allContentSizes.forEach { name, contentSize in
773        assertSnapshot(
774          matching: label,
775          as: .image(traits: .init(preferredContentSizeCategory: contentSize)),
776          named: "label-\(name)"
777        )
778      }
779    }
780    #endif
781  }
782
783  func testTraitsWithViewController() {
784    #if os(iOS)
785    let label = UILabel()
786    label.font = .preferredFont(forTextStyle: .title1)
787    label.adjustsFontForContentSizeCategory = true
788    label.text = "What's the point?"
789
790    let viewController = UIViewController()
791    viewController.view.addSubview(label)
792
793    label.translatesAutoresizingMaskIntoConstraints = false
794    NSLayoutConstraint.activate([
795      label.leadingAnchor.constraint(equalTo: viewController.view.layoutMarginsGuide.leadingAnchor),
796      label.topAnchor.constraint(equalTo: viewController.view.layoutMarginsGuide.topAnchor),
797      label.trailingAnchor.constraint(equalTo: viewController.view.layoutMarginsGuide.trailingAnchor)
798    ])
799
800    allContentSizes.forEach { name, contentSize in
801      assertSnapshot(
802        matching: viewController,
803        as: .recursiveDescription(on: .iPhoneSe, traits: .init(preferredContentSizeCategory: contentSize)),
804        named: "label-\(name)"
805      )
806    }
807    #endif
808  }
809
810  func testUIBezierPath() {
811    #if os(iOS) || os(tvOS)
812    let path = UIBezierPath.heart
813
814    let osName: String
815    #if os(iOS)
816    osName = "iOS"
817    #elseif os(tvOS)
818    osName = "tvOS"
819    #endif
820
821    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
822      assertSnapshot(matching: path, as: .image, named: osName)
823    }
824
825    if #available(iOS 11.0, tvOS 11.0, *) {
826      assertSnapshot(matching: path, as: .elementsDescription, named: osName)
827    }
828    #endif
829  }
830
831  func testUIView() {
832    #if os(iOS)
833    let view = UIButton(type: .contactAdd)
834    assertSnapshot(matching: view, as: .image)
835    assertSnapshot(matching: view, as: .recursiveDescription)
836    #endif
837  }
838
839  func testUIViewControllerLifeCycle() {
840    #if os(iOS)
841    class ViewController: UIViewController {
842      let viewDidLoadExpectation: XCTestExpectation
843      let viewWillAppearExpectation: XCTestExpectation
844      let viewDidAppearExpectation: XCTestExpectation
845      let viewWillDisappearExpectation: XCTestExpectation
846      let viewDidDisappearExpectation: XCTestExpectation
847      init(viewDidLoadExpectation: XCTestExpectation,
848           viewWillAppearExpectation: XCTestExpectation,
849           viewDidAppearExpectation: XCTestExpectation,
850           viewWillDisappearExpectation: XCTestExpectation,
851           viewDidDisappearExpectation: XCTestExpectation){
852        self.viewDidLoadExpectation = viewDidLoadExpectation
853        self.viewWillAppearExpectation = viewWillAppearExpectation
854        self.viewDidAppearExpectation = viewDidAppearExpectation
855        self.viewWillDisappearExpectation = viewWillDisappearExpectation
856        self.viewDidDisappearExpectation = viewDidDisappearExpectation
857        super.init(nibName: nil, bundle: nil)
858      }
859      required init?(coder: NSCoder) {
860        fatalError("init(coder:) has not been implemented")
861      }
862      override func viewDidLoad() {
863        super.viewDidLoad()
864        viewDidLoadExpectation.fulfill()
865      }
866      override func viewWillAppear(_ animated: Bool) {
867        super.viewWillAppear(animated)
868        viewWillAppearExpectation.fulfill()
869      }
870      override func viewDidAppear(_ animated: Bool) {
871        super.viewDidAppear(animated)
872        viewDidAppearExpectation.fulfill()
873      }
874      override func viewWillDisappear(_ animated: Bool) {
875        super.viewWillDisappear(animated)
876        viewWillDisappearExpectation.fulfill()
877      }
878      override func viewDidDisappear(_ animated: Bool) {
879        super.viewDidDisappear(animated)
880        viewDidDisappearExpectation.fulfill()
881      }
882    }
883
884    let viewDidLoadExpectation = expectation(description: "viewDidLoad")
885    let viewWillAppearExpectation = expectation(description: "viewWillAppear")
886    let viewDidAppearExpectation = expectation(description: "viewDidAppear")
887    let viewWillDisappearExpectation = expectation(description: "viewWillDisappear")
888    let viewDidDisappearExpectation = expectation(description: "viewDidDisappear")
889    viewWillAppearExpectation.expectedFulfillmentCount = 4
890    viewDidAppearExpectation.expectedFulfillmentCount = 4
891    viewWillDisappearExpectation.expectedFulfillmentCount = 4
892    viewDidDisappearExpectation.expectedFulfillmentCount = 4
893
894    let viewController = ViewController(
895      viewDidLoadExpectation: viewDidLoadExpectation,
896      viewWillAppearExpectation: viewWillAppearExpectation,
897      viewDidAppearExpectation: viewDidAppearExpectation,
898      viewWillDisappearExpectation: viewWillDisappearExpectation,
899      viewDidDisappearExpectation: viewDidDisappearExpectation
900    )
901
902    assertSnapshot(matching: viewController, as: .image)
903    assertSnapshot(matching: viewController, as: .image)
904
905    wait(for: [
906      viewDidLoadExpectation,
907      viewWillAppearExpectation,
908      viewDidAppearExpectation,
909      viewWillDisappearExpectation,
910      viewDidDisappearExpectation,
911    ], timeout: 1.0, enforceOrder: true)
912    #endif
913  }
914
915  func testCALayer() {
916    #if os(iOS)
917    let layer = CALayer()
918    layer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
919    layer.backgroundColor = UIColor.red.cgColor
920    layer.borderWidth = 4.0
921    layer.borderColor = UIColor.black.cgColor
922    assertSnapshot(matching: layer, as: .image)
923    #endif
924  }
925
926  func testCALayerWithGradient() {
927    #if os(iOS)
928    let baseLayer = CALayer()
929    baseLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
930    let gradientLayer = CAGradientLayer()
931    gradientLayer.colors = [UIColor.red.cgColor, UIColor.yellow.cgColor]
932    gradientLayer.frame = baseLayer.frame
933    baseLayer.addSublayer(gradientLayer)
934    assertSnapshot(matching: baseLayer, as: .image)
935    #endif
936  }
937
938  func testViewControllerHierarchy() {
939    #if os(iOS)
940    let page = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
941    page.setViewControllers([UIViewController()], direction: .forward, animated: false)
942    let tab = UITabBarController()
943    tab.viewControllers = [
944      UINavigationController(rootViewController: page),
945      UINavigationController(rootViewController: UIViewController()),
946      UINavigationController(rootViewController: UIViewController()),
947      UINavigationController(rootViewController: UIViewController()),
948      UINavigationController(rootViewController: UIViewController())
949    ]
950    assertSnapshot(matching: tab, as: .hierarchy)
951    #endif
952  }
953
954  func testURLRequest() {
955    var get = URLRequest(url: URL(string: "https://www.pointfree.co/")!)
956    get.addValue("pf_session={}", forHTTPHeaderField: "Cookie")
957    get.addValue("text/html", forHTTPHeaderField: "Accept")
958    get.addValue("application/json", forHTTPHeaderField: "Content-Type")
959    assertSnapshot(matching: get, as: .raw, named: "get")
960    assertSnapshot(matching: get, as: .curl, named: "get-curl")
961
962    var getWithQuery = URLRequest(url: URL(string: "https://www.pointfree.co?key_2=value_2&key_1=value_1&key_3=value_3")!)
963    getWithQuery.addValue("pf_session={}", forHTTPHeaderField: "Cookie")
964    getWithQuery.addValue("text/html", forHTTPHeaderField: "Accept")
965    getWithQuery.addValue("application/json", forHTTPHeaderField: "Content-Type")
966    assertSnapshot(matching: getWithQuery, as: .raw, named: "get-with-query")
967    assertSnapshot(matching: getWithQuery, as: .curl, named: "get-with-query-curl")
968
969    var post = URLRequest(url: URL(string: "https://www.pointfree.co/subscribe")!)
970    post.httpMethod = "POST"
971    post.addValue("pf_session={\"user_id\":\"0\"}", forHTTPHeaderField: "Cookie")
972    post.addValue("text/html", forHTTPHeaderField: "Accept")
973    post.httpBody = Data("pricing[billing]=monthly&pricing[lane]=individual".utf8)
974    assertSnapshot(matching: post, as: .raw, named: "post")
975    assertSnapshot(matching: post, as: .curl, named: "post-curl")
976    
977    var postWithJSON = URLRequest(url: URL(string: "http://dummy.restapiexample.com/api/v1/create")!)
978    postWithJSON.httpMethod = "POST"
979    postWithJSON.addValue("application/json", forHTTPHeaderField: "Content-Type")
980    postWithJSON.addValue("application/json", forHTTPHeaderField: "Accept")
981    postWithJSON.httpBody = Data("{\"name\":\"tammy134235345235\", \"salary\":0, \"age\":\"tammy133\"}".utf8)
982    assertSnapshot(matching: postWithJSON, as: .raw, named: "post-with-json")
983    assertSnapshot(matching: postWithJSON, as: .curl, named: "post-with-json-curl")
984
985    var head = URLRequest(url: URL(string: "https://www.pointfree.co/")!)
986    head.httpMethod = "HEAD"
987    head.addValue("pf_session={}", forHTTPHeaderField: "Cookie")
988    assertSnapshot(matching: head, as: .raw, named: "head")
989    assertSnapshot(matching: head, as: .curl, named: "head-curl")
990
991    post = URLRequest(url: URL(string: "https://www.pointfree.co/subscribe")!)
992    post.httpMethod = "POST"
993    post.addValue("pf_session={\"user_id\":\"0\"}", forHTTPHeaderField: "Cookie")
994    post.addValue("application/json", forHTTPHeaderField: "Accept")
995    post.httpBody = Data("""
996                         {"pricing": {"lane": "individual","billing": "monthly"}}
997                         """.utf8)
998    _assertInlineSnapshot(matching: post, as: .raw(pretty: true), with: """
999    POST https://www.pointfree.co/subscribe
1000    Accept: application/json
1001    Cookie: pf_session={"user_id":"0"}
1002    
1003    {
1004      "pricing" : {
1005        "billing" : "monthly",
1006        "lane" : "individual"
1007      }
1008    }
1009    """)
1010  }
1011
1012  func testWebView() throws {
1013    #if os(iOS) || os(macOS)
1014    let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
1015      .deletingLastPathComponent()
1016      .appendingPathComponent("__Fixtures__/pointfree.html")
1017    let html = try String(contentsOf: fixtureUrl)
1018    let webView = WKWebView()
1019    webView.loadHTMLString(html, baseURL: nil)
1020    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
1021      assertSnapshot(
1022        matching: webView,
1023        as: .image(size: .init(width: 800, height: 600)),
1024        named: platform
1025      )
1026    }
1027    #endif
1028  }
1029
1030  func testViewWithZeroHeightOrWidth() {
1031    #if os(iOS) || os(tvOS)
1032    var rect = CGRect(x: 0, y: 0, width: 350, height: 0)
1033    var view = UIView(frame: rect)
1034    view.backgroundColor = .red
1035    assertSnapshot(matching: view, as: .image, named: "noHeight")
1036    
1037    rect = CGRect(x: 0, y: 0, width: 0, height: 350)
1038    view = UIView(frame: rect)
1039    view.backgroundColor = .green
1040    assertSnapshot(matching: view, as: .image, named: "noWidth")
1041
1042    rect = CGRect(x: 0, y: 0, width: 0, height: 0)
1043    view = UIView(frame: rect)
1044    view.backgroundColor = .blue
1045    assertSnapshot(matching: view, as: .image, named: "noWidth.noHeight")
1046    #endif
1047  }
1048
1049  func testEmbeddedWebView() throws {
1050    #if os(iOS)
1051    let label = UILabel()
1052    label.text = "Hello, Blob!"
1053
1054    let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
1055      .deletingLastPathComponent()
1056      .appendingPathComponent("__Fixtures__/pointfree.html")
1057    let html = try String(contentsOf: fixtureUrl)
1058    let webView = WKWebView()
1059    webView.loadHTMLString(html, baseURL: nil)
1060    webView.isHidden = true
1061
1062    let stackView = UIStackView(arrangedSubviews: [label, webView])
1063    stackView.axis = .vertical
1064
1065    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
1066      assertSnapshot(
1067        matching: stackView,
1068        as: .image(size: .init(width: 800, height: 600)),
1069        named: platform
1070      )
1071    }
1072    #endif
1073  }
1074
1075  #if os(iOS) || os(macOS)
1076  final class ManipulatingWKWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
1077    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
1078      webView.evaluateJavaScript("document.body.children[0].classList.remove(\"hero\")") // Change layout
1079    }
1080  }
1081  func testWebViewWithManipulatingNavigationDelegate() throws {
1082    let manipulatingWKWebViewNavigationDelegate = ManipulatingWKWebViewNavigationDelegate()
1083    let webView = WKWebView()
1084    webView.navigationDelegate = manipulatingWKWebViewNavigationDelegate
1085
1086    let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
1087      .deletingLastPathComponent()
1088      .appendingPathComponent("__Fixtures__/pointfree.html")
1089    let html = try String(contentsOf: fixtureUrl)
1090    webView.loadHTMLString(html, baseURL: nil)
1091    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
1092      assertSnapshot(
1093        matching: webView,
1094        as: .image(size: .init(width: 800, height: 600)),
1095        named: platform
1096      )
1097    }
1098    _ = manipulatingWKWebViewNavigationDelegate
1099  }
1100
1101  #if os(iOS) || os(macOS)
1102  func testWebViewWithRealUrl() throws {
1103    let manipulatingWKWebViewNavigationDelegate = ManipulatingWKWebViewNavigationDelegate()
1104    let webView = WKWebView()
1105    webView.navigationDelegate = manipulatingWKWebViewNavigationDelegate
1106
1107    webView.load(URLRequest(url: URL(string: "https://www.pointfree.co")!))
1108    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
1109      assertSnapshot(
1110        matching: webView,
1111        as: .image(size: .init(width: 800, height: 600)),
1112        named: platform
1113      )
1114    }
1115    _ = manipulatingWKWebViewNavigationDelegate
1116  }
1117  #endif
1118
1119  final class CancellingWKWebViewNavigationDelegate: NSObject, WKNavigationDelegate {
1120    func webView(
1121      _ webView: WKWebView,
1122      decidePolicyFor navigationAction: WKNavigationAction,
1123      decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
1124    ) {
1125      decisionHandler(.cancel)
1126    }
1127  }
1128  func testWebViewWithCancellingNavigationDelegate() throws {
1129    let cancellingWKWebViewNavigationDelegate = CancellingWKWebViewNavigationDelegate()
1130    let webView = WKWebView()
1131    webView.navigationDelegate = cancellingWKWebViewNavigationDelegate
1132
1133    let fixtureUrl = URL(fileURLWithPath: String(#file), isDirectory: false)
1134      .deletingLastPathComponent()
1135      .appendingPathComponent("__Fixtures__/pointfree.html")
1136    let html = try String(contentsOf: fixtureUrl)
1137    webView.loadHTMLString(html, baseURL: nil)
1138    if !ProcessInfo.processInfo.environment.keys.contains("GITHUB_WORKFLOW") {
1139      assertSnapshot(
1140        matching: webView,
1141        as: .image(size: .init(width: 800, height: 600)),
1142        named: platform
1143      )
1144    }
1145    _ = cancellingWKWebViewNavigationDelegate
1146  }
1147  #endif
1148
1149  @available(iOS 13.0, *)
1150  func testSwiftUIView_iOS() {
1151    #if os(iOS)
1152    struct MyView: SwiftUI.View {
1153      var body: some SwiftUI.View {
1154        HStack {
1155          Image(systemName: "checkmark.circle.fill")
1156            Text("Checked").fixedSize()
1157        }
1158        .padding(5)
1159        .background(RoundedRectangle(cornerRadius: 5.0).fill(Color.blue))
1160        .padding(10)
1161      }
1162    }
1163
1164    let view = MyView().background(Color.yellow)
1165
1166    assertSnapshot(matching: view, as: .image(traits: .init(userInterfaceStyle: .light)))
1167    assertSnapshot(matching: view, as: .image(layout: .sizeThatFits, traits: .init(userInterfaceStyle: .light)), named: "size-that-fits")
1168    assertSnapshot(matching: view, as: .image(layout: .fixed(width: 200.0, height: 100.0), traits: .init(userInterfaceStyle: .light)), named: "fixed")
1169    assertSnapshot(matching: view, as: .image(layout: .device(config: .iPhoneSe), traits: .init(userInterfaceStyle: .light)), named: "device")
1170    #endif
1171  }
1172
1173  @available(tvOS 13.0, *)
1174  func testSwiftUIView_tvOS() {
1175    #if os(tvOS)
1176    struct MyView: SwiftUI.View {
1177      var body: some SwiftUI.View {
1178        HStack {
1179          Image(systemName: "checkmark.circle.fill")
1180            Text("Checked").fixedSize()
1181        }
1182        .padding(5)
1183        .background(RoundedRectangle(cornerRadius: 5.0).fill(Color.blue))
1184        .padding(10)
1185      }
1186    }
1187    let view = MyView().background(Color.yellow)
1188
1189    assertSnapshot(matching: view, as: .image())
1190    assertSnapshot(matching: view, as: .image(layout: .sizeThatFits), named: "size-that-fits")
1191    assertSnapshot(matching: view, as: .image(layout: .fixed(width: 300.0, height: 100.0)), named: "fixed")
1192    assertSnapshot(matching: view, as: .image(layout: .device(config: .tv)), named: "device")
1193    #endif
1194  }
1195
1196  @available(*, deprecated)
1197  func testIsRecordingProxy() {
1198    SnapshotTesting.record = true
1199    XCTAssertEqual(isRecording, true)
1200
1201    SnapshotTesting.record = false
1202    XCTAssertEqual(isRecording, false)
1203  }
1204}
1205
1206#if os(iOS)
1207private let allContentSizes =
1208  [
1209    "extra-small": UIContentSizeCategory.extraSmall,
1210    "small": .small,
1211    "medium": .medium,
1212    "large": .large,
1213    "extra-large": .extraLarge,
1214    "extra-extra-large": .extraExtraLarge,
1215    "extra-extra-extra-large": .extraExtraExtraLarge,
1216    "accessibility-medium": .accessibilityMedium,
1217    "accessibility-large": .accessibilityLarge,
1218    "accessibility-extra-large": .accessibilityExtraLarge,
1219    "accessibility-extra-extra-large": .accessibilityExtraExtraLarge,
1220    "accessibility-extra-extra-extra-large": .accessibilityExtraExtraExtraLarge,
1221    ]
1222#endif
1223
1224#if os(Linux) || os(Windows)
1225extension SnapshotTestingTests {
1226  static var allTests : [(String, (SnapshotTestingTests) -> () throws -> Void)] {
1227    return [
1228      ("testAny", testAny),
1229      ("testAnySnapshotStringConvertible", testAnySnapshotStringConvertible),
1230      ("testAutolayout", testAutolayout),
1231      ("testDeterministicDictionaryAndSetSnapshots", testDeterministicDictionaryAndSetSnapshots),
1232      ("testEncodable", testEncodable),
1233      ("testMixedViews", testMixedViews),
1234      ("testMultipleSnapshots", testMultipleSnapshots),
1235      ("testNamedAssertion", testNamedAssertion),
1236      ("testPrecision", testPrecision),
1237      ("testSCNView", testSCNView),
1238      ("testSKView", testSKView),
1239      ("testTableViewController", testTableViewController),
1240      ("testTraits", testTraits),
1241      ("testTraitsEmbeddedInTabNavigation", testTraitsEmbeddedInTabNavigation),
1242      ("testTraitsWithView", testTraitsWithView),
1243      ("testUIView", testUIView),
1244      ("testURLRequest", testURLRequest),
1245      ("testWebView", testWebView),
1246    ]
1247  }
1248}
1249#endif
1250
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)