### Visualize diffs with command line tools Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md Example of a command line tool invocation for comparing two files. ```sh ksdiff /path/to/file1.png /path/to/file2.png ``` -------------------------------- ### Make a curl Request Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testURLRequest.get-with-query-curl.txt This command-line example shows how to make a curl request with specific headers and cookies to a given URL. It's useful for testing API endpoints or web services. ```bash curl \ --header "Accept: text/html" \ --header "Content-Type: application/json" \ --cookie "pf_session={}" \ "https://www.pointfree.co?key_1=value_1&key_2=value_2&key_3=value_3" ``` -------------------------------- ### Async Pullback for Asynchronous Transformations Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Create snapshotting strategies that handle asynchronous operations using asyncPullback. This example downloads an image from a URL before snapshotting. ```swift import SnapshotTesting import XCTest extension Snapshotting where Value == URL, Format == UIImage { static var downloadedImage: Snapshotting { Snapshotting.image.asyncPullback { Async { callback in URLSession.shared.dataTask(with: url) { data, _, _ in let image = data.flatMap(UIImage.init) ?? UIImage() callback(image) }.resume() } } } } class AsyncSnapshotTests: XCTestCase { func testAsyncSnapshot() { let imageURL = URL(string: "https://example.com/image.png")! // Will download and snapshot the image assertSnapshot(of: imageURL, as: .downloadedImage, timeout: 30) } } ``` -------------------------------- ### Configure Custom Diff Tool Command Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Set a custom command to be used for diffing snapshot failures. This example configures Kaleidoscope. ```swift SnapshotTesting.diffToolCommand = { "ksdiff \($0) \($1)" } ``` -------------------------------- ### Basic Snapshot Assertion in Swift Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Import SnapshotTesting and Testing modules to use assertSnapshot. This example demonstrates asserting a view controller's image representation. ```swift import SnapshotTesting import Testing @MainActor struct MyViewControllerTests { @Test func myViewController() { let vc = MyViewController() assertSnapshot(of: vc, as: .image) } } ``` -------------------------------- ### Configure Snapshot Testing for a Swift Testing Suite Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md Use test traits like `.snapshots` to override configuration options such as `record` and `diffTool` for an entire test suite. This example shows how to set recording to all modes and specify ksdiff as the diff tool. ```swift import SnapshotTesting @Suite(.snapshots(record: .all, diffTool: .ksdiff)) struct FeatureTests { … } ``` -------------------------------- ### SnapshotTesting/isRecording Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/isRecording-property-deprecation.md The `isRecording` property is deprecated. Use `withSnapshotTesting(record:diffTool:operation:)` instead for customizing record mode. Refer to the migration guide for more details. ```APIDOC ## Deprecation Notice: SnapshotTesting/isRecording ### Description The `isRecording` property is deprecated and should no longer be used. ### Reason for Deprecation To provide more granular control over snapshot testing behavior, including recording, diffing, and operations, the `withSnapshotTesting` function should be used. ### Recommended Alternative Use `withSnapshotTesting(record:diffTool:operation:)` to customize the record mode. ### Migration Guide For detailed instructions on migrating from `isRecording` to the new API, please refer to the documentation. ``` -------------------------------- ### Snapshot Testing with Device Configurations Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Configure snapshot tests for specific devices and orientations using the 'on:' parameter. Ensure consistency by using the same simulator for reference and comparison. ```swift assertSnapshot(of: vc, as: .image(on: .iPhoneSe)) assertSnapshot(of: vc, as: .recursiveDescription(on: .iPhoneSe)) ``` ```swift assertSnapshot(of: vc, as: .image(on: .iPhoneSe(.landscape))) assertSnapshot(of: vc, as: .recursiveDescription(on: .iPhoneSe(.landscape))) ``` ```swift assertSnapshot(of: vc, as: .image(on: .iPhoneX)) assertSnapshot(of: vc, as: .recursiveDescription(on: .iPhoneX)) ``` ```swift assertSnapshot(of: vc, as: .image(on: .iPadMini(.portrait))) assertSnapshot(of: vc, as: .recursiveDescription(on: .iPadMini(.portrait))) ``` -------------------------------- ### Snapshot Any Value with .dump and .description Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Use .dump for structured tree snapshots and .description for simple string representations. Ensure SnapshotTesting and XCTest are imported. ```swift import SnapshotTesting import XCTest struct ComplexModel { let id: Int let nested: NestedModel let items: [String] } struct NestedModel { let value: String let optional: Int? } class AnyValueSnapshotTests: XCTestCase { func testAnyValueSnapshots() { let model = ComplexModel( id: 42, nested: NestedModel(value: "test", optional: nil), items: ["a", "b", "c"] ) // Dump-based snapshot (structured tree format) assertSnapshot(of: model, as: .dump) // Records: // ▿ ComplexModel // - id: 42 // ▿ items: 3 elements // - "a" // - "b" // - "c" // ▿ nested: NestedModel // - optional: Optional.none // - value: "test" // Simple description assertSnapshot(of: model, as: .description) // Records: ComplexModel(id: 42, nested: NestedModel(value: "test", optional: nil), items: ["a", "b", "c"]) } } ``` -------------------------------- ### Create Custom Snapshot Strategies with Pullback Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Build custom snapshotting strategies by composing existing ones with pullback transformations. Requires SnapshotTesting and XCTest imports. ```swift import SnapshotTesting import XCTest // Custom model struct Chart { let data: [Double] let title: String } // Extend Snapshotting for custom types extension Snapshotting where Value == Chart, Format == String { static var textRepresentation: Snapshotting { SimplySnapshotting.lines.pullback { var output = "Chart: \(chart.title)\n" output += "Data: \(chart.data.map { String(format: "%.2f", $0) }.joined(separator: ", "))\n" output += "Min: \(chart.data.min() ?? 0), Max: \(chart.data.max() ?? 0)" return output } } } // Pullback from UIView strategy for custom rendering extension Snapshotting where Value == Chart, Format == UIImage { static var image: Snapshotting { Snapshotting.image.pullback { let chartView = ChartView(chart: chart) chartView.frame = CGRect(x: 0, y: 0, width: 300, height: 200) return chartView } } } class CustomStrategyTests: XCTestCase { func testCustomStrategies() { let chart = Chart(data: [1.0, 2.5, 3.0, 1.5], title: "Sales") assertSnapshot(of: chart, as: .textRepresentation) assertSnapshot(of: chart, as: .image) } } ``` -------------------------------- ### Defining an asynchronous strategy with initializer Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/CustomStrategies.md Uses the Snapshotting initializer to define an asynchronous strategy from scratch. ```swift extension Snapshotting where Value == WKWebView, Format == UIImage { public static let image = Snapshotting( pathExtension: "png", diffing: .image, asyncSnapshot: { webView in Async { callback in webView.takeSnapshot(with: nil) { image, error in callback(image!) } } } ) } ``` -------------------------------- ### Make a POST Request to Subscribe Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testURLRequest.post-curl.txt Use this command to make a POST request to the Pointfree subscription endpoint. Ensure you have the correct session cookie and data format. ```bash curl \ --request POST \ --header "Accept: text/html" \ --data "pricing[billing]=monthly&pricing[lane]=individual" \ --cookie "pf_session={"user_id":"0"}" \ "https://www.pointfree.co/subscribe" ``` -------------------------------- ### Creating an asynchronous strategy with asyncPullback Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/CustomStrategies.md Uses asyncPullback to handle callback-based APIs like WKWebView's snapshotting. ```swift extension Snapshotting where Value == WKWebView, Format == UIImage { public static let image: Snapshotting = Snapshotting .image .asyncPullback { webView in Async { callback in webView.takeSnapshot(with: nil) { image, error in callback(image!) } } } } ``` -------------------------------- ### Recording Snapshots in Swift Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Customize snapshot recording inline or using the withSnapshotTesting tool. Use record: .all to record all snapshots or record: .failed to record only failed ones. ```swift // Record just this one snapshot assertSnapshot(of: vc, as: .image, record: .all) ``` ```swift // Record all snapshots in a scope: withSnapshotTesting(record: .all) { assertSnapshot(of: vc1, as: .image) assertSnapshot(of: vc2, as: .image) assertSnapshot(of: vc3, as: .image) } ``` ```swift // Record all snapshot failures in a Swift Testing suite: @Suite(.snapshots(record: .failed)) struct FeatureTests {} ``` ```swift // Record all snapshot failures in an 'XCTestCase' subclass: class FeatureTests: XCTestCase { override func invokeTest() { withSnapshotTesting(record: .failed) { super.invokeTest() } } } ``` -------------------------------- ### Defining a strategy with pullback Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/CustomStrategies.md Extends Snapshotting to support UIViewController by pulling back from the UIView strategy. ```swift extension Snapshotting where Value == UIViewController, Format == UIImage { public static let image: Snapshotting = Snapshotting .image .pullback { viewController in viewController.view } } ``` -------------------------------- ### View a disk-based snapshot file Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/InlineSnapshotTesting/Documentation.docc/InlineSnapshotTesting.md Displays the contents of a snapshot file stored in the __Snapshots__ directory. ```sh $ cat __Snapshots__/MySnapshotTests/testMySnapshot.2.json { "id": 42, "name": "Blob" } ``` -------------------------------- ### Snapshotting UIViews and UIViewControllers Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Snapshot UIViews and UIViewControllers as images. Supports configurable device settings, precision, and trait collections. Ensure MyCustomView and MyViewController are defined elsewhere. ```swift import SnapshotTesting import XCTest class ViewSnapshotTests: XCTestCase { func testViewSnapshots() { let view = MyCustomView() let vc = MyViewController() // Basic image snapshot assertSnapshot(of: view, as: .image) assertSnapshot(of: vc, as: .image) // Specific device configurations assertSnapshot(of: vc, as: .image(on: .iPhoneSe)) assertSnapshot(of: vc, as: .image(on: .iPhoneSe(.landscape))) assertSnapshot(of: vc, as: .image(on: .iPhoneX)) assertSnapshot(of: vc, as: .image(on: .iPadMini(.portrait))) // With precision threshold (useful for animations/timing) assertSnapshot(of: vc, as: .image(precision: 0.98)) // With perceptual precision (mimics human eye ~98-99%) assertSnapshot(of: vc, as: .image(perceptualPrecision: 0.98)) // Custom size override assertSnapshot(of: view, as: .image(size: CGSize(width: 300, height: 200))) // With trait collection (dark mode, accessibility sizes) assertSnapshot(of: vc, as: .image( traits: UITraitCollection(userInterfaceStyle: .dark) )) // Draw hierarchy in key window (for UIAppearance/UIVisualEffects) assertSnapshot(of: vc, as: .image(drawHierarchyInKeyWindow: true)) } } ``` -------------------------------- ### Snapshotting with Traits Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/SnapshotsTrait.md This section covers the configuration of snapshot tests using traits, including options for specifying a diff tool and recording snapshots. ```APIDOC ## `SnapshotTesting/Testing/Trait/snapshots(diffTool:record:)` ### Description Configures snapshot tests with a specific diff tool and an option to record new snapshots. ### Method Not applicable (this is a configuration function). ### Endpoint Not applicable. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response None ## `Testing/Trait/snapshots(_:)` ### Description Configures snapshot tests with default settings. ### Method Not applicable (this is a configuration function). ### Endpoint Not applicable. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response None ``` -------------------------------- ### Snapshotting SwiftUI Views Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Snapshot SwiftUI views using layout configuration options similar to Preview layouts. Ensure ContentView is defined. ```swift import SnapshotTesting import SwiftUI import XCTest struct ContentView: View { var body: some View { VStack { Text("Hello, World!") Button("Tap me") { } } } } class SwiftUISnapshotTests: XCTestCase { func testSwiftUISnapshots() { let view = ContentView() // Fit to content size assertSnapshot(of: view, as: .image(layout: .sizeThatFits)) // Fixed size container assertSnapshot(of: view, as: .image(layout: .fixed(width: 300, height: 200))) // Device container assertSnapshot(of: view, as: .image(layout: .device(config: .iPhoneX))) // With traits assertSnapshot(of: view, as: .image( layout: .sizeThatFits, traits: UITraitCollection(userInterfaceStyle: .dark) )) } } ``` -------------------------------- ### Migrate XCTestCase configuration Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md Comparison of overriding invokeTest using global variables versus the new scoped withSnapshotTesting function. ```swift // Before class FeatureTests: XCTestCase { override func invokeTest() { isRecording = true diffTool = "ksdiff" defer { isRecording = false diffTool = nil } super.invokeTest() } } ``` ```swift // After class FeatureTests: XCTestCase { override func invokeTest() { withSnapshotTesting(record: .all, diffTool: .ksdiff) { super.invokeTest() } } } ``` -------------------------------- ### Migrate test function configuration Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md Comparison of the deprecated global variable approach versus the new scoped withSnapshotTesting function. ```swift // Before func testFeature() { isRecording = true diffTool = "ksdiff" assertSnapshot(…) } ``` ```swift // After func testFeature() { withSnapshotTesting(record: .all, diffTool: .ksdiff) { assertSnapshot(…) } } ``` -------------------------------- ### Defining a Snapshot Strategy Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/Snapshotting.md Methods for creating custom snapshotting strategies by defining path extensions, diffing logic, and snapshot generation. ```APIDOC ## init(pathExtension:diffing:snapshot:) ### Description Initializes a new snapshotting strategy with a specific file extension, diffing strategy, and snapshot generation closure. ### Parameters - **pathExtension** (String) - Required - The file extension for the snapshot file. - **diffing** (Diffing) - Required - The strategy used to compare snapshots. - **snapshot** (Closure) - Required - A closure that generates the snapshot data. ``` -------------------------------- ### Swift Package Manager Dependency Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Add SnapshotTesting as a dependency in your Package.swift file for projects using SwiftPM. Ensure it's added to a test target. ```swift dependencies: [ .package( url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.12.0" ), ] ``` ```swift targets: [ .target(name: "MyApp"), .testTarget( name: "MyAppTests", dependencies: [ "MyApp", .product(name: "SnapshotTesting", package: "swift-snapshot-testing"), ] ) ] ``` -------------------------------- ### Accessing existing image strategy Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/CustomStrategies.md Reference to the built-in image strategy for UIView. ```swift Snapshotting.image ``` -------------------------------- ### Create Employee Record via API Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testURLRequest.post-with-json-curl.txt Use this cURL command to send a POST request to create a new employee record. Ensure the Content-Type and Accept headers are set to application/json. The request body includes the employee's name, salary, and age. ```shell curl \ --request POST \ --header "Accept: application/json" \ --header "Content-Type: application/json" \ --data "{\"name\":\"tammy134235345235\", \"salary\":0, \"age\":\"tammy133\"}" \ "http://dummy.restapiexample.com/api/v1/create" ``` -------------------------------- ### Define a custom diff tool Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md Implementation of a custom diff tool using ImageMagick's compare command. ```swift extension SnapshotTestingConfiguration.DiffTool { static let compare = Self { "compare \"\($0)\" \"\($1)\" png: | open -f -a Preview.app" } } ``` -------------------------------- ### Snapshot View Hierarchies with .recursiveDescription and .hierarchy Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Debug view layouts by snapshotting view hierarchies using .recursiveDescription or controller structures with .hierarchy. Requires SnapshotTesting and XCTest imports. ```swift import SnapshotTesting import XCTest class ViewHierarchySnapshotTests: XCTestCase { func testViewHierarchySnapshots() { let button = UIButton(type: .system) button.setTitle("Tap", for: .normal) button.frame = CGRect(x: 0, y: 0, width: 100, height: 44) // Recursive view description assertSnapshot(of: button, as: .recursiveDescription) // Records: // > // | // With specific size assertSnapshot(of: button, as: .recursiveDescription(size: CGSize(width: 200, height: 60))) // View controller hierarchy let tabVC = UITabBarController() let nav1 = UINavigationController(rootViewController: UIViewController()) let nav2 = UINavigationController(rootViewController: UIViewController()) tabVC.viewControllers = [nav1, nav2] assertSnapshot(of: tabVC, as: .hierarchy) // Records: // , state: appeared, view: // | , state: appeared, view: // | | , state: appeared, view: // | , state: disappeared, view: ... } } ``` -------------------------------- ### POST /subscribe Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testURLRequest.post-json.txt Endpoint to create a new subscription for a user. ```APIDOC ## POST /subscribe ### Description Initiates a new subscription for the authenticated user. ### Method POST ### Endpoint https://www.pointfree.co/subscribe ### Request Body - **pricing** (object) - Required - Subscription details - **billing** (string) - Required - Billing cycle (e.g., "monthly") - **lane** (string) - Required - Subscription tier (e.g., "individual") ### Request Example { "pricing": { "billing": "monthly", "lane": "individual" } } ``` -------------------------------- ### Perform a standard snapshot assertion Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/InlineSnapshotTesting/Documentation.docc/InlineSnapshotTesting.md Uses the standard snapshot testing library to write snapshots to disk. ```swift assertSnapshot(of: value, as: .json) ``` -------------------------------- ### Snapshotting URLRequests as Raw HTTP or cURL Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Snapshot URL requests as raw HTTP format or cURL commands for API testing. Ensure the URLRequest is properly configured. ```swift import SnapshotTesting import XCTest class URLRequestSnapshotTests: XCTestCase { func testURLRequestSnapshots() { var request = URLRequest(url: URL(string: "https://api.example.com/users")!) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("Bearer token123", forHTTPHeaderField: "Authorization") request.httpBody = try? JSONEncoder().encode(["name": "Blobby"]) // Raw HTTP format assertSnapshot(of: request, as: .raw) // Records: // POST https://api.example.com/users // Authorization: Bearer token123 // Content-Type: application/json // // {"name":"Blobby"} // Pretty-printed JSON body assertSnapshot(of: request, as: .raw(pretty: true)) // cURL command format assertSnapshot(of: request, as: .curl) // Records: // curl \ // --request POST \ // --header "Authorization: Bearer token123" \ // --header "Content-Type: application/json" \ // --data "{\"name\":\"Blobby\"}" \ // "https://api.example.com/users" } } ``` -------------------------------- ### withSnapshotTesting - Configuration Scope Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Allows customizing snapshot testing configuration, such as record mode and diff tool settings, for a defined scope within your tests. ```APIDOC ## withSnapshotTesting - Configuration Scope ### Description Customize snapshot testing configuration for a defined scope, including record mode and diff tool settings. ### Method `withSnapshotTesting` ### Parameters - **record** (SnapshotTestingConfiguration.Record?) - Optional - Sets the recording mode for the scope. Options include `.all`, `.missing`, `.never`, `.failed`. - **diffTool** (SnapshotTestingConfiguration.DiffTool?) - Optional - Specifies a custom diff tool for comparing snapshots. - **block** (() -> Void) - Required - The closure containing the snapshot tests to be configured. ### Request Example ```swift import SnapshotTesting import XCTest class FeatureTests: XCTestCase { // Override for entire test class override func invokeTest() { withSnapshotTesting(record: .all, diffTool: .ksdiff) { super.invokeTest() } } func testFeature() { // Record all snapshots in this scope withSnapshotTesting(record: .all) { assertSnapshot(of: view1, as: .image) assertSnapshot(of: view2, as: .image) assertSnapshot(of: view3, as: .image) } // Never record (fail if missing) - useful for CI withSnapshotTesting(record: .never) { assertSnapshot(of: criticalView, as: .image) } // Custom diff tool withSnapshotTesting(diffTool: .init { current, failed in "compare \"\(current)\" \"\(failed)\" png: | open -f -a Preview.app" }) { assertSnapshot(of: imageView, as: .image) } } } ``` ### Response This function does not return a value. It applies the specified configuration to the snapshot tests executed within the provided block. ``` -------------------------------- ### Snapshot Testing URL Requests Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Snapshot test URL requests using the .raw strategy to capture the request details, including method, headers, and body. ```swift assertSnapshot(of: urlRequest, as: .raw) // POST http://localhost:8080/account // Cookie: pf_session={"userId":"1"} // // email=blob%40pointfree.co&name=Blob ``` -------------------------------- ### withSnapshotTesting(record:diffTool:operation:) Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/WithSnapshotTesting.md This function allows you to configure snapshot testing with options for recording, diffing, and custom operations. ```APIDOC ## `withSnapshotTesting(record:diffTool:operation:)-2kuyr` ### Description Configures snapshot testing with options for recording, diffing, and custom operations. ### Topics - `withSnapshotTesting(record:diffTool:operation:)-6bsqw` ``` -------------------------------- ### Configure Snapshot Testing with Swift Testing Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Applies snapshot configuration using the .snapshots trait at the suite or test level. Overrides can be specified for individual tests. ```swift import SnapshotTesting import Testing // Configure entire suite @Suite(.snapshots(record: .failed, diffTool: .ksdiff)) struct FeatureTests { @Test func testView() { let view = MyView() assertSnapshot(of: view, as: .image) } // Override for specific test @Test(.snapshots(record: .all)) func testNewFeature() { let view = NewFeatureView() assertSnapshot(of: view, as: .image) } } // Using default configuration @Suite(.snapshots) struct DefaultTests { @Test func testBasic() { assertSnapshot(of: MyView(), as: .image) } } ``` -------------------------------- ### Transforming Strategies Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/Snapshotting.md Methods to transform existing snapshotting strategies using pullbacks or asynchronous operations. ```APIDOC ## pullback(_:) ### Description Transforms a snapshotting strategy by mapping the input type. ## asyncPullback(_:) ### Description Asynchronously transforms a snapshotting strategy by mapping the input type. ## wait(for:on:) ### Description Wraps a strategy to wait for a specific duration or condition before performing the snapshot. ``` -------------------------------- ### Basic Snapshot Assertions Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Use assertSnapshot with a value and a strategy to capture its current state. Supports image and recursive description formats. ```swift assertSnapshot(of: vc, as: .image) assertSnapshot(of: vc, as: .recursiveDescription) ``` -------------------------------- ### Update custom Diffing strategy implementation Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.19.md Migrate custom Diffing definitions to use the diffV2 static method and return DiffAttachment values instead of XCTAttachment. ```swift // Before extension Diffing where Value == MyImage { static let myImage = Diffing( toData: { $0.pngData()! }, fromData: { MyImage(data: $0)! } ) { old, new in guard old != new else { return nil } let oldAttachment = XCTAttachment(image: old) oldAttachment.name = "reference" let newAttachment = XCTAttachment(image: new) newAttachment.name = "failure" return ( "Images did not match", [oldAttachment, newAttachment] ) } } ``` ```swift // After extension Diffing where Value == MyImage { static let myImage = Diffing.diff( toData: { $0.pngData()! }, fromData: { MyImage(data: $0)! } ) { old, new in guard old != new else { return nil } return ( "Images did not match", [ .data(old.pngData()!, name: "reference.png"), .data(new.pngData()!, name: "failure.png"), ] ) } } ``` -------------------------------- ### Snapshotting Encodable Values as JSON or Property List Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Snapshot Encodable values as formatted JSON or property list XML. Ensure the User struct conforms to Codable. ```swift import SnapshotTesting import XCTest struct User: Codable { let id: Int let name: String let bio: String let createdAt: Date } class EncodableSnapshotTests: XCTestCase { func testEncodableSnapshots() { let user = User( id: 1, name: "Blobby", bio: "Blobbed around the world.", createdAt: Date(timeIntervalSince1970: 0) ) // JSON snapshot (pretty-printed, sorted keys) assertSnapshot(of: user, as: .json) // Records: // { // "bio" : "Blobbed around the world.", // "createdAt" : -978307200, // "id" : 1, // "name" : "Blobby" // } // Property list snapshot (XML format) assertSnapshot(of: user, as: .plist) // Records XML plist representation // Custom JSON encoder let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 encoder.outputFormatting = [.prettyPrinted, .sortedKeys] assertSnapshot(of: user, as: .json(encoder)) } } ``` -------------------------------- ### View an inline snapshot assertion with recorded data Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/InlineSnapshotTesting/Documentation.docc/InlineSnapshotTesting.md Shows how the library automatically inserts the snapshot as a trailing closure after a test run. ```swift assertInlineSnapshot(of: value, as: .json) { // ❌ """ { "id": 42, "name": "Blob" } """ } ``` -------------------------------- ### assertSnapshots - Multiple Strategies at Once Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Asserts a value against multiple snapshot strategies simultaneously, which is useful for testing the same view in various formats or device configurations. ```APIDOC ## assertSnapshots - Multiple Strategies at Once ### Description Asserts a value against multiple snapshot strategies simultaneously. Useful for testing the same view in multiple formats or device configurations. ### Method `assertSnapshots` ### Parameters - **value** (autoclosure () throws -> Value) - Required - The value to snapshot. - **as** ([String: Snapshotting]) - Required - A dictionary where keys are names for the strategies and values are the snapshotting strategies. ### Request Example ```swift import SnapshotTesting import XCTest class UserTests: XCTestCase { func testUser() { let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.") // Test with multiple named strategies assertSnapshots(of: user, as: [ "json": .json, "plist": .plist, "dump": .dump ]) // Test view controller in multiple device configurations let vc = ProfileViewController(user: user) assertSnapshots(of: vc, as: [ "iPhone-SE": .image(on: .iPhoneSe), "iPhone-X": .image(on: .iPhoneX), "iPad-Mini": .image(on: .iPadMini(.portrait)) ]) } } ``` ### Response This function does not return a value directly. It fails the test if any of the snapshot comparisons fail. ``` -------------------------------- ### verifySnapshot - Custom Assert Helpers Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Allows building custom snapshot assertion helpers by returning an optional failure message instead of directly failing the test. ```APIDOC ## verifySnapshot - Custom Assert Helpers ### Description Build custom snapshot assertion helpers by using `verifySnapshot`, which returns an optional failure message instead of failing the test directly. ### Method `verifySnapshot` ### Parameters - **value** (autoclosure () throws -> Value) - Required - The value to snapshot. - **as** (Snapshotting) - Required - The snapshot strategy to use. - **named** (String?) - Optional - A name for the snapshot. - **record** (SnapshotTestingConfiguration.Record?) - Optional - Enables recording snapshots. - **snapshotDirectory** (String) - Required - The directory to save snapshots. - **timeout** (TimeInterval) - Optional - Custom timeout for asynchronous content. Defaults to 5 seconds. - **file** (StaticString) - Internal use for test file location. - **testName** (String) - Internal use for test function name. ### Request Example ```swift import SnapshotTesting import XCTest public func myAssertSnapshot( of value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, record: SnapshotTestingConfiguration.Record? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, line: UInt = #line ) { // Custom snapshot directory based on environment variable let snapshotDirectory = ProcessInfo.processInfo.environment["SNAPSHOT_REFERENCE_DIR"]! + "/" + URL(fileURLWithPath: "\(file)").deletingPathExtension().lastPathComponent let failure = verifySnapshot( of: try value(), as: snapshotting, named: name, record: record, snapshotDirectory: snapshotDirectory, timeout: timeout, file: file, testName: testName ) guard let message = failure else { return } XCTFail(message, file: file, line: line) } ``` ### Response - **failure** (String?) - An optional string describing the failure message if the snapshot comparison fails. Returns `nil` if the assertion passes. ``` -------------------------------- ### verifySnapshot(of:as:named:record:snapshotDirectory:timeout:file:testName:line:) Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/AssertSnapshot.md Custom assertion function for verifying snapshots with specific directory configurations. ```APIDOC ## verifySnapshot(of:as:named:record:snapshotDirectory:timeout:file:testName:line:) ### Description Verifies a snapshot with custom directory path support. ### Parameters - **of** (Any) - The value to snapshot. - **as** (Snapshotting) - The strategy to use. - **named** (String?) - Optional name for the snapshot. - **record** (Bool) - Whether to record. - **snapshotDirectory** (String?) - Custom directory for storing snapshots. - **timeout** (TimeInterval) - Timeout duration. - **file** (StaticString) - File path. - **testName** (String) - Test name. - **line** (UInt) - Line number. ``` -------------------------------- ### Snapshot Testing with Mirror Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/README.md Snapshot test any value by default using its Mirror representation, which provides a structural dump of its properties. ```swift assertSnapshot(of: user, as: .dump) // ▿ User // - bio: "Blobbed around the world." // - id: 1 // - name: "Blobby" ``` -------------------------------- ### Creating Custom Assertions with verifySnapshot Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Use verifySnapshot to build custom assertion helpers that return failure messages instead of triggering immediate test failures. ```swift import SnapshotTesting import XCTest public func myAssertSnapshot( of value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, record: SnapshotTestingConfiguration.Record? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, line: UInt = #line ) { // Custom snapshot directory based on environment variable let snapshotDirectory = ProcessInfo.processInfo.environment["SNAPSHOT_REFERENCE_DIR"]! + "/" + URL(fileURLWithPath: "\(file)").deletingPathExtension().lastPathComponent let failure = verifySnapshot( of: try value(), as: snapshotting, named: name, record: record, snapshotDirectory: snapshotDirectory, timeout: timeout, file: file, testName: testName ) guard let message = failure else { return } XCTFail(message, file: file, line: line) } ``` -------------------------------- ### Record Inline Snapshots Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Uses assertInlineSnapshot to store snapshots directly in the test source file. The source code is automatically updated during the recording phase. ```swift import InlineSnapshotTesting import XCTest class InlineSnapshotTests: XCTestCase { func testInlineSnapshot() { let user = User(id: 1, name: "Blobby") // First run records the snapshot inline in the source assertInlineSnapshot(of: user, as: .json) { """ { "id" : 1, "name" : "Blobby" } """ } // With custom message on failure assertInlineSnapshot( of: user, as: .dump, message: "User dump changed unexpectedly" ) { """ ▿ User - id: 1 - name: "Blobby" """ } } } ``` -------------------------------- ### Deprecation Notice for diffTool Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/diffTool-property-deprecation.md The `diffTool` functionality is deprecated. Use `withSnapshotTesting(record:diffTool:operation:)` instead. ```APIDOC ## Deprecated `diffTool` ### Description The `diffTool` parameter is deprecated. It was used to customize the diff tool for snapshot comparisons. ### Method N/A (This is a deprecation notice, not an API endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A ### Migration Note Use `withSnapshotTesting(record:diffTool:operation:)` to customize the diff tool. Refer to for migration details. ``` -------------------------------- ### Define Path Coordinates Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testCGPath.macOS.txt Represents a series of path commands for drawing a shape. ```text MoveTo (0.0, 0.0) LineTo (0.0, 60.0) QuadCurveTo (3.75, 86.25) (30.0, 90.0) QuadCurveTo (56.25, 86.25) (60.0, 60.0) CurveTo (75.0, 60.0) (90.0, 45.0) (90.0, 30.0) CurveTo (90.0, 15.0) (75.0, 0.0) (60.0, 0.0) LineTo (0.0, 0.0) Close ``` ```text MoveTo (90.0, 75.0) CurveTo (90.0, 83.284) (83.284, 90.0) (75.0, 90.0) CurveTo (66.716, 90.0) (60.0, 83.284) (60.0, 75.0) CurveTo (60.0, 66.716) (66.716, 60.0) (75.0, 60.0) CurveTo (83.284, 60.0) (90.0, 66.716) (90.0, 75.0) Close ``` -------------------------------- ### Configuring Snapshot Scope with withSnapshotTesting Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Use withSnapshotTesting to apply specific recording modes or custom diff tools to a block of assertions. ```swift import SnapshotTesting import XCTest class FeatureTests: XCTestCase { // Override for entire test class override func invokeTest() { withSnapshotTesting(record: .all, diffTool: .ksdiff) { super.invokeTest() } } func testFeature() { // Record all snapshots in this scope withSnapshotTesting(record: .all) { assertSnapshot(of: view1, as: .image) assertSnapshot(of: view2, as: .image) assertSnapshot(of: view3, as: .image) } // Never record (fail if missing) - useful for CI withSnapshotTesting(record: .never) { assertSnapshot(of: criticalView, as: .image) } // Custom diff tool withSnapshotTesting(diffTool: .init { current, failed in "compare \"\(current)\" \"\(failed)\" png: | open -f -a Preview.app" }) { assertSnapshot(of: imageView, as: .image) } } } ``` -------------------------------- ### Create Employee API Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testURLRequest.post-with-json.txt This endpoint is used to create a new employee record. It accepts employee details in the request body and returns the created record. ```APIDOC ## POST /api/v1/create ### Description Creates a new employee record with the provided details. ### Method POST ### Endpoint http://dummy.restapiexample.com/api/v1/create ### Parameters #### Request Body - **name** (string) - Required - The name of the employee. - **salary** (integer) - Required - The salary of the employee. - **age** (string) - Required - The age of the employee. ### Request Example { "name": "tammy134235345235", "salary": 0, "age": "tammy133" } ### Response #### Success Response (200) - **name** (string) - The name of the created employee. - **salary** (integer) - The salary of the created employee. - **age** (string) - The age of the created employee. - **id** (integer) - The unique identifier of the created employee. #### Response Example { "name": "tammy134235345235", "salary": 0, "age": "tammy133", "id": 1 } ``` -------------------------------- ### Asserting Multiple Strategies with assertSnapshots Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Use assertSnapshots to validate a single value against multiple formats or device configurations simultaneously. ```swift import SnapshotTesting import XCTest class UserTests: XCTestCase { func testUser() { let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.") // Test with multiple named strategies assertSnapshots(of: user, as: [ "json": .json, "plist": .plist, "dump": .dump ]) // Test view controller in multiple device configurations let vc = ProfileViewController(user: user) assertSnapshots(of: vc, as: [ "iPhone-SE": .image(on: .iPhoneSe), "iPhone-X": .image(on: .iPhoneX), "iPad-Mini": .image(on: .iPadMini(.portrait)) ]) } } ``` -------------------------------- ### Define Path Coordinates Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSBezierPath.macOS.txt Represents a sequence of drawing commands for a vector path. ```text MoveTo (0.0, 0.0) LineTo (0.0, 60.0) CurveTo (0.0, 75.0) (15.0, 90.0) (30.0, 90.0) CurveTo (45.0, 90.0) (60.0, 75.0) (60.0, 60.0) CurveTo (75.0, 60.0) (90.0, 45.0) (90.0, 30.0) CurveTo (90.0, 15.0) (75.0, 0.0) (60.0, 0.0) LineTo (0.0, 0.0) Close ``` ```text MoveTo (85.607, 64.393) CurveTo (91.464, 70.251) (91.464, 79.749) (85.607, 85.607) CurveTo (79.749, 91.464) (70.251, 91.464) (64.393, 85.607) CurveTo (58.536, 79.749) (58.536, 70.251) (64.393, 64.393) CurveTo (70.251, 58.536) (79.749, 58.536) (85.607, 64.393) ``` -------------------------------- ### Configure Snapshots with `withSnapshotTesting` in XCTest Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md Override `diffTool` and `record` properties for all tests in an `XCTestCase` subclass by wrapping the test invocation in `withSnapshotTesting`. ```swift class FeatureTests: XCTestCase { override func invokeTest() { withSnapshotTesting(record: .failed, diffTool: .ksdiff) { super.invokeTest() } } } ``` -------------------------------- ### View test failure message Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/InlineSnapshotTesting/Documentation.docc/InlineSnapshotTesting.md Displays the console output when a new snapshot is automatically recorded. ```text ❌ failed - Automatically recorded a new snapshot. Re-run "testMySnapshot" to test against the newly-recorded snapshot. ``` -------------------------------- ### Perform an inline snapshot assertion Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/InlineSnapshotTesting/Documentation.docc/InlineSnapshotTesting.md Uses the inline snapshot testing library to write snapshots directly into the test file. ```swift assertInlineSnapshot(of: value, as: .json) ``` -------------------------------- ### Asserting Snapshots with assertSnapshot Source: https://context7.com/pointfreeco/swift-snapshot-testing/llms.txt Use assertSnapshot to compare a value against a reference snapshot. Supports custom naming, recording modes, and timeouts for asynchronous content. ```swift import SnapshotTesting import XCTest class MyViewControllerTests: XCTestCase { func testMyViewController() { let vc = MyViewController() // Basic image snapshot assertSnapshot(of: vc, as: .image) // Named snapshot for multiple assertions in one test assertSnapshot(of: vc, as: .image, named: "default-state") // With recording enabled for this assertion only assertSnapshot(of: vc, as: .image, record: .all) // With custom timeout for async content assertSnapshot(of: vc, as: .image, timeout: 10) } } ``` -------------------------------- ### assertSnapshots(of:as:record:timeout:file:testName:line:) Source: https://github.com/pointfreeco/swift-snapshot-testing/blob/main/Sources/SnapshotTesting/Documentation.docc/Extensions/AssertSnapshot.md Asserts that a value matches multiple snapshots. ```APIDOC ## assertSnapshots(of:as:record:timeout:file:testName:line:) ### Description Asserts that a value matches multiple provided snapshot strategies. ### Parameters - **of** (Any) - The value to snapshot. - **as** ([String: Snapshotting]) - A dictionary of snapshot strategies. - **record** (Bool) - Whether to record new snapshots. - **timeout** (TimeInterval) - The timeout for the snapshot operations. - **file** (StaticString) - The file path of the test. - **testName** (String) - The name of the test. - **line** (UInt) - The line number of the test. ```