From d36f0607d4e1e7f072d21bad3589bb53e61c193f Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:03:11 -0400 Subject: [PATCH 01/15] Update Package.swift (#861) --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index fd528bc50..cdfb64d6b 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/apple/swift-syntax", "508.0.1"..<"601.0.0") + .package(url: "https://github.com/apple/swift-syntax", "509.0.0"..<"601.0.0-prerelease"), ], targets: [ .target( From d2341adf332dc7341b4acad8761dff65e905d63c Mon Sep 17 00:00:00 2001 From: mbrandonw Date: Wed, 26 Jun 2024 15:04:14 +0000 Subject: [PATCH 02/15] Run swift-format --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index cdfb64d6b..6d013b163 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/apple/swift-syntax", "509.0.0"..<"601.0.0-prerelease"), + .package(url: "https://github.com/apple/swift-syntax", "509.0.0"..<"601.0.0-prerelease") ], targets: [ .target( From fa43e37127d86b35b8edbf324a88371bc53aaac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20B=C4=85k?= Date: Thu, 4 Jul 2024 03:03:18 +0200 Subject: [PATCH 03/15] Add .editorconfig for consistent code formatting (#864) --- .editorconfig | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..410ff6c9e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true From 172f441d2817e7c2d3e4fa2481088c2529b362fa Mon Sep 17 00:00:00 2001 From: Thomas Grapperon <35562418+tgrapperon@users.noreply.github.com> Date: Thu, 4 Jul 2024 04:03:33 +0200 Subject: [PATCH 04/15] Configure `isRecording` default value with launch arguments (#862) --- Sources/SnapshotTesting/AssertSnapshot.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 9d4a24318..8e7640a62 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -9,7 +9,16 @@ import XCTest public var diffTool: String? = nil /// Whether or not to record all new references. -public var isRecording = false +public var isRecording: Bool = { + let args = ProcessInfo.processInfo.arguments + if let index = args.firstIndex(of: "-co.pointfree.SnapshotTesting.IsRecording"), + index < args.count - 1, + args[index + 1] == "1" + { + return true + } + return false +}() /// Whether or not to record all new references. /// From f2fe5df6ba031cccb02fa47b727fedb861754842 Mon Sep 17 00:00:00 2001 From: stephencelis Date: Thu, 4 Jul 2024 02:04:06 +0000 Subject: [PATCH 05/15] Run swift-format --- Sources/SnapshotTesting/AssertSnapshot.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 8e7640a62..f5b49b3cf 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -12,8 +12,8 @@ public var diffTool: String? = nil public var isRecording: Bool = { let args = ProcessInfo.processInfo.arguments if let index = args.firstIndex(of: "-co.pointfree.SnapshotTesting.IsRecording"), - index < args.count - 1, - args[index + 1] == "1" + index < args.count - 1, + args[index + 1] == "1" { return true } From 635114c52e0fe6721ceb5f5cca0456b3755a86ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20S=C3=B8rensen?= Date: Thu, 4 Jul 2024 04:12:38 +0200 Subject: [PATCH 06/15] Add `diffToolBuilder` for building complex diff command messages (#840) * Add SnapshotTesting.diffToolBuilder for building complex diff command messages It takes the existing and the failure snapshot as arguments, and thus complex commands which are not just prefixed with the existing diffTool can be created. * Rename diffToolBuilder to diffToolCommand, replace diffTool with custom getter/setter --- README.md | 4 ++-- Sources/SnapshotTesting/AssertSnapshot.swift | 23 ++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fae8506ac..a4fcae17f 100644 --- a/README.md +++ b/README.md @@ -210,9 +210,9 @@ targets: [ - **`Codable` support**. Snapshot encodable data structures into their JSON and property list representations. - **Custom diff tool integration**. Configure failure messages to print diff commands for - [Kaleidoscope](https://kaleidoscope.app) (or your diff tool of choice). + [Kaleidoscope](https://kaleidoscope.app) or your diff tool of choice. ``` swift - SnapshotTesting.diffTool = "ksdiff" + SnapshotTesting.diffToolCommand = { "ksdiff \($0) \($1)" } ``` [available-strategies]: https://swiftpackageindex.com/pointfreeco/swift-snapshot-testing/main/documentation/snapshottesting/snapshotting diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index f5b49b3cf..c1816568c 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,12 +1,28 @@ import XCTest /// Enhances failure messages with a command line diff tool expression that can be copied and pasted -/// into a terminal. +/// into a terminal. For more complex difftool needs, see `diffToolCommand`. /// /// ```swift /// diffTool = "ksdiff" /// ``` -public var diffTool: String? = nil +public var diffTool: String? { + get { diffToolCommand?("", "").trimmingCharacters(in: .whitespaces) } + set { + diffToolCommand = newValue.map { value in + { [value, $0, $1].joined(separator: " ") } + } + } +} + +/// Enhances failure messages with a diff tool expression created by the closure, such as an clickable +/// URL or a complex command. The closure will receive the existing screenshot path and the failed +/// screenshot path as arguments. +/// +/// ```swift +/// diffToolCommand = { "compare \"\($0)\" \"\($1)\" png: | open -f -a Preview.app" } +/// ``` +public var diffToolCommand: ((String, String) -> String)? /// Whether or not to record all new references. public var isRecording: Bool = { @@ -333,8 +349,7 @@ public func verifySnapshot( } let diffMessage = - diffTool - .map { "\($0) \"\(snapshotFileUrl.path)\" \"\(failedSnapshotFileUrl.path)\"" } + diffToolCommand?(snapshotFileUrl.path, failedSnapshotFileUrl.path) ?? """ @\(minus) "\(snapshotFileUrl.absoluteString)" From 02ff55362ca0380dd5a8d33d76b91f02e2290d61 Mon Sep 17 00:00:00 2001 From: stephencelis Date: Thu, 4 Jul 2024 02:13:15 +0000 Subject: [PATCH 07/15] Run swift-format --- Sources/SnapshotTesting/AssertSnapshot.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index c1816568c..617495aa2 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -7,12 +7,12 @@ import XCTest /// diffTool = "ksdiff" /// ``` public var diffTool: String? { - get { diffToolCommand?("", "").trimmingCharacters(in: .whitespaces) } - set { - diffToolCommand = newValue.map { value in - { [value, $0, $1].joined(separator: " ") } - } + get { diffToolCommand?("", "").trimmingCharacters(in: .whitespaces) } + set { + diffToolCommand = newValue.map { value in + { [value, $0, $1].joined(separator: " ") } } + } } /// Enhances failure messages with a diff tool expression created by the closure, such as an clickable From 346f84cb0ed3d8e6ec3377545429520762f78e47 Mon Sep 17 00:00:00 2001 From: NachoSoto Date: Wed, 3 Jul 2024 19:23:46 -0700 Subject: [PATCH 08/15] New `canGenerateNewSnapshots` to avoid automatically creating missing ones in CI (#768) * New `canGenerateNewSnapshots` to avoid automatically creating missing ones in CI Fixes #748. * Update AssertSnapshot.swift --- Sources/SnapshotTesting/AssertSnapshot.swift | 6 +++++- .../SnapshotTesting/Documentation.docc/SnapshotTesting.md | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 617495aa2..216b35b6c 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -36,6 +36,10 @@ public var isRecording: Bool = { return false }() +/// Whether or not to create snapshots if they aren't found. +/// It's recommended to set this to `false` in CI to avoid false positives if the test is retried. +public var canGenerateNewSnapshots = true + /// Whether or not to record all new references. /// /// Due to a name clash in Xcode 12, this has been renamed to `isRecording`. @@ -281,7 +285,7 @@ public func verifySnapshot( return "Couldn't snapshot value" } - guard !recording, fileManager.fileExists(atPath: snapshotFileUrl.path) else { + guard !recording, canGenerateNewSnapshots, fileManager.fileExists(atPath: snapshotFileUrl.path) else { try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) #if !os(Linux) && !os(Windows) if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { diff --git a/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md b/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md index 92a11e84c..473bee907 100644 --- a/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md +++ b/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md @@ -18,6 +18,7 @@ Powerfully flexible snapshot testing. ### Configuration - ``isRecording`` +- ``canGenerateNewSnapshots`` - ``diffTool`` ### Deprecations From 47420605fa85a311a02c4a89612d7ec24e103c49 Mon Sep 17 00:00:00 2001 From: mbrandonw Date: Thu, 4 Jul 2024 02:24:19 +0000 Subject: [PATCH 09/15] Run swift-format --- Sources/SnapshotTesting/AssertSnapshot.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 216b35b6c..772a35681 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -285,7 +285,8 @@ public func verifySnapshot( return "Couldn't snapshot value" } - guard !recording, canGenerateNewSnapshots, fileManager.fileExists(atPath: snapshotFileUrl.path) else { + guard !recording, canGenerateNewSnapshots, fileManager.fileExists(atPath: snapshotFileUrl.path) + else { try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) #if !os(Linux) && !os(Windows) if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { From dc6d151a98b9bf22daebfcae272a5f2ee0ae15ef Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:21:56 -0400 Subject: [PATCH 10/15] Beta support for Swift Testing, and other improvements. (#867) * wip * wip * wip * wip * wip * tests * wip * migration guide * wip * wip * wip * Update Sources/SnapshotTesting/AssertSnapshot.swift * wip * formatting * wip * format * more * wip * fix * Make record mode opaque. * more docs * wip * wip * Added new 'failed' record strategy, and wrote some tests. * remove test artificats * wip * more docs * fix linux tests * more test fixes * test clean up * debugging * debug * wip * fix * fix tests * wip * wip * wip * make snapshot configuration optional * make snapshot configuration optional * clean up * fix * indent * typo * more clean up * record before difftool * more tests * clean up test code --------- Co-authored-by: Stephen Celis --- README.md | 28 +- .../AssertInlineSnapshot.swift | 173 +++++---- Sources/SnapshotTesting/AssertSnapshot.swift | 360 +++++++++--------- Sources/SnapshotTesting/Async.swift | 1 - Sources/SnapshotTesting/Diffing.swift | 7 +- .../{ => Articles}/CustomStrategies.md | 0 .../Articles/IntegratingWithTestFrameworks.md | 87 +++++ .../MigrationGuides/MigratingTo1.17.md | 175 +++++++++ .../MigrationGuides/MigrationGuides.md | 17 + .../Documentation.docc/Deprecations.md | 11 - .../{ => Extensions}/AssertSnapshot.md | 8 +- .../SnapshotTestingDeprecations.md | 17 + .../diffTool-property-deprecation.md | 6 + .../isRecording-property-deprecation.md | 6 + .../Extensions/SnapshotsTrait.md | 5 + .../{ => Extensions}/Snapshotting.md | 0 .../Extensions/WithSnapshotTesting.md | 7 + .../Documentation.docc/SnapshotTesting.md | 10 +- .../Internal/Deprecations.swift | 43 ++- .../Internal/RecordIssue.swift | 26 ++ .../SnapshotTestingConfiguration.swift | 236 ++++++++++++ .../SnapshotTesting/SnapshotsTestTrait.swift | 52 +++ Sources/SnapshotTesting/Snapshotting.swift | 4 - .../SnapshotTesting/Snapshotting/CGPath.swift | 5 +- .../AssertInlineSnapshotSwiftTests.swift | 307 +++++++++++++++ .../InlineSnapshotTestingTests.swift | 8 +- .../DeprecationTests.swift | 13 + Tests/SnapshotTestingTests/RecordTests.swift | 204 ++++++++++ .../SnapshotTestingTests.swift | 52 +-- .../SnapshotsTraitTests.swift | 54 +++ .../WithSnapshotTestingTests.swift | 35 ++ .../SnapshotTestingTests/testCGPath.macOS.png | Bin 8568 -> 8565 bytes .../testNSBezierPath.macOS.png | Bin 8679 -> 8676 bytes .../SnapshotTestingTests/testNSView.1.png | Bin 4420 -> 4594 bytes .../SnapshotTestingTests/testNSView.2.txt | 6 +- .../testNSViewWithLayer.2.txt | 2 +- .../testPrecision.macos.png | Bin 2377 -> 2465 bytes .../testWebView.macos.png | Bin 126247 -> 126251 bytes ...thManipulatingNavigationDelegate.macos.png | Bin 126247 -> 126251 bytes 39 files changed, 1593 insertions(+), 372 deletions(-) rename Sources/SnapshotTesting/Documentation.docc/{ => Articles}/CustomStrategies.md (100%) create mode 100644 Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md create mode 100644 Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md create mode 100644 Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigrationGuides.md delete mode 100644 Sources/SnapshotTesting/Documentation.docc/Deprecations.md rename Sources/SnapshotTesting/Documentation.docc/{ => Extensions}/AssertSnapshot.md (76%) create mode 100644 Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/SnapshotTestingDeprecations.md create mode 100644 Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/diffTool-property-deprecation.md create mode 100644 Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/isRecording-property-deprecation.md create mode 100644 Sources/SnapshotTesting/Documentation.docc/Extensions/SnapshotsTrait.md rename Sources/SnapshotTesting/Documentation.docc/{ => Extensions}/Snapshotting.md (100%) create mode 100644 Sources/SnapshotTesting/Documentation.docc/Extensions/WithSnapshotTesting.md create mode 100644 Sources/SnapshotTesting/Internal/RecordIssue.swift create mode 100644 Sources/SnapshotTesting/SnapshotTestingConfiguration.swift create mode 100644 Sources/SnapshotTesting/SnapshotsTestTrait.swift create mode 100644 Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift create mode 100644 Tests/SnapshotTestingTests/DeprecationTests.swift create mode 100644 Tests/SnapshotTestingTests/RecordTests.swift create mode 100644 Tests/SnapshotTestingTests/SnapshotsTraitTests.swift create mode 100644 Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift diff --git a/README.md b/README.md index a4fcae17f..5782f945a 100644 --- a/README.md +++ b/README.md @@ -38,16 +38,28 @@ Repeat test runs will load this reference and compare it with the runtime value. match, the test will fail and describe the difference. Failures can be inspected from Xcode's Report Navigator or by inspecting the file URLs of the failure. -You can record a new reference by setting the `record` parameter to `true` on the assertion or -setting `isRecording` globally. +You can record a new reference by customizing snapshots inline with the assertion, or using the +`withSnapshotTesting` tool: -``` swift -assertSnapshot(of: vc, as: .image, record: true) - -// or globally +```swift +// Record just this one snapshot +assertSnapshot(of: vc, as: .image, record: .all) + +// Record all snapshots in a scope: +withSnapshotTesting(record: .all) { + assertSnapshot(of: vc1, as: .image) + assertSnapshot(of: vc2, as: .image) + assertSnapshot(of: vc3, as: .image) +} -isRecording = true -assertSnapshot(of: vc, as: .image) +// Record all snapshots in an XCTestCase subclass: +class FeatureTests: XCTestCase { + override func invokeTest() { + withSnapshotTesting(record: .all) { + super.invokeTest() + } + } +} ``` ## Snapshot Anything diff --git a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift index 4d8bfabaa..bc78be83e 100644 --- a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift +++ b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift @@ -1,7 +1,7 @@ import Foundation #if canImport(SwiftSyntax509) - import SnapshotTesting + @_spi(Internals) import SnapshotTesting import SwiftParser import SwiftSyntax import SwiftSyntaxBuilder @@ -35,7 +35,7 @@ import Foundation of value: @autoclosure () throws -> Value?, as snapshotting: Snapshotting, message: @autoclosure () -> String = "", - record isRecording: Bool = isRecording, + record isRecording: Bool? = nil, timeout: TimeInterval = 5, syntaxDescriptor: InlineSnapshotSyntaxDescriptor = InlineSnapshotSyntaxDescriptor(), matches expected: (() -> String)? = nil, @@ -44,95 +44,116 @@ import Foundation line: UInt = #line, column: UInt = #column ) { - let _: Void = installTestObserver - do { - var actual: String? - let expectation = XCTestExpectation() - if let value = try value() { - snapshotting.snapshot(value).run { - actual = $0 - expectation.fulfill() + let record = + (isRecording == true ? .all : isRecording == false ? .missing : nil) + ?? SnapshotTestingConfiguration.current?.record + ?? _record + withSnapshotTesting(record: record) { + let _: Void = installTestObserver + do { + var actual: String? + let expectation = XCTestExpectation() + if let value = try value() { + snapshotting.snapshot(value).run { + actual = $0 + expectation.fulfill() + } + switch XCTWaiter.wait(for: [expectation], timeout: timeout) { + case .completed: + break + case .timedOut: + recordIssue( + """ + Exceeded timeout of \(timeout) seconds waiting for snapshot. + + This can happen when an asynchronously loaded value (like a network response) has not \ + loaded. If a timeout is unavoidable, consider setting the "timeout" parameter of + "assertInlineSnapshot" to a higher value. + """, + file: file, + line: line + ) + return + case .incorrectOrder, .interrupted, .invertedFulfillment: + recordIssue("Couldn't snapshot value", file: file, line: line) + return + @unknown default: + recordIssue("Couldn't snapshot value", file: file, line: line) + return + } } - switch XCTWaiter.wait(for: [expectation], timeout: timeout) { - case .completed: - break - case .timedOut: - XCTFail( + let expected = expected?() + guard + record != .all, + record != .missing || expected != nil + else { + // NB: Write snapshot state before calling `XCTFail` in case `continueAfterFailure = false` + inlineSnapshotState[File(path: file), default: []].append( + InlineSnapshot( + expected: expected, + actual: actual, + wasRecording: record == .all, + syntaxDescriptor: syntaxDescriptor, + function: "\(function)", + line: line, + column: column + ) + ) + + var failure: String + if syntaxDescriptor.trailingClosureLabel + == InlineSnapshotSyntaxDescriptor.defaultTrailingClosureLabel + { + failure = "Automatically recorded a new snapshot." + } else { + failure = """ + Automatically recorded a new snapshot for "\(syntaxDescriptor.trailingClosureLabel)". + """ + } + if let difference = snapshotting.diffing.diff(expected ?? "", actual ?? "")?.0 { + failure += " Difference: …\n\n\(difference.indenting(by: 2))" + } + recordIssue( """ - Exceeded timeout of \(timeout) seconds waiting for snapshot. + \(failure) - This can happen when an asynchronously loaded value (like a network response) has not \ - loaded. If a timeout is unavoidable, consider setting the "timeout" parameter of - "assertInlineSnapshot" to a higher value. + Re-run "\(function)" to assert against the newly-recorded snapshot. """, file: file, line: line ) return - case .incorrectOrder, .interrupted, .invertedFulfillment: - XCTFail("Couldn't snapshot value", file: file, line: line) - return - @unknown default: - XCTFail("Couldn't snapshot value", file: file, line: line) - return } - } - let expected = expected?() - guard !isRecording, let expected - else { - // NB: Write snapshot state before calling `XCTFail` in case `continueAfterFailure = false` - inlineSnapshotState[File(path: file), default: []].append( - InlineSnapshot( - expected: expected, - actual: actual, - wasRecording: isRecording, - syntaxDescriptor: syntaxDescriptor, - function: "\(function)", - line: line, - column: column - ) - ) - var failure: String - if syntaxDescriptor.trailingClosureLabel - == InlineSnapshotSyntaxDescriptor.defaultTrailingClosureLabel - { - failure = "Automatically recorded a new snapshot." - } else { - failure = """ - Automatically recorded a new snapshot for "\(syntaxDescriptor.trailingClosureLabel)". + guard let expected + else { + recordIssue( """ + No expected value to assert against. + """, + file: file, + line: line + ) + return } - if let difference = snapshotting.diffing.diff(expected ?? "", actual ?? "")?.0 { - failure += " Difference: …\n\n\(difference.indenting(by: 2))" - } - XCTFail( + guard + let difference = snapshotting.diffing.diff(expected, actual ?? "")?.0 + else { return } + + let message = message() + syntaxDescriptor.fail( """ - \(failure) + \(message.isEmpty ? "Snapshot did not match. Difference: …" : message) - Re-run "\(function)" to assert against the newly-recorded snapshot. + \(difference.indenting(by: 2)) """, file: file, - line: line + line: line, + column: column ) - return + } catch { + recordIssue("Threw error: \(error)", file: file, line: line) } - guard let difference = snapshotting.diffing.diff(expected, actual ?? "")?.0 - else { return } - - let message = message() - syntaxDescriptor.fail( - """ - \(message.isEmpty ? "Snapshot did not match. Difference: …" : message) - - \(difference.indenting(by: 2)) - """, - file: file, - line: line, - column: column - ) - } catch { - XCTFail("Threw error: \(error)", file: file, line: line) } } #else @@ -197,6 +218,8 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { /// Initializes an inline snapshot syntax descriptor. /// /// - Parameters: + /// - deprecatedTrailingClosureLabels: An array of deprecated labels to consider for the inline + /// snapshot. /// - trailingClosureLabel: The label of the trailing closure that returns the inline snapshot. /// - trailingClosureOffset: The offset of the trailing closure that returns the inline /// snapshot, relative to the first trailing closure. @@ -242,7 +265,7 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { visitor.walk(testSource.sourceFile) trailingClosureLine = visitor.trailingClosureLine } - XCTFail( + recordIssue( message(), file: file, line: trailingClosureLine.map(UInt.init) ?? line @@ -386,7 +409,7 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { ) { self.file = file self.line = snapshots.first?.line - self.wasRecording = snapshots.first?.wasRecording ?? isRecording + self.wasRecording = snapshots.first?.wasRecording ?? false self.indent = String( sourceLocationConverter.sourceLines .first { $0.first?.isWhitespace == true && $0.contains { !$0.isWhitespace } }? diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 772a35681..737f607bb 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,54 +1,42 @@ import XCTest /// Enhances failure messages with a command line diff tool expression that can be copied and pasted -/// into a terminal. For more complex difftool needs, see `diffToolCommand`. -/// -/// ```swift -/// diffTool = "ksdiff" -/// ``` -public var diffTool: String? { - get { diffToolCommand?("", "").trimmingCharacters(in: .whitespaces) } - set { - diffToolCommand = newValue.map { value in - { [value, $0, $1].joined(separator: " ") } - } - } +/// into a terminal. +@available( + *, + deprecated, + message: + "Use 'withSnapshotTesting' to customize the diff tool. See the documentation for more information." +) +public var diffTool: SnapshotTestingConfiguration.DiffTool { + get { _diffTool } + set { _diffTool = newValue } } -/// Enhances failure messages with a diff tool expression created by the closure, such as an clickable -/// URL or a complex command. The closure will receive the existing screenshot path and the failed -/// screenshot path as arguments. -/// -/// ```swift -/// diffToolCommand = { "compare \"\($0)\" \"\($1)\" png: | open -f -a Preview.app" } -/// ``` -public var diffToolCommand: ((String, String) -> String)? +@_spi(Internals) +public var _diffTool: SnapshotTestingConfiguration.DiffTool = .default /// Whether or not to record all new references. -public var isRecording: Bool = { - let args = ProcessInfo.processInfo.arguments - if let index = args.firstIndex(of: "-co.pointfree.SnapshotTesting.IsRecording"), - index < args.count - 1, - args[index + 1] == "1" +@available( + *, deprecated, + message: + "Use 'withSnapshotTesting' to customize the record mode. See the documentation for more information." +) +public var isRecording: Bool { + get { SnapshotTestingConfiguration.current?.record ?? _record == .all } + set { _record = newValue ? .all : .missing } +} + +@_spi(Internals) +public var _record: SnapshotTestingConfiguration.Record = { + if let value = ProcessInfo.processInfo.environment["SNAPSHOT_TESTING_RECORD"], + let record = SnapshotTestingConfiguration.Record(rawValue: value) { - return true + return record } - return false + return .missing }() -/// Whether or not to create snapshots if they aren't found. -/// It's recommended to set this to `false` in CI to avoid false positives if the test is retried. -public var canGenerateNewSnapshots = true - -/// Whether or not to record all new references. -/// -/// Due to a name clash in Xcode 12, this has been renamed to `isRecording`. -@available(*, deprecated, renamed: "isRecording") -public var record: Bool { - get { isRecording } - set { isRecording = newValue } -} - /// Asserts that a given value matches a reference on disk. /// /// - Parameters: @@ -67,7 +55,7 @@ public func assertSnapshot( of value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, - record recording: Bool = false, + record recording: Bool? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -84,7 +72,7 @@ public func assertSnapshot( line: line ) guard let message = failure else { return } - XCTFail(message, file: file, line: line) + recordIssue(message, file: file, line: line) } /// Asserts that a given value matches references on disk. @@ -104,7 +92,7 @@ public func assertSnapshot( public func assertSnapshots( of value: @autoclosure () throws -> Value, as strategies: [String: Snapshotting], - record recording: Bool = false, + record recording: Bool? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -140,7 +128,7 @@ public func assertSnapshots( public func assertSnapshots( of value: @autoclosure () throws -> Value, as strategies: [Snapshotting], - record recording: Bool = false, + record recording: Bool? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -214,174 +202,182 @@ public func verifySnapshot( of value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, - record recording: Bool = false, + record recording: Bool? = nil, snapshotDirectory: String? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, line: UInt = #line ) -> String? { - CleanCounterBetweenTestCases.registerIfNeeded() - let recording = recording || isRecording - - do { - let fileUrl = URL(fileURLWithPath: "\(file)", isDirectory: false) - let fileName = fileUrl.deletingPathExtension().lastPathComponent - - let snapshotDirectoryUrl = - snapshotDirectory.map { URL(fileURLWithPath: $0, isDirectory: true) } - ?? fileUrl - .deletingLastPathComponent() - .appendingPathComponent("__Snapshots__") - .appendingPathComponent(fileName) - - let identifier: String - if let name = name { - identifier = sanitizePathComponent(name) - } else { - let counter = counterQueue.sync { () -> Int in - let key = snapshotDirectoryUrl.appendingPathComponent(testName) - counterMap[key, default: 0] += 1 - return counterMap[key]! - } - identifier = String(counter) - } - let testName = sanitizePathComponent(testName) - let snapshotFileUrl = - snapshotDirectoryUrl - .appendingPathComponent("\(testName).\(identifier)") - .appendingPathExtension(snapshotting.pathExtension ?? "") - let fileManager = FileManager.default - try fileManager.createDirectory(at: snapshotDirectoryUrl, withIntermediateDirectories: true) - - let tookSnapshot = XCTestExpectation(description: "Took snapshot") - var optionalDiffable: Format? - snapshotting.snapshot(try value()).run { b in - optionalDiffable = b - tookSnapshot.fulfill() - } - let result = XCTWaiter.wait(for: [tookSnapshot], timeout: timeout) - switch result { - case .completed: - break - case .timedOut: - return """ - Exceeded timeout of \(timeout) seconds waiting for snapshot. + let record = + (recording == true ? .all : recording == false ? .missing : nil) + ?? SnapshotTestingConfiguration.current?.record + ?? _record + return withSnapshotTesting(record: record) { () -> String? in + do { + let fileUrl = URL(fileURLWithPath: "\(file)", isDirectory: false) + let fileName = fileUrl.deletingPathExtension().lastPathComponent + + let snapshotDirectoryUrl = + snapshotDirectory.map { URL(fileURLWithPath: $0, isDirectory: true) } + ?? fileUrl + .deletingLastPathComponent() + .appendingPathComponent("__Snapshots__") + .appendingPathComponent(fileName) + + let identifier: String + if let name = name { + identifier = sanitizePathComponent(name) + } else { + let counter = counterQueue.sync { () -> Int in + let key = snapshotDirectoryUrl.appendingPathComponent(testName) + counterMap[key, default: 0] += 1 + return counterMap[key]! + } + identifier = String(counter) + } - This can happen when an asynchronously rendered view (like a web view) has not loaded. \ - Ensure that every subview of the view hierarchy has loaded to avoid timeouts, or, if a \ - timeout is unavoidable, consider setting the "timeout" parameter of "assertSnapshot" to \ - a higher value. - """ - case .incorrectOrder, .invertedFulfillment, .interrupted: - return "Couldn't snapshot value" - @unknown default: - return "Couldn't snapshot value" - } + let testName = sanitizePathComponent(testName) + let snapshotFileUrl = + snapshotDirectoryUrl + .appendingPathComponent("\(testName).\(identifier)") + .appendingPathExtension(snapshotting.pathExtension ?? "") + let fileManager = FileManager.default + try fileManager.createDirectory(at: snapshotDirectoryUrl, withIntermediateDirectories: true) + + let tookSnapshot = XCTestExpectation(description: "Took snapshot") + var optionalDiffable: Format? + snapshotting.snapshot(try value()).run { b in + optionalDiffable = b + tookSnapshot.fulfill() + } + let result = XCTWaiter.wait(for: [tookSnapshot], timeout: timeout) + switch result { + case .completed: + break + case .timedOut: + return """ + Exceeded timeout of \(timeout) seconds waiting for snapshot. + + This can happen when an asynchronously rendered view (like a web view) has not loaded. \ + Ensure that every subview of the view hierarchy has loaded to avoid timeouts, or, if a \ + timeout is unavoidable, consider setting the "timeout" parameter of "assertSnapshot" to \ + a higher value. + """ + case .incorrectOrder, .invertedFulfillment, .interrupted: + return "Couldn't snapshot value" + @unknown default: + return "Couldn't snapshot value" + } - guard var diffable = optionalDiffable else { - return "Couldn't snapshot value" - } + guard var diffable = optionalDiffable else { + return "Couldn't snapshot value" + } - guard !recording, canGenerateNewSnapshots, fileManager.fileExists(atPath: snapshotFileUrl.path) - else { - try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) - #if !os(Linux) && !os(Windows) - if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { - XCTContext.runActivity(named: "Attached Recorded Snapshot") { activity in - let attachment = XCTAttachment(contentsOfFile: snapshotFileUrl) - activity.add(attachment) + func recordSnapshot() throws { + try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) + #if !os(Linux) && !os(Windows) + if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { + XCTContext.runActivity(named: "Attached Recorded Snapshot") { activity in + let attachment = XCTAttachment(contentsOfFile: snapshotFileUrl) + activity.add(attachment) + } } - } - #endif - - return recording - ? """ - Record mode is on. Automatically recorded snapshot: … + #endif + } - open "\(snapshotFileUrl.absoluteString)" + guard + record != .all, + (record != .missing && record != .failed) + || fileManager.fileExists(atPath: snapshotFileUrl.path) + else { + try recordSnapshot() - Turn record mode off and re-run "\(testName)" to assert against the newly-recorded snapshot - """ - : """ - No reference was found on disk. Automatically recorded snapshot: … + return SnapshotTestingConfiguration.current?.record == .all + ? """ + Record mode is on. Automatically recorded snapshot: … - open "\(snapshotFileUrl.absoluteString)" + open "\(snapshotFileUrl.absoluteString)" - Re-run "\(testName)" to assert against the newly-recorded snapshot. - """ - } + Turn record mode off and re-run "\(testName)" to assert against the newly-recorded snapshot + """ + : """ + No reference was found on disk. Automatically recorded snapshot: … - let data = try Data(contentsOf: snapshotFileUrl) - let reference = snapshotting.diffing.fromData(data) + open "\(snapshotFileUrl.absoluteString)" - #if os(iOS) || os(tvOS) - // If the image generation fails for the diffable part and the reference was empty, use the reference - if let localDiff = diffable as? UIImage, - let refImage = reference as? UIImage, - localDiff.size == .zero && refImage.size == .zero - { - diffable = reference + Re-run "\(testName)" to assert against the newly-recorded snapshot. + """ } - #endif - guard let (failure, attachments) = snapshotting.diffing.diff(reference, diffable) else { - return nil - } + let data = try Data(contentsOf: snapshotFileUrl) + let reference = snapshotting.diffing.fromData(data) - let artifactsUrl = URL( - fileURLWithPath: ProcessInfo.processInfo.environment["SNAPSHOT_ARTIFACTS"] - ?? NSTemporaryDirectory(), isDirectory: true - ) - let artifactsSubUrl = artifactsUrl.appendingPathComponent(fileName) - try fileManager.createDirectory(at: artifactsSubUrl, withIntermediateDirectories: true) - let failedSnapshotFileUrl = artifactsSubUrl.appendingPathComponent( - snapshotFileUrl.lastPathComponent) - try snapshotting.diffing.toData(diffable).write(to: failedSnapshotFileUrl) - - if !attachments.isEmpty { - #if !os(Linux) && !os(Windows) - if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { - XCTContext.runActivity(named: "Attached Failure Diff") { activity in - attachments.forEach { - activity.add($0) - } - } + #if os(iOS) || os(tvOS) + // If the image generation fails for the diffable part and the reference was empty, use the reference + if let localDiff = diffable as? UIImage, + let refImage = reference as? UIImage, + localDiff.size == .zero && refImage.size == .zero + { + diffable = reference } #endif - } - let diffMessage = - diffToolCommand?(snapshotFileUrl.path, failedSnapshotFileUrl.path) - ?? """ - @\(minus) - "\(snapshotFileUrl.absoluteString)" - @\(plus) - "\(failedSnapshotFileUrl.absoluteString)" + guard let (failure, attachments) = snapshotting.diffing.diff(reference, diffable) else { + return nil + } - To configure output for a custom diff tool, like Kaleidoscope: + let artifactsUrl = URL( + fileURLWithPath: ProcessInfo.processInfo.environment["SNAPSHOT_ARTIFACTS"] + ?? NSTemporaryDirectory(), isDirectory: true + ) + let artifactsSubUrl = artifactsUrl.appendingPathComponent(fileName) + try fileManager.createDirectory(at: artifactsSubUrl, withIntermediateDirectories: true) + let failedSnapshotFileUrl = artifactsSubUrl.appendingPathComponent( + snapshotFileUrl.lastPathComponent) + try snapshotting.diffing.toData(diffable).write(to: failedSnapshotFileUrl) + + if !attachments.isEmpty { + #if !os(Linux) && !os(Windows) + if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { + XCTContext.runActivity(named: "Attached Failure Diff") { activity in + attachments.forEach { + activity.add($0) + } + } + } + #endif + } - SnapshotTesting.diffTool = "ksdiff" - """ + let diffMessage = (SnapshotTestingConfiguration.current?.diffTool ?? _diffTool)( + currentFilePath: snapshotFileUrl.path, + failedFilePath: failedSnapshotFileUrl.path + ) - let failureMessage: String - if let name = name { - failureMessage = "Snapshot \"\(name)\" does not match reference." - } else { - failureMessage = "Snapshot does not match reference." - } + var failureMessage: String + if let name = name { + failureMessage = "Snapshot \"\(name)\" does not match reference." + } else { + failureMessage = "Snapshot does not match reference." + } + + if record == .failed { + try recordSnapshot() + failureMessage += " A new snapshot was automatically recorded." + } - return """ - \(failureMessage) + return """ + \(failureMessage) - \(diffMessage) + \(diffMessage) - \(failure.trimmingCharacters(in: .whitespacesAndNewlines)) - """ - } catch { - return error.localizedDescription + \(failure.trimmingCharacters(in: .whitespacesAndNewlines)) + """ + } catch { + return error.localizedDescription + } } } diff --git a/Sources/SnapshotTesting/Async.swift b/Sources/SnapshotTesting/Async.swift index bf1ddc295..2c16adda5 100644 --- a/Sources/SnapshotTesting/Async.swift +++ b/Sources/SnapshotTesting/Async.swift @@ -20,7 +20,6 @@ public struct Async { /// /// - Parameters: /// - run: A function that, when called, can hand a value to a callback. - /// - callback: A function that can be called with a value. public init(run: @escaping (_ callback: @escaping (Value) -> Void) -> Void) { self.run = run } diff --git a/Sources/SnapshotTesting/Diffing.swift b/Sources/SnapshotTesting/Diffing.swift index cf850b7b8..357159fff 100644 --- a/Sources/SnapshotTesting/Diffing.swift +++ b/Sources/SnapshotTesting/Diffing.swift @@ -14,16 +14,11 @@ public struct Diffing { public var diff: (Value, Value) -> (String, [XCTAttachment])? /// Creates a new `Diffing` on `Value`. - /// + /// /// - Parameters: /// - toData: A function used to convert a value _to_ data. - /// - value: A value to convert into data. /// - fromData: A function used to produce a value _from_ data. - /// - data: Data to convert into a value. /// - diff: A function used to compare two values. If the values do not match, returns a failure - /// message and artifacts describing the failure. - /// - lhs: A value to compare. - /// - rhs: Another value to compare. public init( toData: @escaping (_ value: Value) -> Data, fromData: @escaping (_ data: Data) -> Value, diff --git a/Sources/SnapshotTesting/Documentation.docc/CustomStrategies.md b/Sources/SnapshotTesting/Documentation.docc/Articles/CustomStrategies.md similarity index 100% rename from Sources/SnapshotTesting/Documentation.docc/CustomStrategies.md rename to Sources/SnapshotTesting/Documentation.docc/Articles/CustomStrategies.md diff --git a/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md b/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md new file mode 100644 index 000000000..2f7020772 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md @@ -0,0 +1,87 @@ +# Intergrating with test frameworks + +Learn how to use snapshot testing in the two main testing frameworks: Xcode's XCTest and Swift's +native testing framework. + +## Overview + +The Apple ecosystem currently has two primary testing frameworks, and unfortunately they are not +compatible with each other. There is the XCTest framework, which is a private framework provided +by Apple and heavily integrated into Xcode. And now there is Swift Testing, an open source testing +framework built in Swift that is capable of integrating into a variety of environments. + +These two frameworks are not compatible in the sense that an assertion made in one framework +from a test in the other framework will not trigger a test failure. So, if you are writing a test +with the new `@Test` macro style, and you use a test helper that ultimately calls `XCTFail` under +the hood, that will not bubble up to an actual test failure when tests are run. And similarly, if +you have a test case inheriting from `XCTestCase` that ultimiately invokes the new style `#expect` +macro, that too will not actually trigger a test failure. + +However, these details have all been hidden away in the SnapshotTesting library. You can simply +use ``assertSnapshot(of:as:named:record:timeout:file:testName:line:)`` in either an `XCTestCase` +subclass _or_ `@Test`, and it will dynamically detect what context it is running in and trigger +the correct test failure: + +```swift +class FeatureTests: XCTestCase { + func testFeature() { + assertSnapshot(of: MyView(), as: .image) // ✅ + } +} + +@Test +func testFeature() { + assertSnapshot(of: MyView(), as: .image) // ✅ +} +``` + +### Configuring snapshots + +For the most part, asserting on snapshots works the same whether you are using XCTest or Swift +Testing. There is one major difference, and that is how snapshot configuration works. There are +two major ways snapshots can be configured: ``SnapshotTestingConfiguration/diffTool-swift.property`` +and ``SnapshotTestingConfiguration/record-swift.property``. + +The `diffTool` property allows you to customize how a command is printed to the test failure +message that allows you to quickly open a diff of two files, such as +[Kaleidoscope](http://kaleidoscope.app). The `record` property allows you to change the mode of +assertion so that new snapshots are generated and saved to disk. + +These properties can be overridden for a scope of an operation using the +``withSnapshotTesting(record:diffTool:operation:)-2kuyr`` function. In an XCTest context the +simplest way to do this is to override the `invokeTest` method on `XCTestCase` and wrap it in +`withSnapshotTesting`: + +```swift +class FeatureTests: XCTestCase { + override func invokeTest() { + withSnapshotTesting( + record: .missing, + diffTool: .ksdiff + ) { + super.invokeTest() + } + } +} +``` + +This will override the `diffTool` and `record` properties for each test function. + +Swift's new testing framework does not currently have a public API for this kind of customization. +There is an experimental feature, called `CustomExecutionTrait`, that does gives us this ability, +and the library provides such a trait called ``Testing/Trait/snapshots(diffTool:record:)``. It can +be attached to any `@Test` or `@Suite` to configure snapshot testing: + +```swift +@_spi(Experimental) import SnapshotTesting + +@Suite(.snapshots(record: .all, diffTool: .ksdiff)) +struct FeatureTests { + … +} +``` + +> Important: You must import SnapshotTesting with the `@_spi(Experimental)` attribute to get access +to this functionality because Swift Testing's own `CustomExecutionTrait` is hidden behind the same +SPI flag. This means this API is subject to change in the future, but hopefully Apple will +publicize this tool soon. diff --git a/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md b/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md new file mode 100644 index 000000000..489516307 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md @@ -0,0 +1,175 @@ +# Migrating to 1.17 + +Learn how to use the new `withSnapshotTesting` tool for customizing how snapshots are generated and +diffs displayed. + +## Overview + +This library is under constant development, and we are always looking for ways to simplify the +library, and make it more powerful. This version of the library has deprecated some APIs, +introduced a new APIs, and includes beta support for Swift's new native testing library. + +## Customizing snapshots + +Currently there are two global variables in the library for customizing snapshot testing: + + * ``isRecording`` determines whether new snapshots are generated and saved to disk when the test + runs. + + * ``diffTool`` determines the command line tool that is used to inspect the diff of two files on + disk. + +These customization options have a few downsides currently. + + * First, because they are globals they can easily bleed over from test to test in unexpected ways. + And further, Swift's new testing library runs parallel tests in the same process, which is in + stark contrast to XCTest, which runs parallel tests in separate processes. This means there are + even more chances for these globals to bleed from one test to another. + + * And second, these options aren't as granular as some of our users wanted. When ``isRecording`` + is true snapshots are generated and written to disk, and when it is false snapshots are not + generated, _unless_ a file is not present on disk. The a snapshot _is_ generated. Some of our + users wanted an option between these two extremes, where snapshots would not be generated if the + file does not exist on disk. + + And the ``diffTool`` variable allows one to specify a command line tool to use for visualizing + diffs of files, but only works when the command line tool accepts a very narrow set of + arguments, _e.g.: + + ```sh + ksdiff /path/to/file1.png /path/to/file2.png + ``` + +Because of these reasons, the globals ``isRecording`` and ``diffTool`` are now deprecated, and we +have introduced a new tool that greatly improves upon all of these problems. There is now a function +called ``withSnapshotTesting(record:diffTool:operation:)-2kuyr`` for customizing snapshots. It +allows you to customize how the `assertSnapshot` tool behaves for a well-defined scope. + +Rather than overriding `isRecording` or `diffTool` directly in your tests, you can wrap your test in +`withSnapshotTesting`: + +@Row { + @Column { + ```swift + // Before + + func testFeature() { + isRecording = true + diffTool = "ksdiff" + assertSnapshot(…) + } + ``` + } + @Column { + ```swift + // After + + func testFeature() { + withSnapshotTesting(record: .all, diffTool: .ksdiff) { + assertSnapshot(…) + } + } + ``` + } +} + +If you want to override the options for an entire test class, you can override the `invokeTest` +method of `XCTestCase`: + +@Row { + @Column { + ```swift + // Before + + class FeatureTests: XCTestCase { + override func invokeTest() { + isRecording = true + diffTool = "ksdiff" + defer { + isRecording = false + diffTool = nil + } + super.invokeTest() + } + } + ``` + } + @Column { + ```swift + // After + + class FeatureTests: XCTestCase { + override func invokeTest() { + withSnapshotTesting(record: .all, diffTool: .ksdiff) { + super.invokeTest() + } + } + } + ``` + } +} + +And if you want to override these settings for _all_ tests, then you can implement a base +`XCTestCase` subclass and have your tests inherit from it. + +Further, the `diffTool` and `record` arguments have extra customization capabilities: + + * `diffTool` is now a [function]() + `(String, String) -> String` that is handed the current snapshot file and the failed snapshot + file. It can return the command that one can run to display a diff. For example, to use + ImageMagick's `compare` command and open the result in Preview.app: + + ```swift + extension SnapshotTestingConfiguration.DiffTool { + static let compare = Self { + "compare \"\($0)\" \"\($1)\" png: | open -f -a Preview.app" + } + } + ``` + + * `record` is now a [type]() with 4 + choices: `all`, `missing`, `never`, `failed`: + * `all`: All snapshots will be generated and saved to disk. + * `missing`: only the snapshots that are missing from the disk will be generated + and saved. + * `never`: No snapshots will be generated, even if they are missing. This option is appropriate + when running tests on CI so that re-tries of tests do not surprisingly pass after snapshots are + unexpectedly generated. + * `failed`: Snapshots only for failing tests will be generated. This can be useful for tests + that use precision thresholds so that passing tests do not re-record snapshots that are + subtly different but still within the threshold. + +## Beta support for Swift Testing + +This release of the library provides beta support for Swift's native Testing library. Prior to this +release, using `assertSnapshot` in a `@Test` would result in a passing test no matter what. That is +because under the hood `assertSnapshot` uses `XCTFail` to trigger test failures, but that does not +cause test failures when using Swift Testing. + +In version 1.17 the `assertSnapshot` helper will now intelligently figure out if tests are running +in an XCTest context or a Swift Testing context, and will determine if it should invoke `XCTFail` or +`Issue.record` to trigger a test failure. + +For the most part you can write tests for Swift Testing exactly as you would for XCTest. However, +there is one major difference. Swift Testing does not (yet) have a substitute for `invokeTest`, +which we used alongside `withSnapshotTesting` to customize snapshotting for a full test class. + +There is an experimental version of this tool in Swift Testing, called `CustomExecutionTrait`, and +this library provides such a trait called ``Testing/Trait/snapshots(diffTool:record:)``. It allows +you to customize snapshots for a `@Test` or `@Suite`, but to get access to it you must perform an +`@_spi(Experimental)` import of snapshot testing: + +```swift +@_spi(Experimental) import SnapshotTesting + +@Suite(.snapshots(record: .all, diffTool: .ksdiff)) +struct FeatureTests { + … +} +``` + +That will override the `diffTool` and `record` options for the entire `FeatureTests` suite. + +> Important: As evident by the usage of `@_spi(Experimental)` this API is subject to change. As +soon as the Swift Testing library finalizes its API for `CustomExecutionTrait` we will update +the library accordingly and remove the `@_spi` annotation. diff --git a/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigrationGuides.md b/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigrationGuides.md new file mode 100644 index 000000000..17e3f4503 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigrationGuides.md @@ -0,0 +1,17 @@ +# Migration guides + +Learn how to upgrade your application to the newest version of this library. + +## Overview + +This library is under constant development, and we are always looking for ways to simplify the +library, and make it more powerful. As such, we often need to deprecate certain APIs in favor of +newer ones. We recommend people update their code as quickly as possible to the newest APIs, and +these guides contain tips to do so. + +> Important: Before following any particular migration guide be sure you have followed all the +> preceding migration guides. + +### Guides + +- diff --git a/Sources/SnapshotTesting/Documentation.docc/Deprecations.md b/Sources/SnapshotTesting/Documentation.docc/Deprecations.md deleted file mode 100644 index f5460227c..000000000 --- a/Sources/SnapshotTesting/Documentation.docc/Deprecations.md +++ /dev/null @@ -1,11 +0,0 @@ -# Deprecations - -## Topics - -### Configuration - -- ``record`` - -### Supporting types - -- ``SnapshotTestCase`` diff --git a/Sources/SnapshotTesting/Documentation.docc/AssertSnapshot.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/AssertSnapshot.md similarity index 76% rename from Sources/SnapshotTesting/Documentation.docc/AssertSnapshot.md rename to Sources/SnapshotTesting/Documentation.docc/Extensions/AssertSnapshot.md index 8b2bd4821..bb10bb9a2 100644 --- a/Sources/SnapshotTesting/Documentation.docc/AssertSnapshot.md +++ b/Sources/SnapshotTesting/Documentation.docc/Extensions/AssertSnapshot.md @@ -4,8 +4,8 @@ ### Multiple snapshots -- ``assertSnapshots(of:as:record:timeout:file:testName:line:)-98vsq`` -- ``assertSnapshots(of:as:record:timeout:file:testName:line:)-4upll`` +- ``assertSnapshots(of:as:record:timeout:file:testName:line:)-6mdbp`` +- ``assertSnapshots(of:as:record:timeout:file:testName:line:)-6c4fe`` ### Custom assertions @@ -14,6 +14,6 @@ ### Deprecations - ``assertSnapshot(matching:as:named:record:timeout:file:testName:line:)`` -- ``assertSnapshots(matching:as:record:timeout:file:testName:line:)-3i804`` -- ``assertSnapshots(matching:as:record:timeout:file:testName:line:)-6bvvj`` +- ``assertSnapshots(matching:as:record:timeout:file:testName:line:)-4fz7d`` +- ``assertSnapshots(matching:as:record:timeout:file:testName:line:)-wq4j`` - ``verifySnapshot(matching:as:named:record:snapshotDirectory:timeout:file:testName:line:)`` diff --git a/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/SnapshotTestingDeprecations.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/SnapshotTestingDeprecations.md new file mode 100644 index 000000000..6a1624626 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/SnapshotTestingDeprecations.md @@ -0,0 +1,17 @@ +# Deprecations + +## Topics + +### Assert helpers + +- ``assertSnapshots(matching:as:record:timeout:file:testName:line:)-4fz7d`` +- ``assertSnapshots(matching:as:record:timeout:file:testName:line:)-wq4j`` + +### Configuration + +- ``isRecording`` +- ``diffTool`` + +### Supporting types + +- ``SnapshotTestCase`` diff --git a/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/diffTool-property-deprecation.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/diffTool-property-deprecation.md new file mode 100644 index 000000000..f112fcc06 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/diffTool-property-deprecation.md @@ -0,0 +1,6 @@ +# ``SnapshotTesting/diffTool`` + +@DeprecationSummary { + Use ``withSnapshotTesting(record:diffTool:operation:)-2kuyr`` to customize the diff tool, instead. + See for more information. +} diff --git a/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/isRecording-property-deprecation.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/isRecording-property-deprecation.md new file mode 100644 index 000000000..8c8852bc4 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Extensions/Deprecations/isRecording-property-deprecation.md @@ -0,0 +1,6 @@ +# ``SnapshotTesting/isRecording`` + +@DeprecationSummary { + Use ``withSnapshotTesting(record:diffTool:operation:)-2kuyr`` to customize the record mode, + instead. See for more information. +} diff --git a/Sources/SnapshotTesting/Documentation.docc/Extensions/SnapshotsTrait.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/SnapshotsTrait.md new file mode 100644 index 000000000..532f53ca8 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Extensions/SnapshotsTrait.md @@ -0,0 +1,5 @@ +# ``SnapshotTesting/Testing/Trait/snapshots(diffTool:record:)`` + +### Configuration + +- ``Testing/Trait/snapshots(_:)`` diff --git a/Sources/SnapshotTesting/Documentation.docc/Snapshotting.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/Snapshotting.md similarity index 100% rename from Sources/SnapshotTesting/Documentation.docc/Snapshotting.md rename to Sources/SnapshotTesting/Documentation.docc/Extensions/Snapshotting.md diff --git a/Sources/SnapshotTesting/Documentation.docc/Extensions/WithSnapshotTesting.md b/Sources/SnapshotTesting/Documentation.docc/Extensions/WithSnapshotTesting.md new file mode 100644 index 000000000..397b4b089 --- /dev/null +++ b/Sources/SnapshotTesting/Documentation.docc/Extensions/WithSnapshotTesting.md @@ -0,0 +1,7 @@ +# ``SnapshotTesting/withSnapshotTesting(record:diffTool:operation:)-2kuyr`` + +## Topics + +### Overloads + +- ``withSnapshotTesting(record:diffTool:operation:)-6bsqw`` diff --git a/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md b/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md index 473bee907..8704d920d 100644 --- a/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md +++ b/Sources/SnapshotTesting/Documentation.docc/SnapshotTesting.md @@ -7,6 +7,8 @@ Powerfully flexible snapshot testing. ### Essentials - ``assertSnapshot(of:as:named:record:timeout:file:testName:line:)`` +- +- ### Strategies @@ -17,10 +19,10 @@ Powerfully flexible snapshot testing. ### Configuration -- ``isRecording`` -- ``canGenerateNewSnapshots`` -- ``diffTool`` +- ``Testing/Trait/snapshots(diffTool:record:)`` +- ``withSnapshotTesting(record:diffTool:operation:)-2kuyr`` +- ``SnapshotTestingConfiguration`` ### Deprecations -- +- diff --git a/Sources/SnapshotTesting/Internal/Deprecations.swift b/Sources/SnapshotTesting/Internal/Deprecations.swift index 8e2472cf7..debb08dac 100644 --- a/Sources/SnapshotTesting/Internal/Deprecations.swift +++ b/Sources/SnapshotTesting/Internal/Deprecations.swift @@ -30,7 +30,7 @@ public func _assertInlineSnapshot( line: line ) guard let message = failure else { return } - XCTFail(message, file: file, line: line) + recordIssue(message, file: file, line: line) } @available( @@ -316,15 +316,12 @@ private var recordings: Recordings = [:] // Deprecated after 1.11.1: -@available(iOS, deprecated: 10000, message: "Use `assertSnapshot(of:…:)` instead.") -@available(macOS, deprecated: 10000, message: "Use `assertSnapshot(of:…:)` instead.") -@available(tvOS, deprecated: 10000, message: "Use `assertSnapshot(of:…:)` instead.") -@available(watchOS, deprecated: 10000, message: "Use `assertSnapshot(of:…:)` instead.") +@available(*, deprecated, renamed: "assertSnapshot(of:as:named:record:timeout:file:testName:line:)") public func assertSnapshot( matching value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, - record recording: Bool = false, + record recording: Bool? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -342,14 +339,13 @@ public func assertSnapshot( ) } -@available(iOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") -@available(macOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") -@available(tvOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") -@available(watchOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") +@available( + *, deprecated, renamed: "assertSnapshots(of:as:named:record:timeout:file:testName:line:)" +) public func assertSnapshots( matching value: @autoclosure () throws -> Value, as strategies: [String: Snapshotting], - record recording: Bool = false, + record recording: Bool? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -366,14 +362,13 @@ public func assertSnapshots( ) } -@available(iOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") -@available(macOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") -@available(tvOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") -@available(watchOS, deprecated: 10000, message: "Use `assertSnapshots(of:…:)` instead.") +@available( + *, deprecated, renamed: "assertSnapshots(of:as:named:record:timeout:file:testName:line:)" +) public func assertSnapshots( matching value: @autoclosure () throws -> Value, as strategies: [Snapshotting], - record recording: Bool = false, + record recording: Bool? = nil, timeout: TimeInterval = 5, file: StaticString = #file, testName: String = #function, @@ -390,15 +385,15 @@ public func assertSnapshots( ) } -@available(iOS, deprecated: 10000, message: "Use `verifySnapshot(of:…:)` instead.") -@available(macOS, deprecated: 10000, message: "Use `verifySnapshot(of:…:)` instead.") -@available(tvOS, deprecated: 10000, message: "Use `verifySnapshot(of:…:)` instead.") -@available(watchOS, deprecated: 10000, message: "Use `verifySnapshot(of:…:)` instead.") +@available( + *, deprecated, + renamed: "verifySnapshot(of:as:named:record:snapshotDirectory:timeout:file:testName:line:)" +) public func verifySnapshot( matching value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, - record recording: Bool = false, + record recording: Bool? = nil, snapshotDirectory: String? = nil, timeout: TimeInterval = 5, file: StaticString = #file, @@ -420,3 +415,9 @@ public func verifySnapshot( @available(*, deprecated, renamed: "XCTestCase") public typealias SnapshotTestCase = XCTestCase + +@available(*, deprecated, renamed: "isRecording") +public var record: Bool { + get { isRecording } + set { isRecording = newValue } +} diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift new file mode 100644 index 000000000..76f0a4c86 --- /dev/null +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -0,0 +1,26 @@ +import XCTest + +#if canImport(Testing) + import Testing +#endif + +@_spi(Internals) +public func recordIssue( + _ message: @autoclosure () -> String, + file: StaticString = #filePath, + line: UInt = #line +) { + #if canImport(Testing) + if Test.current != nil { + Issue.record( + Comment(rawValue: message()), + filePath: file.description, + line: Int(line) + ) + } else { + XCTFail(message(), file: file, line: line) + } + #else + XCTFail(message(), file: file, line: line) + #endif +} diff --git a/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift b/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift new file mode 100644 index 000000000..93c2e7122 --- /dev/null +++ b/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift @@ -0,0 +1,236 @@ +/// Customizes `assertSnapshot` for the duration of an operation. +/// +/// Use this operation to customize how the `assertSnapshot` function behaves in a test. It is most +/// convenient to use in the context of XCTest where you can wrap `invokeTest` of an `XCTestCase` +/// subclass so that the configuration applies to every test method. +/// +/// > Note: To customize tests when using Swift's native Testing library, use the +/// > ``Testing/Trait/snapshots(diffTool:record:)`` trait. +/// +/// For example, to specify to put an entire test class in record mode you do the following: +/// +/// ```swift +/// class FeatureTests: XCTestCase { +/// override func invokeTest() { +/// withSnapshotTesting(record: .all) { +/// super.invokeTest() +/// } +/// } +/// } +/// ``` +/// +/// - Parameters: +/// - record: The record mode to use while asserting snapshots. +/// - diffTool: The diff tool to use while asserting snapshots. +/// - operation: The operation to perform. +public func withSnapshotTesting( + record: SnapshotTestingConfiguration.Record? = nil, + diffTool: SnapshotTestingConfiguration.DiffTool? = nil, + operation: () throws -> R +) rethrows -> R { + try SnapshotTestingConfiguration.$current.withValue( + SnapshotTestingConfiguration( + record: record ?? SnapshotTestingConfiguration.current?.record ?? _record, + diffTool: diffTool ?? SnapshotTestingConfiguration.current?.diffTool + ?? SnapshotTesting._diffTool + ) + ) { + try operation() + } +} + +/// Customizes `assertSnapshot` for the duration of an asynchronous operation. +/// +/// See ``withSnapshotTesting(record:diffTool:operation:)-2kuyr`` for more information. +public func withSnapshotTesting( + record: SnapshotTestingConfiguration.Record? = nil, + diffTool: SnapshotTestingConfiguration.DiffTool? = nil, + operation: () async throws -> R +) async rethrows -> R { + try await SnapshotTestingConfiguration.$current.withValue( + SnapshotTestingConfiguration( + record: record ?? SnapshotTestingConfiguration.current?.record ?? _record, + diffTool: diffTool ?? SnapshotTestingConfiguration.current?.diffTool ?? _diffTool + ) + ) { + try await operation() + } +} + +/// The configuration for a snapshot test. +public struct SnapshotTestingConfiguration: Sendable { + @_spi(Internals) + @TaskLocal public static var current: Self? + + /// The diff tool use to print helpful test failure messages. + /// + /// See ``DiffTool-swift.struct`` for more information. + public var diffTool: DiffTool? + + /// The recording strategy to use while running snapshot tests. + /// + /// See ``Record-swift.struct`` for more information. + public var record: Record? + + public init( + record: Record?, + diffTool: DiffTool? + ) { + self.diffTool = diffTool + self.record = record + } + + /// The record mode of the snapshot test. + /// + /// There are 4 primary strategies for recording: ``Record-swift.struct/all``, + /// ``Record-swift.struct/missing``, ``Record-swift.struct/never`` and + /// ``Record-swift.struct/failed`` + public struct Record: Equatable, Sendable { + private let storage: Storage + + public init?(rawValue: String) { + switch rawValue { + case "all": + self.storage = .all + case "failed": + self.storage = .failed + case "missing": + self.storage = .missing + case "never": + self.storage = .never + default: + return nil + } + } + + /// Records all snapshots to disk, no matter what. + public static let all = Self(storage: .all) + + /// Records snapshots for assertions that fail. This can be useful for tests that use precision + /// thresholds so that passing tests do not re-record snapshots that are subtly different but + /// still within the threshold. + public static let failed = Self(storage: .failed) + + /// Records only the snapshots that are missing from disk. + public static let missing = Self(storage: .missing) + + /// Does not record any snapshots. If a snapshot is missing a test failure will be raised. This + /// option is appropriate when running tests on CI so that re-tries of tests do not + /// surprisingly pass after snapshots are unexpectedly generated. + public static let never = Self(storage: .never) + + private init(storage: Storage) { + self.storage = storage + } + + private enum Storage: Equatable, Sendable { + case all + case failed + case missing + case never + } + } + + /// Describes the diff command used to diff two files on disk. + /// + /// This type can be created with a closure that takes two arguments: the first argument is + /// is a file path to the currently recorded snapshot on disk, and the second argument is the + /// file path to a _failed_ snapshot that was recorded to a temporary location on disk. You can + /// use these two file paths to construct a command that can be used to compare the two files. + /// + /// For example, to use ImageMagick's `compare` tool and pipe the result into Preview.app, you + /// could create the following `DiffTool`: + /// + /// ```swift + /// extension SnapshotTestingConfiguration.DiffTool { + /// static let compare = Self { + /// "compare \"\($0)\" \"\($1)\" png: | open -f -a Preview.app" + /// } + /// } + /// ``` + /// + /// `DiffTool` also comes with two values: ``DiffTool-swift.struct/ksdiff`` for printing a + /// command for opening [Kaleidoscope](https://kaleidoscope.app), and + /// ``DiffTool-swift.struct/default`` for simply printing the two URLs to the test failure + /// message. + public struct DiffTool: Sendable, ExpressibleByStringLiteral { + var tool: @Sendable (_ currentFilePath: String, _ failedFilePath: String) -> String + + public init( + _ tool: @escaping @Sendable (_ currentFilePath: String, _ failedFilePath: String) -> String + ) { + self.tool = tool + } + + public init(stringLiteral value: StringLiteralType) { + self.tool = { "\(value) \($0) \($1)" } + } + + /// The [Kaleidoscope](http://kaleidoscope.app) diff tool. + public static let ksdiff = Self { + "ksdiff \($0) \($1)" + } + + /// The default diff tool. + public static let `default` = Self { + """ + @\(minus) + "file://\($0)" + @\(plus) + "file://\($1)" + + To configure output for a custom diff tool, use 'withSnapshotTesting'. For example: + + withSnapshotTesting(diffTool: .ksdiff) { + // ... + } + """ + } + public func callAsFunction(currentFilePath: String, failedFilePath: String) -> String { + self.tool(currentFilePath, failedFilePath) + } + } +} + +@available( + iOS, + deprecated: 9999, + message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." +) +@available( + macOS, + deprecated: 9999, + message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." +) +@available( + tvOS, + deprecated: 9999, + message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." +) +@available( + watchOS, + deprecated: 9999, + message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." +) +@available( + visionOS, + deprecated: 9999, + message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." +) +extension SnapshotTestingConfiguration.Record: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: BooleanLiteralType) { + self = value ? .all : .missing + } +} + +@available( + *, + deprecated, + renamed: "SnapshotTestingConfiguration.DiffTool.default", + message: "Use '.default' instead of a 'nil' value for 'diffTool'." +) +extension SnapshotTestingConfiguration.DiffTool: ExpressibleByNilLiteral { + public init(nilLiteral: ()) { + self = .default + } +} diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift new file mode 100644 index 000000000..4a392ff16 --- /dev/null +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -0,0 +1,52 @@ +#if canImport(Testing) + @_spi(Experimental) import Testing + + @_spi(Experimental) + extension Trait where Self == _SnapshotsTestTrait { + /// Configure snapshot testing in a suite or test. + /// + /// - Parameters: + /// - record: The record mode of the test. + /// - diffTool: The diff tool to use in failure messages. + public static func snapshots( + record: SnapshotTestingConfiguration.Record? = nil, + diffTool: SnapshotTestingConfiguration.DiffTool? = nil + ) -> Self { + _SnapshotsTestTrait( + configuration: SnapshotTestingConfiguration( + record: record, + diffTool: diffTool + ) + ) + } + + /// Configure snapshot testing in a suite or test. + /// + /// - Parameter configuration: The configuration to use. + public static func snapshots( + _ configuration: SnapshotTestingConfiguration + ) -> Self { + _SnapshotsTestTrait(configuration: configuration) + } + } + + /// A type representing the configuration of snapshot testing. + @_spi(Experimental) + public struct _SnapshotsTestTrait: CustomExecutionTrait, SuiteTrait, TestTrait { + public let isRecursive = true + let configuration: SnapshotTestingConfiguration + + public func execute( + _ function: @escaping () async throws -> Void, + for test: Test, + testCase: Test.Case? + ) async throws { + try await withSnapshotTesting( + record: configuration.record, + diffTool: configuration.diffTool + ) { + try await function() + } + } + } +#endif diff --git a/Sources/SnapshotTesting/Snapshotting.swift b/Sources/SnapshotTesting/Snapshotting.swift index 02c655409..4e984f783 100644 --- a/Sources/SnapshotTesting/Snapshotting.swift +++ b/Sources/SnapshotTesting/Snapshotting.swift @@ -20,7 +20,6 @@ public struct Snapshotting { /// - diffing: How to diff and convert the snapshot format to and from data. /// - asyncSnapshot: An asynchronous transform function from a value into a diffable snapshot /// format. - /// - value: A value to be converted. public init( pathExtension: String?, diffing: Diffing, @@ -37,7 +36,6 @@ public struct Snapshotting { /// - pathExtension: The path extension applied to references saved to disk. /// - diffing: How to diff and convert the snapshot format to and from data. /// - snapshot: A transform function from a value into a diffable snapshot format. - /// - value: A snapshot value to be converted. public init( pathExtension: String?, diffing: Diffing, @@ -76,7 +74,6 @@ public struct Snapshotting { /// /// - Parameters: /// - transform: A transform function from `NewValue` into `Value`. - /// - otherValue: A value to be transformed. public func pullback(_ transform: @escaping (_ otherValue: NewValue) -> Value) -> Snapshotting { @@ -93,7 +90,6 @@ public struct Snapshotting { /// /// - Parameters: /// - transform: A transform function from `NewValue` into `Async`. - /// - otherValue: A value to be transformed. public func asyncPullback( _ transform: @escaping (_ otherValue: NewValue) -> Async ) -> Snapshotting { diff --git a/Sources/SnapshotTesting/Snapshotting/CGPath.swift b/Sources/SnapshotTesting/Snapshotting/CGPath.swift index 1e8c30444..cd48ec40e 100644 --- a/Sources/SnapshotTesting/Snapshotting/CGPath.swift +++ b/Sources/SnapshotTesting/Snapshotting/CGPath.swift @@ -25,8 +25,11 @@ /// match. 98-99% mimics /// [the precision](http://zschuessler.github.io/DeltaE/learn/#toc-defining-delta-e) of the /// human eye. + /// - drawingMode: The drawing mode. public static func image( - precision: Float = 1, perceptualPrecision: Float = 1, drawingMode: CGPathDrawingMode = .eoFill + precision: Float = 1, + perceptualPrecision: Float = 1, + drawingMode: CGPathDrawingMode = .eoFill ) -> Snapshotting { return SimplySnapshotting.image( precision: precision, perceptualPrecision: perceptualPrecision diff --git a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift new file mode 100644 index 000000000..15a1f2eb2 --- /dev/null +++ b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift @@ -0,0 +1,307 @@ +#if canImport(Testing) +import Testing +import Foundation +import InlineSnapshotTesting +@_spi(Experimental) import SnapshotTesting + +@Suite( + .snapshots( + record: .missing + ) +) +struct AssertInlineSnapshotTests { + @Test func inlineSnapshot() { + assertInlineSnapshot(of: ["Hello", "World"], as: .dump) { + """ + ▿ 2 elements + - "Hello" + - "World" + + """ + } + } + + @Test func inlineSnapshot_NamedTrailingClosure() { + assertInlineSnapshot( + of: ["Hello", "World"], as: .dump, + matches: { + """ + ▿ 2 elements + - "Hello" + - "World" + + """ + }) + } + + @Test func inlineSnapshot_Escaping() { + assertInlineSnapshot(of: "Hello\"\"\"#, world", as: .lines) { + ##""" + Hello"""#, world + """## + } + } + + @Test func customInlineSnapshot() { + assertCustomInlineSnapshot { + "Hello" + } is: { + """ + - "Hello" + + """ + } + } + + @Test func customInlineSnapshot_Multiline() { + assertCustomInlineSnapshot { + """ + "Hello" + "World" + """ + } is: { + #""" + - "\"Hello\"\n\"World\"" + + """# + } + } + + @Test func customInlineSnapshot_SingleTrailingClosure() { + assertCustomInlineSnapshot(of: { "Hello" }) { + """ + - "Hello" + + """ + } + } + + @Test func customInlineSnapshot_MultilineSingleTrailingClosure() { + assertCustomInlineSnapshot( + of: { "Hello" } + ) { + """ + - "Hello" + + """ + } + } + + @Test func customInlineSnapshot_NoTrailingClosure() { + assertCustomInlineSnapshot( + of: { "Hello" }, + is: { + """ + - "Hello" + + """ + } + ) + } + + @Test func argumentlessInlineSnapshot() { + func assertArgumentlessInlineSnapshot( + expected: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) { + assertInlineSnapshot( + of: "Hello", + as: .dump, + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "is", + trailingClosureOffset: 1 + ), + matches: expected, + file: file, + function: function, + line: line, + column: column + ) + } + + assertArgumentlessInlineSnapshot { + """ + - "Hello" + + """ + } + } + + @Test func multipleInlineSnapshots() { + func assertResponse( + of url: () -> String, + head: (() -> String)? = nil, + body: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) { + assertInlineSnapshot( + of: """ + HTTP/1.1 200 OK + Content-Type: text/html; charset=utf-8 + """, + as: .lines, + message: "Head did not match", + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "head", + trailingClosureOffset: 1 + ), + matches: head, + file: file, + function: function, + line: line, + column: column + ) + assertInlineSnapshot( + of: """ + + + + + Point-Free + + + +

What's the point?

+ + + """, + as: .lines, + message: "Body did not match", + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "body", + trailingClosureOffset: 2 + ), + matches: body, + file: file, + function: function, + line: line, + column: column + ) + } + + assertResponse { + """ + https://www.pointfree.co/ + """ + } head: { + """ + HTTP/1.1 200 OK + Content-Type: text/html; charset=utf-8 + """ + } body: { + """ + + + + + Point-Free + + + +

What's the point?

+ + + """ + } + } + + @Test func asyncThrowing() async throws { + func assertAsyncThrowingInlineSnapshot( + of value: () -> String, + is expected: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) async throws { + assertInlineSnapshot( + of: value(), + as: .dump, + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "is", + trailingClosureOffset: 1 + ), + matches: expected, + file: file, + function: function, + line: line, + column: column + ) + } + + try await assertAsyncThrowingInlineSnapshot { + "Hello" + } is: { + """ + - "Hello" + + """ + } + } + + @Test func nestedInClosureFunction() { + func withDependencies(operation: () -> Void) { + operation() + } + + withDependencies { + assertInlineSnapshot(of: "Hello", as: .dump) { + """ + - "Hello" + + """ + } + } + } + + @Test func carriageReturnInlineSnapshot() { + assertInlineSnapshot(of: "This is a line\r\nAnd this is a line\r\n", as: .lines) { + """ + This is a line\r + And this is a line\r + + """ + } + } + + @Test func carriageReturnRawInlineSnapshot() { + assertInlineSnapshot(of: "\"\"\"#This is a line\r\nAnd this is a line\r\n", as: .lines) { + ##""" + """#This is a line\##r + And this is a line\##r + + """## + } + } +} + +private func assertCustomInlineSnapshot( + of value: () -> String, + is expected: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column +) { + assertInlineSnapshot( + of: value(), + as: .dump, + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "is", + trailingClosureOffset: 1 + ), + matches: expected, + file: file, + function: function, + line: line, + column: column + ) +} + +#endif diff --git a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift index 7292f5895..70bace93c 100644 --- a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift +++ b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift @@ -5,13 +5,9 @@ import XCTest final class InlineSnapshotTestingTests: XCTestCase { override func invokeTest() { - SnapshotTesting.diffTool = "ksdiff" - // SnapshotTesting.isRecording = true - defer { - SnapshotTesting.diffTool = nil - SnapshotTesting.isRecording = false + withSnapshotTesting(record: .missing, diffTool: .ksdiff) { + super.invokeTest() } - super.invokeTest() } func testInlineSnapshot() { diff --git a/Tests/SnapshotTestingTests/DeprecationTests.swift b/Tests/SnapshotTestingTests/DeprecationTests.swift new file mode 100644 index 000000000..f3725a65a --- /dev/null +++ b/Tests/SnapshotTestingTests/DeprecationTests.swift @@ -0,0 +1,13 @@ +import SnapshotTesting +import XCTest + +final class DeprecationTests: XCTestCase { + @available(*, deprecated) + func testIsRecordingProxy() { + SnapshotTesting.record = true + XCTAssertEqual(isRecording, true) + + SnapshotTesting.record = false + XCTAssertEqual(isRecording, false) + } +} diff --git a/Tests/SnapshotTestingTests/RecordTests.swift b/Tests/SnapshotTestingTests/RecordTests.swift new file mode 100644 index 000000000..cfe40e83f --- /dev/null +++ b/Tests/SnapshotTestingTests/RecordTests.swift @@ -0,0 +1,204 @@ +import SnapshotTesting +import XCTest + +class RecordTests: XCTestCase { + var snapshotURL: URL! + + override func setUp() { + super.setUp() + + let testName = String( + self.name + .split(separator: " ") + .flatMap { String($0).split(separator: ".") } + .last! + ) + .prefix(while: { $0 != "]" }) + let fileURL = URL(fileURLWithPath: #file, isDirectory: false) + let testClassName = fileURL.deletingPathExtension().lastPathComponent + let testDirectory = + fileURL + .deletingLastPathComponent() + .appendingPathComponent("__Snapshots__") + .appendingPathComponent(testClassName) + snapshotURL = + testDirectory + .appendingPathComponent("\(testName).1.json") + try? FileManager.default + .removeItem(at: snapshotURL.deletingLastPathComponent()) + try? FileManager.default + .createDirectory(at: testDirectory, withIntermediateDirectories: true) + } + + override func tearDown() { + super.tearDown() + try? FileManager.default + .removeItem(at: snapshotURL.deletingLastPathComponent()) + } + + #if canImport(Darwin) + func testRecordNever() { + XCTExpectFailure { + withSnapshotTesting(record: .never) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription == """ + failed - The file “testRecordNever.1.json” couldn’t be opened because there is no such file. + """ + } + + XCTAssertEqual( + FileManager.default.fileExists(atPath: snapshotURL.path), + false + ) + } + #endif + + #if canImport(Darwin) + func testRecordMissing() { + XCTExpectFailure { + withSnapshotTesting(record: .missing) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription.hasPrefix( + """ + failed - No reference was found on disk. Automatically recorded snapshot: … + """) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "42" + ) + } + #endif + + #if canImport(Darwin) + func testRecordMissing_ExistingFile() throws { + try Data("999".utf8).write(to: snapshotURL) + + XCTExpectFailure { + withSnapshotTesting(record: .missing) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription.hasPrefix( + """ + failed - Snapshot does not match reference. + """) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "999" + ) + } + #endif + + #if canImport(Darwin) + func testRecordAll_Fresh() throws { + XCTExpectFailure { + withSnapshotTesting(record: .all) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription.hasPrefix( + """ + failed - Record mode is on. Automatically recorded snapshot: … + """) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "42" + ) + } + #endif + + #if canImport(Darwin) + func testRecordAll_Overwrite() throws { + try Data("999".utf8).write(to: snapshotURL) + + XCTExpectFailure { + withSnapshotTesting(record: .all) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription.hasPrefix( + """ + failed - Record mode is on. Automatically recorded snapshot: … + """) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "42" + ) + } + #endif + + #if canImport(Darwin) + func testRecordFailed_WhenFailure() throws { + try Data("999".utf8).write(to: snapshotURL) + + XCTExpectFailure { + withSnapshotTesting(record: .failed) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription.hasPrefix( + """ + failed - Snapshot does not match reference. A new snapshot was automatically recorded. + """) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "42" + ) + } + #endif + + func testRecordFailed_NoFailure() throws { + try Data("42".utf8).write(to: snapshotURL) + let modifiedDate = + try FileManager.default + .attributesOfItem(atPath: snapshotURL.path)[FileAttributeKey.modificationDate] as! Date + + withSnapshotTesting(record: .failed) { + assertSnapshot(of: 42, as: .json) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "42" + ) + XCTAssertEqual( + try FileManager.default + .attributesOfItem(atPath: snapshotURL.path)[FileAttributeKey.modificationDate] as! Date, + modifiedDate + ) + } + + #if canImport(Darwin) + func testRecordFailed_MissingFile() throws { + XCTExpectFailure { + withSnapshotTesting(record: .failed) { + assertSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription.hasPrefix( + """ + failed - No reference was found on disk. Automatically recorded snapshot: … + """) + } + + try XCTAssertEqual( + String(decoding: Data(contentsOf: snapshotURL), as: UTF8.self), + "42" + ) + } + #endif +} diff --git a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift index 07aa425a1..95a66b18f 100644 --- a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift @@ -21,15 +21,13 @@ import XCTest #endif final class SnapshotTestingTests: XCTestCase { - override func setUp() { - super.setUp() - diffTool = "ksdiff" - // isRecording = true - } - - override func tearDown() { - isRecording = false - super.tearDown() + override func invokeTest() { + withSnapshotTesting( + record: .missing, + diffTool: .ksdiff + ) { + super.invokeTest() + } } func testAny() { @@ -1316,15 +1314,6 @@ final class SnapshotTestingTests: XCTestCase { assertSnapshot(of: view, as: .image(layout: .device(config: .tv)), named: "device") } #endif - - @available(*, deprecated) - func testIsRecordingProxy() { - SnapshotTesting.record = true - XCTAssertEqual(isRecording, true) - - SnapshotTesting.record = false - XCTAssertEqual(isRecording, false) - } } #if os(iOS) @@ -1344,30 +1333,3 @@ final class SnapshotTestingTests: XCTestCase { "accessibility-extra-extra-extra-large": .accessibilityExtraExtraExtraLarge, ] #endif - -#if os(Linux) || os(Windows) - extension SnapshotTestingTests { - static var allTests: [(String, (SnapshotTestingTests) -> () throws -> Void)] { - return [ - ("testAny", testAny), - ("testAnySnapshotStringConvertible", testAnySnapshotStringConvertible), - ("testAutolayout", testAutolayout), - ("testDeterministicDictionaryAndSetSnapshots", testDeterministicDictionaryAndSetSnapshots), - ("testEncodable", testEncodable), - ("testMixedViews", testMixedViews), - ("testMultipleSnapshots", testMultipleSnapshots), - ("testNamedAssertion", testNamedAssertion), - ("testPrecision", testPrecision), - ("testSCNView", testSCNView), - ("testSKView", testSKView), - ("testTableViewController", testTableViewController), - ("testTraits", testTraits), - ("testTraitsEmbeddedInTabNavigation", testTraitsEmbeddedInTabNavigation), - ("testTraitsWithView", testTraitsWithView), - ("testUIView", testUIView), - ("testURLRequest", testURLRequest), - ("testWebView", testWebView), - ] - } - } -#endif diff --git a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift new file mode 100644 index 000000000..a3a7ad2f5 --- /dev/null +++ b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift @@ -0,0 +1,54 @@ +#if compiler(>=6) && canImport(Testing) +@_spi(Experimental) import Testing +@_spi(Experimental) @_spi(Internals) import SnapshotTesting + + +struct SnapshotsTraitTests { + @Test(.snapshots(diffTool: "ksdiff")) + func testDiffTool() { + #expect( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + == "ksdiff old.png new.png" + ) + } + + @Suite(.snapshots(diffTool: "ksdiff")) + struct OverrideDiffTool { + @Test(.snapshots(diffTool: "difftool")) + func testDiffToolOverride() { + #expect( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + == "difftool old.png new.png" + ) + } + + @Suite(.snapshots(record: .all)) + struct OverrideRecord { + @Test + func config() { + #expect( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + == "ksdiff old.png new.png" + ) + #expect(SnapshotTestingConfiguration.current?.record == .all) + } + + @Suite(.snapshots(record: .failed, diffTool: "diff")) + struct OverrideDiffToolAndRecord { + @Test + func config() { + #expect( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + == "diff old.png new.png" + ) + #expect(SnapshotTestingConfiguration.current?.record == .failed) + } + } + } + } +} +#endif diff --git a/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift b/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift new file mode 100644 index 000000000..b6f6c6f57 --- /dev/null +++ b/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift @@ -0,0 +1,35 @@ +import XCTest + +@_spi(Internals) @testable import SnapshotTesting + +class WithSnapshotTestingTests: XCTestCase { + func testNesting() { + withSnapshotTesting(record: .all) { + XCTAssertEqual( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png"), + """ + @− + "file://old.png" + @+ + "file://new.png" + + To configure output for a custom diff tool, use 'withSnapshotTesting'. For example: + + withSnapshotTesting(diffTool: .ksdiff) { + // ... + } + """ + ) + XCTAssertEqual(SnapshotTestingConfiguration.current?.record, .all) + withSnapshotTesting(diffTool: "ksdiff") { + XCTAssertEqual( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png"), + "ksdiff old.png new.png" + ) + XCTAssertEqual(SnapshotTestingConfiguration.current?.record, .all) + } + } + } +} diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testCGPath.macOS.png b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testCGPath.macOS.png index e6e25b5b7978fdb04c5a284dc6c141d1906849a7..0731e43150e185f0fb7bb7a075d8083d2b64c1bf 100644 GIT binary patch delta 3179 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 UpWA-{HT`^6h*`c1vug}_70#PL%>V!Z diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSView.1.png b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSView.1.png index 2c9a5ce573833812d600c97cee8068e4a2cb5176..5c2d5782cf587d30d8a00147c5064b5286eac65d 100644 GIT binary patch delta 3481 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 delta 3306 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 Mx+Xf++Sus-0GN6nkN^Mx diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSView.2.txt b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSView.2.txt index a9694f789..5880103ba 100644 --- a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSView.2.txt +++ b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSView.2.txt @@ -1,4 +1,4 @@ -[ AF ! wLU ] h=--- v=--- NSButton "Push Me" f=(0,0,83,32) b=(-) => <_NSViewBackingLayer> - [ A ! wLU ] h=--- v=--- NSButtonBezelView f=(0,0,83,32) b=(-) => <_NSViewBackingLayer> - [ AF ! wLU ] h=--- v=--- NSButtonTextField "Push Me" f=(11,7,61,15) b=(-) => +[ AF ! wLU ] h=--- v=--- NSButton "Push Me" f=(0,0,87,32) b=(-) => + [ A ! wLU ] h=--- v=--- NSButtonBezelView f=(0,0,87,32) b=(-) => + [ AF ! wLU ] h=--- v=--- NSButtonTextField "Push Me" f=(11,6,65,16) b=(-) => A=autoresizesSubviews, C=canDrawConcurrently, D=needsDisplay, F=flipped, G=gstate, H=hidden (h=by ancestor), L=needsLayout (l=child needsLayout), U=needsUpdateConstraints (u=child needsUpdateConstraints), O=opaque, P=preservesContentDuringLiveResize, S=scaled/rotated, W=wantsLayer (w=ancestor wantsLayer), V=needsVibrancy (v=allowsVibrancy), #=has surface diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSViewWithLayer.2.txt b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSViewWithLayer.2.txt index d5f30a139..c4763d5c4 100644 --- a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSViewWithLayer.2.txt +++ b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testNSViewWithLayer.2.txt @@ -1,2 +1,2 @@ -[ A ! W U ] h=--- v=--- NSView f=(0,0,10,10) b=(-) => <_NSViewBackingLayer> +[ A ! W U ] h=--- v=--- NSView f=(0,0,10,10) b=(-) => A=autoresizesSubviews, C=canDrawConcurrently, D=needsDisplay, F=flipped, G=gstate, H=hidden (h=by ancestor), L=needsLayout (l=child needsLayout), U=needsUpdateConstraints (u=child needsUpdateConstraints), O=opaque, P=preservesContentDuringLiveResize, S=scaled/rotated, W=wantsLayer (w=ancestor wantsLayer), V=needsVibrancy (v=allowsVibrancy), #=has surface diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testPrecision.macos.png b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testPrecision.macos.png index d0f149a54bd2480138d60287ce911f609bd1f578..e13d013030b92f452eeebfeaca522e19ee9f1294 100644 GIT binary patch delta 1255 zcmV948adBi|V8F*QG&Dr7udn3q?@xh&fqcKF8lph8wYAa7$qBi;yHiF+hUEOSv$Hfd zHpc8qN=nGW!a{P4lmUD;G&C@?n3xzcF)`tX)YR0_^Yb&MrKM>FDAA)gK0Zz(BO^35 zHN^*~uCckf$?ShI=HcN%o#}t669wwOT#W{U)&V6GT+tjQbNr{xK0ZF^;^KlXFE7c~ z)|MO`9DYmEpLQrQ;PLU1PESu+K67+*BpVwWRvaXTDXFyv)cgB8b#!#lz`y`qUtjZq zSXo(7e0)6R=jVSbV5_UE)Y8&Ib8~Z~c%5}|aiQeoWJ-TZO5$UX)6g1FRaI3qI5?;j z)9vjo0}$XTwPsJU0og1`TF`&cXv0LnVGS7 za5O9;At8bG_V%c;v5_4KBO@b~zT|Yax3{w#2;1V~VoFU-<%fBDd$ajsV`B+GVwXon zMUlR~bWM{4>i+(orl+U*$v)dau0R5Zl$V$DAaQ?wKun8@iYPZXm)_pqXnT8`0s;a! z^{1a}Yin!_*t#M}oFi9PS1KqdU?3sU;|KQg^5WE@Pf4IGEiEZ5EKJk^r$Ao7t`G_r zIQnmHZdh^^+F;jlvcA6lWuRVOUI=kO)Lm;7b%^ge^sy>u`40!77rcnkEn)-FFHC}a!Sb^CFw!JfD0UE>W&nSDD>b}-yr}( zjwn(Gb@mzu3e^plTT~!aIAddDb@BX>4#mRI(2(sa6d^I$-{0rC6}~>m5$SX<$BP;p zE)Wn-d^XXfpj!I)_^>HfR#rr(T3%k}bzFaZe1}LwYd~TCii!$C6%`70Tx4V<`cz6g+RK9Ec=;3~qnVCsQ_SjMB>FJC&1qTPy z)6)}8PEIl%+UDlw6cQ4mGEljl;CwSPGmJ~s*VnV_61bYRwKXj)EKqN6FXK?~S5|*k zCW}MCR^vcnlET75IzKgwuZ>>s2OZTtxZTuLr0 z$5_#$$FWt#&#%JC6yG^}^a;nH0@c>mvYmxrR#9LZ5fMSd!^0FB8mg$`{b0PXigEJ^ z=Yj*|Dck_yPdLum*_ld9ODQ`$`?p`Yq+axXl}D}qrx-~cpIJaY!O9W1s>MnLE?1A7 zh|esbDfp~oXJ@Abo*Z9V2TD#*|DuiP(fb#J{hKlAfRc&64k#T^G7*qz_7kU@y!p&z RN*DkD002ovPDHLkV1m2!Xt@9Y delta 1167 zcmV;A1aSMI6Uh>=%LIRENklmR`|*A5xz~U7|8?KG?sv|4&U?;% z&O6=9@avC|F0u?*$s%+BV?ZZL&=7Q@bfN?q5QOO#^o; z)6LBd-QC@pz%BKgfHZ1YBub<8{#&&=QG!SJqeMMEJ`&>DPsqi^1--w&|FxxT{+gyQ z6pf9IQFnJY?e2f>65g0RJv}KdE{>9ulPM-9=8Kuih9)K^Xl7=HmX?<2?Cgx3ot-H% zGLo&4nVCt}*4D}tO3<1UH8L_nm6er}C5cW>P6+*@qodT*(?ikG(I(?+8iRv_R9#(d zG8GwnYHEsIJ3Bj6RaIp&uB4%<>n$uS7&jLmA5Z=L{j`6)yv(dCC@6?tUtg)HsEGFW z_m%AV6BcCD)YPzkloefFU9_^YLIVQ>l#-Id`iF*wsH3Cf(_GOGS&M3HY^2W4&M);{ zU0sQfq4~+1uMQ97qcY2%z-zbh^B}q~YOVDlacLt3#v{#2_B|`ub8^ zTN^n!IkA6f5fKp-9v;rtn4h0#&ykmxM^;wK?L(F*n6F6D`SF3?-ri_yYm0T~=H?nn z;y4cv4@yi-WT(EdvBA3)-(i(}oq~b_BS~BlNGUBXB@p%S@IZTed*tu$&xeKYvP2;W zCL|<$sSqxOjYtK78(9w0*VjjLb92&R_8UPS0-}Eqe<>+9MO6%rC6OVsS_?57QaC@yPjYlO>^pyIy1z9u&}H%kzU{nGdb*E1)! zwzlN%?#_}3EJ}^YT9g{4nB(K)W1L!BTT5PEUdA^6ffI%m!99@5)rgdwqfAdvQ$s_8Y*zg^PuhlCadJ@9^0+9)w6wIaCbBNFts2pcC~PJt zCx`86adDAl9(=Yz(8j}nJbZ2F?d>JF%y)kzJ3E_ANA^R8Lvld5086T`ucyh$Nj9F9 zm8H5m*Ua^>Gkm5wIyz#t4PGyB;Z&cVo)}@k;Dn2di}6#nq^73Q>FFsoH8mM4al}38 zyIxXK5|x#esb0e(QCNrvTRH8(Lik;ZFDxu1S65f|4z{|wYIF@pM@P!Y$RHGeh+%(H z;d=O;kMTCY^M2g(^Yd9kfIDLy)J%w7VPRn`K4M%=`N7vP{BeaJ`@i1H%L{V{WH_Yj z?`)hufVn&3A>7W}+nXF59Lzx!_x&hQig))9P0%!$|3lCD?XBoU2~wyNr4uE{fFMk_ hD4i%l1_WWh0fp4TXj<}HSO5S307(Z$PDHLkV1jMrIOYHV diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testWebView.macos.png b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testWebView.macos.png index f6fd0490cc70159e324432f223733c19b58cc5ac..ab2073c852b6f9c01aa23eda0e87cda3fadf7c8a 100644 GIT binary patch delta 57876 zcmd3O_dnI|A2)IkiAt2+63NOz=ond9*(5vJtIQmnw^0;{kIgB2%iiOVl)d++?45D! zabKrC_33**?myuEA&<9?bFS-pU9amkp3moX(uRq%hKchIT27yXNvep8i&3eE61HB2 zZu$$nCjJg1@PF}qg0%6&nAQ8!-(Rs9>|-q*u+C`N43*m3#(L)TrAUX7)!Nh0<-MJNNPM2`SCX z@bH6uN1n3~kT84V{rh8@MGV5bF2MCpI{w|Kk1;8;->{*r&Ak;u2X|}+Go^?NYXoX{ z7&+XcGO5F(&vHb2#P#0h$<>5RO>G~?s731_ds>+KkXpP&8XfQ3tvHD<5H?MGxW4<3 zsE)lf7?k#w7+!LM{d>RPU&B~c})vTaqYHq`n? zmFc{A@czq!38f#`+}Phqf`Lgnz+yYU>rwz?i-F(453h}j%y_ERJFziyvWA#}Yv1?C znPN%>+S@H`DNFCtp3j8(`XN&qyN7Q@H1rg7>UZDh!g|FyHslfcZ+`5s9# zi+g=VYeuIDRK;z&U+TJ=Zr130Q77s{m0081@DFX<(6|O&qc^%+*e(H+%`8OGSSz&N|QLO>k8Qc_H0SZ>Y-}((CGS z%$PS6azn6{q??-!^Tnq;l*TZcEOW|9OMh5SS_3 zfefDKeUjuVL5LS_-5a$SL+1bBzBhd*)zh#guz&yZ`t0fay znru|jpPG4;OFkaqej|JakLyQ%5Y4XnP~shfNQ;ua^Mp;u{pSxG$NjIJ1Dl^p&5YOG z>*Bd|?az5*Ru%zU)jX%K)^n9onRz-?F%CixWQtmCbv}|({!k<}*u0dG*wnUTUe4eZ zR3taF!c3xCbD=h9KkzOA&YpkEyYSjql6#cevCcn>zKYkG5D!>DZ^Ta2%>$i-DX zuWmBqdVBwzdK7i4frdb#OG~WjTysvU6d8HHl-zw!<_AbAZ>9wsXwV1PhAIn0hbI`` zFtWeAclIXm=)EyDOZ6uNF+LJ?#%z>{Z|eEfHP}*CFQU<28Y3|X%s3-jqlhgfF;ZRo zw0AE?k5F_mCJ%<2D-6svoftzbtP;X*1$;XT_!_+?L_8lgqK_Nc}FCE6B zF@Ph(KqknaqiUQ{2R-)K*0^MY#fYn~sFqB`B4qzEpFxyVG5b-|WFK8xH=0-KLbH|k z9>Xo+1E;Z)0<}=B&1kb&9?{)e3I#>Q<5?Sv4LMV7PtEMd(I6T|p6)2z`pyl`OMDa| zi6>RhSp03^BhYWpfZKujwjCU+R-UI$m$ljOVUBYR+;pfiZ1f(!sDC%v0_o?NJ=jV? zxU4?(bt`A_J2A0bRR70JJv04`0ht;{ABjl0(<&(LHPyUg#jUl|9IP{t<@zaHgu*9;ex27wRj@G;%JjZs`J~nl zY~U?c12GpfoJ{XG8u3W1gQPrp#cvmq#Tt z!H5g6@tjzj@m%ewV^8VjuH-F>Y_|dPO9iQNq~4Yk- z1-fhedchdoKhHz#2scOD_*4Gety%rch2N&0-mx;|lwovzT6o5rb@%zn(GL2bYcl-G zzCEElSSq1rZLn*C6CR82#CU05cubus9PgdRMA+HBH_;r(={Rt@qxXqO{BenO^g>?9 zkeLsYA0yJdDJhGp`tS-%fewv8^#ST`kfb(tD% zCBA5w>&+ZQ54u^y#glK~!KQt;?bEecXiLK`0dJ6FME9@mWc(`c83s=;uBGNmV}Qe8afD3`JO_ zW(iG!cyM96P>c0w8P7-$sq=es6uo`p6<8$;&CdcxES?S4pQC3Laa;R|=Ep}y{MLhp z{5H2j5&e2(f)1(C_go9K%bq2Kru6eeL#ceQ?35hsk4;44{wX&}YJ;A5sIt=F0+E;q z;TG}S)F>#iIh=oXiaAqDQ8Do3AQiQvPS>hs;4yQ;nK>crGWxt>Rvr6s@%*uk zaF*I#5(qddE6NK5MzjlmJKH010jsWIYwc-#N+WvI?l(nR!YjKfc`_knSAHIvH=e#s zkE&kePqZW%H@r)=87V<^Pz1JoH1s35B1b6VKkch>=2x%)=TZ`8%`Ax#EwY|Nt1&;F zX%0VLOV+W&I1RO(zK@qI$z<*yhzAiw!}c|uH%+I_jV#+voKCg6OHXZY=Pr(yogsbU ztOgVB?cDryiXzH~LZr;Ict-WtD&g6lEcXVO;`x6h2$pZjq$5%DY6hez5C?`2zV!V* ziC(HSoony+yVoLVy*0cjIjmT3lhbADqw&fD~a|9XCmhX^I1=jXP3wn(iIDd!-ob~Qc=f6*|oh^*r?PN;Y?*;#^ z^={+I&Z|Dfl>q;C1!A42B&qiG9H;67#kp~-dZ=JfW3T>@FExjRSy_`nrg*&1dMMFj ze9>KU2|v|p#?-Z?hVn8yiT#Af4$SV z{)AJ1`A^5O3&*P&GxmxzI-B;Gsa`s-I~UBy5}V%-*)sK1OJ#kr${D|LP%_N6?vB1% zS9ezUb{B3nsbvAW7jRn<9|ha;OF#ZmBu;@PV4D+_4A|3G;Ri4L%Bk^Tur1+KhT~iN z!scuPSqUaL@w$}-+a>V4Le33lCi)1Lu2iQQ2k^fMcQtQ`ogM7=Ip30d>5kkjT*$t( z%3|_!uB`m{2Q0Biw@Wru7=IrEJg?ashR|A3Tw9j&(10)AgKbUvH+Td$Zg*xEB<($~ zgwC1XwEMhKpB$0eP2o;IVj7(BV|?1$HX|SBbZskd;zfR%TlVyz=)Dy))xBTF`gaqa z6KwB1Jh<$lAZQKt_pD2_&{dEE^R%Vt93EDFo2|6jhU*lWM~3>}XE>Er!WUUAI(WvW zk2lRher3{^NSp)}W-@9fHSLHPL36Ng2t*@41PH7X(Gd!6w(=@EIq9Lz*GW*4QjcUp z^T#hh=9ZwMQ1l=!6CoghzY#MDAmxoWaXDcRmx~5n)@;jgv8hkSI#Ic$(QvW3P00oU zV|JBnZwucLbK_;R_y7DX26W>n7X$yB>hCA2QalO6i#taNj==fw@B?3!xk~Bu6k5vn z3@oj5Rc2-lrP|YN7Mw*r+6H+s23P+VS@t#Cl6ss!Bzd0a9eU;9!Zl?{P;~pxn<`V` zoaPd&8zxS5xH~6$VsTbvck;z|6}@L0b+aYt2&%6QOK(x z)Sf0~CAnkLOqIk;ayk_M;KF4*uP4;;#1D8T7@B>-lBp8#YJ;v;u~Fe(r6PU@va`^2 z>(GQP+B0|{?15Hh(It4}TIl*A9Weu#tkZ)*@C;rgNWsmlca3=lw__(2P{}uY|nDDfoC*FgM3GwEjP@_XS$cZp>(c0+LpVR--?qaeeAN4WAy}i9r z&CPN>`Nj?JTdJOXB`ti~biNSVuY+zAn7B8$DVVTJxOH#7T-kD>8e`Fysj+@BOcmJ`-s``ym$&4C65Uk4#J( z|H$o;p0@fxx;9^OIt3@EVrZ~ zcsb8!p(}|P{~w|I)_=kjC2KPH%=?xO9Dfe~&(QOL5WXCaM6ni|cYS6eV%O{9w;6t# zsuZ^hrKn~&`dwz&`ATE3Yp{mdiJdrzcUc=p9a|_pA^ywIuE0Q0$jwIuQvXw7`fH0h zpv(ueG_o|KAAS(p+m!ke?lM$hGW)@0d_Ab}pmfw;z9!ADT}`C8xY%^8!s*!k>gHU> zj^9^RZb|XrS7bCX-|GC(5galfJ>%zc+w6mVeJoli6>87{V(i^RxBa;_Soluc^AVYU3>mB5I#6?%^_$l@-^ zHMy90L`+bL)x!&VS_byPp{>1HP)cUzYFx`AN0LKWh4YFf6=gRc)wFh{b2gL0Vt+Oo zs)mAhM6qwRan+HJG`3(TS;Ft^cJL%`OwGq)#m&NW5!%d;9tYbfJh`|)S)}H4y8A$` z!5ZDI4x7@k{#-5N&3=T|kOm}ZVSA}hZzr)jdGlk&Y5+Y|y4obiYBkiT(NVCNY_-5R zzZW^uog#na;Hab_(57Y_nv-ylX7;dSL{rCRCX#2BcAH-0-wG(ch;Z>(TI=ylTG9U% z<6}K(XUE2AIsIu*DDF;rDo^Fo1{gp`PAA-ayNuA``YM}g`+GrD9fm)1UAyj4c_7qa z3D-PTK)^^!l#Z_*xL^w~9gnvR!u@tp$J3!o3KP{HOJ`oC*egVF*V=tLdvOwdk-V_@ z~A4;Pd_F-FB$5~p*BSI#qxnF^L>fbuQS<)z48w* zufKbrvF|R7pOn?@=C-sSGV)`%U+I*+KGkqALS=XvZXP_b#OfGanur(a@eT`}VN<@O zNJ_xq*eQOzNk7&g^zQ);ixr#c)4zpzqW0u(PiB?EZ@Z}S&|w4JVufz!MRp&h>1nun3h%*tv5E$19D&Ecsh$7y)YqvZ}q z1r>XlM&m^Hdb1=<0_1PydehkF@7zSbN8W6d!CZx`?KicKBDf4}UHbOaJBVB}&0e8< zPc;rVO4Tw6uqnZ+yAkXaH#5`T@qIV4v zdE8&qBR67KRl zxjXz(;HHp)tQRr%hqCI_535|vtiY24y7wm;`4cRq>#k`ZoHtH!?APg-JaeN?cX>&! zKCcTihdV|PNZ#^UIf{qk>p<@^L;Qs5lZw)LKGhM?=|1!~Fv1R9Z{H`|Q^L(^2)@yJ zdu&0TQx7U!2Jw_iK{=_cwO2WZ`8Co_@)U_s0}J2e&eA}~&hcVa?qPf|`Rzd@TX4Kp z`We#x^!5T}Rf#Iv;i(XW^iGyc5F<+Lel0n+RYgo*7N8W#kaGMrbn;|40aYeC1i7-c z*w;ewnbn-nZF`xSJDKr3GPb}~KP+-|tcs5+JeFZ7v#P>?pZgjyg3Fd7LN=6TuYr~8 z27;J&Lr(nam>DcNEGRZxVEjehTFN(~plXq&rIRca(o{nLOB>B+rAhg;5aaEbT&)Fv z8MC22*&d+;?WlI>mgKA!YvZ7ETtD(1m$r3xe13JO|MmoU1mx$HCDy%&8RrEakDTc( zJ6JC4AR?c&oa{&yAK@otkBc3rRO7c`q~LR8XEThS^rqeI3qI+RVH&EtA6F9TO`C61 zhdHY(vMNY=o>df0b*3v=%5qvu72-O_r*DP!W(HA}uS4{t>ZHDgc3Xp=FFlLKpPVuM z9D>$RSjf6~>%o;Ooz2H3WnZ5Los?>tAV(48s;PJOh0NT3Fb2p(k$HtYQgO zW0S$F*eD+3w*+|2I^zCDb-pH{#Y}_wUN^$EOzclldF*ekuLUyPSE$X#KSi{=b07a) z_DHgQSzXK!vPBc01-lz1=nE|XgvmY(%)65e}7q$X8Wf$WaTUe?^Z zkX3Sg%B;GZzk*B(`ws|fr;?(BlEcA*e{4;{JbBujgdLN=#=?hJiH|4j9_pqrT0r~B z#@sJ#ouX}oQqdBwHC3!=`$^2T0{;SE zKl`I6KGeWL926x(X9)zqy}WS9SYZRpN>2r3ZH}TMQtiLkX8FZK*c!x7gYJ13x$?X9K zpVlp&;5;pVODbY}@EX-&-U#-6qoNlJtiUlg6sHA_+&=>l6<|ueNw72*}Bt1r3Ygxk4pk~X)PZZSOz=$@K`RF z+KtO}IMEe2y+aa1gUOTcXt7umKc0ev-bc1AwxwS^ZjmI!lC7pi*r--NXVY85gPB?@ zMV7fGR%Ggy+?1|3bh3rNc+!#(AAH6sXG0~JWh{T2o^O7{)2AeZej7DxoES&?sHwg^ z?);eDKzJ#Gru+!JMn<=rZ>(v4g=ZC`Mfn*sw|&W@qL#Z4(!;z?+!3FvKqxKm@sp%E zt(0~okL4=Cw5{b_43<%UQa&69x7B+jhW+g(o?_DYrR)6&<-qoG7CO9VJ~u6&mP*K% z2R8BBmCpH$nTpzQkns?bg}%L_DT?AL7ry|uih-82g$S}K(sNKMvpXCy zUP+@}=CdftS!zFRv}3jz4G>U0iE6$^M~2cl#jU$D?D9I!use%no@L|B9cMQ$wh32o zI+U78I@a`$Rn3G12BL%9P^n0(_KOI&lAHgy#kMKc#*|I^j^%dLkJ1P*Mf|Q_c3}V_ zIYA`81WWk?zJrDoLofu-96&b-5D&(`88H?kU$%Ut30g4t=;8O0p(E$JSIFI-hN4Ty zG$+!?Tgw_U^7SxyaGBSN&fU(HtEk1hia!`4Bi(e>xUzN>Q3aUZ!zXUU64^q?pZeXb*6relZo(m4ykvIxHGeAm zi=@+yHg)A2MWNa3cHy$Man^1!^N;uB`fuwUuO2&MAZXM<&(3DTWx``@EWuFXLh05M9329G2+HTS*F5%cjr$6xMnw@iW`ve^CTxG6p8FeMUR zLqOY={4I~=;d^sm3MR(k6vH>{2-oy=#Tw>WgmP(U3`~z;!?8)PyAEf`j?Owpyk2*+4Tk{0bC;`dZn~YBCt0} zI`EDX0vo2nEtz3AQJru)YfQG6?@js0$d}n9C77kv69-WS+eY7XczRb~L9x-+gNf`d1JhU*<>86d+xD~m@7 zq?YCQKGD2p^|6UfHN{G^(eIusX^yW}aWlF9@TwGk)So<~bZ`CTN$dPx-eyTzhc|L_ zzN~DzUk4-I4b%SKZbJ9(TEo&n6S+~f)=T@RAH%Kq0mL3}6l9%Lfpi%hCqk-0HAmZI z+vS(j&mDjogu+)uRf!a{keeKPt#Y*@%dKo;s%{%k`8XG|{rH2cAl2auY@b$JvTP`b z=;`b*V$;^BbJH13ofOE8L z4nGd40n~^R7#sMBEWa$~amfVgV6xMqC-t&GSqj7A2OigrrxRkckDc9GS?|J;Tjrvk z>&FLc#I6?N7dl3g50VXEd9(4eG4;s|D64+@a@Hv2^wLUU{8W7q6Vu{C!W5PswZD+| zcq`PGv&AHe!;SGbwyvyCfURLs)rS~+ssG0!tZw*iK0M}~%+Mt^>})5u8ZrGdPf>Un z@*%z3a{g=pSM?7!*7S3a5z@Vsxzfu3^P$C7D^n2hJ+pEH=PL!=XZz2r;XZC2&I0$igr6??jwy}>S zmrGy)N%~~)%KKj7+U;fKTq?fhkz_Hijb8d2a*M_B3GdaJ_-3+96~cO!=MJ0FwQ!hE4#Ea>YyY#pXxM|&8!1wdla5S zqq_B||KEU*hwuC8`~MZJ_MTOTyuV zUGiL*X=2G`9$EM8g`S3G%+7c{Lu~VGmQ~iyYv2BYP0959aT|55yt?ej_P!qvR$neL zd2IdD)}6kthfwNmxgGrorbkwGtsAKgVY`ey`B7?-tbk45M<1L0!ylv9eBSCPnP2|6lW>2B27h*mp`o zO6ZU6al0_3WV`zCS&q>~xcWc7QmVm{7`7PXCAQTIe~qT;iT65u@+TAVJADD%_$Gea zLOdf=@>2j1hBAb-pjbkA%m3J7h7I7f_tu1q|LwPa?>Xz8%U+$H7dTl%2PXb{sQ3Zh>EK{s zp_j}}M8DzR|Nq_({ht4Siv~|#>0%}(DK#JsDYAsi!3?^l{>2S`TA5iEf5%1Xh%@sk zB%rt<^fi_S2v=$(!u|*HmD7xOTIxp)Wo2dgO!^&Py732=1}*}c47|h%sqp1B)zrNz z+x!_tyyU@El9|6@2QSlWof&F3YdC>V-T^=>ic*qpi#oPn_P0j^AG*#KKfz-YL;({o z%K7Kv6U9(DVg?J+}Qs`gh_97=I9Ck1m2|rsH68b=g^s%w~}n+E?&F{gjn?_ z#_CXT$X_OuH&6E@cb|8s+kFI(%oE}CZKt(y#4e&JVSx4P=HnOPW_ZJ@RSsdl&l1k& z=cxt(a&;%7$NZMPe+H6nN%GDQ~sjbD5Rqf59XD3dMOE2?VM+vT$O)22Y zwAdo&mB+k*Ea0{1zFvsLTK0gAa%kmgh+;$_pWe&8D@AG!>9kJf^#o)zobVCb zN*m=mkcD~=_d1}n{SJDag`hwiAx_gn?aj=lqHRh015AwCV)$mu=VE!eFk2zod4^s% ztazyGc~WT02`4eXHTT59_)Zx94dT(V=cZp?p9{Z@&&k*ogrZvR(^=y+ZRG|c1d@_` z5G)nh<3Banp*HElU*KCoR{gg(_m^@H5aRcRABp3630AELT@brEw_iQatB?Ra9WLb zLW`_m9&2z9sjBn3&O;`(KadQ<&hPX;auBWrx@)PUfHb2=Ps2LrT%71S&7Lb@nm1szCj|P@Bd;hOf`7_kQ-2e^2 zQ~IdR;A_gs;hgAYzo9q6em3CnSAEJwVcB_IR!5cVi5VP&T|r~<*7qwCM{M9V0E->wV;JF6+mSc0XzVaGK`~rJyt;| zEcfgRx+2oBnAQFo>;)(7>Bfb>C-8GVlVse)52nRmtP~Htoju4~XlBpd@(b?LnURZ; zm;@hRTnRF|7XeunAW&3kM}%$KMMHNP}I(-P^2>R>yfRXs%*QzNFK5xxKdN!Ou!jF~c` zB58Az4}w|#qKw4WflBqwD4k0z1v!_)YWZ9Y=(b{jNU0GL-2em{Jb;?x&RC^O(EFjh zK7bF7-U9@5ZId6p{p%sy$`u70o9vpSlt}$MfB_Sr?J%g3TxeUv(O-ZWB$|6#$ZcGI zW^;Ec=%AKCkv3a40^q6^&f~6T4jWB3(Htd%SNYM<$-zWzoC~ABS zv@4PJFnq*SGtq{iw{f@tZT}ckJHNP>~(!Sm~jT zmJANC9W&*fr)9%6TyI#UA3h*qrsRr;pcZJah0a!>5759!NPi?Q$Q^Z5dim_#uwmZ# zHHS4=OTn?LR=em@hMVh&PRG&Q@#Yz-0p3sa%;R<{{1z|hG5=VHez>b`_a#d{OA%?s zXV7F7w&6G3b-jHdWZe6B$>79tYxWROj@=BV*87xnC0IH1x? zidVBsHAj;xMv`s!Kzb<3auSJiTP^S8&o$yIV$^e;3D@#g1e=QWyF<#~Ti6*kBlo#4 zTfcj++%-){a}6)oNT~OMF^IMGR;>Iu#Z*Pl{gIlJqcy*Nn+~7O`bPg)yWA_ngB5+6 zI(v39FuHD)Q{7YVgqJ?rE)OkqYtx?nM}{$@ z)O_)4V!5`p>Kgyi`zF4z=M4yOk%>m@jmE`bvr$%6(L9XTks9)n<$>t9ZTX{R+0|t=CW)5rduOt%R z2#~+K0*wsEa&>isSM+-yAiux4NhEXY?mF;r*pe)#`RiCf)Ddf+y~O>A%g;B|5(M2m zJu=ICl@Q3g5+lq0zPeq?yj`BYzPE%XJx{%*t>pU>iS7+f{wC8~W)Vu;G&W7dF}h+o z-}6k*RyFUs9H$DtBu3LMc6>T6spUxv!sX;n2D|S_Bg-f%;+m`Q_O+3Z^@ zSZ12t(u=NiS~5M0*y@~YLD+7#2~d=b7{lL=Md;XGwvK#*hSydgG~+UJQSByZ+Vej) zkULRt;LW+Nju-&D4D)JL42t`1{QXV->if=+FBf9@jqy!nh_bI1E^~gptd=V3% zqqu~9m%n7IM5kvA#98Fq3zuL?_NP6Ui+UcS;+rD0L_-(JgrwF=$30taEQlQMHi(}6 zkSO+U6##C~GVvJPC4hip@wsW-w;S>iFWcYf$nLu-i5uEI5-kJ_$)r8nrbIi^>I^8$TDIHQJjM1%(~0Tp^uyPV(q>8KrDTring6Z( z#l8X8b2nb)Cx9&GDam0oEPRwYS+KDW1}d-IO~)s*e64v(qo}skG{tue(5M4B z`*CroeG7BMFiEzdKf&FF5Z?g7#q=cau|@K!vq95m$&;^Wejm?q<`|V$pi4 z^P(ajySk~Xme3MjWYxWAveCmeYWdpfl+rbscUwNEkV#N=f@~c{`3~oPeGNJ{_M8Ca zIr7-DhW^rzu5w$}7ObUZ$=|Huj@@?9fzHWL|4v{mja_$FXRtz-1KE*+RIb7D5-m0N z$U!y{>Y$`%u`l=_+cOspR}T}WPpDLCsenKc<>ct_0SivKRGbGaf^R^oBH7a!ZkVKh zm4Ej=v|3fRLdsv>v@-L}cA#L^P^EJe#YSSQCZcOSzOCj}Pt5p&c`jjXd2gF{p@7B2 zyrlt0S51UbODIbYRqzJV@>4QK04XJAG8(hdeNx_3g+iHN094`*#JGi-C7Y(&fm+W`E4{an8kEPgb{YeBBlztIMWmYk)V$S;a0P=*G=pyboAPFrSIEkGA=l>(Ef0DeHPT0a9T@Q^3{b9+USdv`*lpm z%5%Z@Mbw-iPW`KNqm26d*B)Z16J6BGNQ$xRj*FYN91H9Mcclvd-`7IQj zUGB10j-e`Q&tWujPQM6M02OwIK&65Nb%x6;H1+LAlR><>NR$2Ukx#bvn<_quzVZcZ z`!eqjB1(!2Bo-Dfqni{bI56MS#czAkEF*M*Yb z)2@OF$Y8(jY5BnIY2F$A(y)l69bwMNl!Po=;X@6_bc}gCb7=HP)>WjgNcB#ltF+sK zRLf+J%+kfS76kv;2B2|NZ$9IyfkclMluQTnjE*}{W2KuWkDy$30MX8Xz$Fu-ElPvN&!&acIdU0(Ifa{wCY1^hBDj|p#ZpO z*irdXY+5XQ@t>slINty@?(0HNwM2AB?_4i`A5_3%6!ny$30#_riS!&1u5|5tI}8e< z9DSs$V7E9PHgvXhvf3~aCknTG@jiki`5!v@if}*2aAJ*I(n9%xDJp(%_M9j^+FY#@gw@MSO15;cjp!+F>xVJ!2#vFF)ddzu8clJV0)D*m|-GRdC%OmEpmd(1WCQ`_ZQ{? zpi4A3$?#ouy9jh(T{EDHNPFdM^_oS1jrD@!s~2EHTX!l}T|$~L6Qm01H@&RK#*J-* zuMb#RUBck{(zFG$2Suflc|F?75+|U=`@r$-E2s;c7JHk@BpzmbTvdj?oj;s-3?#NV z9K@SE=9DEM7fJg=b(P1FIeZEcXlrg^CeBr-5EEV7%z}Qif4%)Lun`BFhn!;_0g?3K zz;q+X6N6VId1J}^eiQuMUUOmxOl+`Xf-y*w(2+XBmOTjf|B+d2KX!7_OplEdvcoiXF zJ8J$=a3&1t=082kE!Sj)~XL;=9M*S+u>vo>9)Bo z-GLL3F{TM_EVW&ee#;Fm$B@5!e#(3A*=f$OANNB{6ubX*{XZE0FZ2bj8gG4yxyw@u z9sMXZj`T8rWPh^eO8PD_iz7u_N^(gvqipv_G`K0>RN_ZN4~wf zqu1auWq^4;>MFfG?q=7MYfz(*W>%~;;bzOLeR1tCQcUO$A&l5#rNwiLPjpXe3ra?^!L( zqHu3P30mBN%e#FN5Z+kFq}{u?l`o4BZWldquY5eG=H(ASRE{Fd75w{%9URi)lZz{@ zDen2+an_7=osCweY+5M~p`e-Te#6P4-G80@LiY9O-(WrT2T2o4f;Hd4OY|MbRi`i0 zVkye6^IfmBt6bvP(Ve^2ID;&w&uVJMn&zW>xigskd>6avYH-NCUCmL+gjhCF9)OjI z{H*RQNt_kD{>X)9G{I|hCFfP8USNF8^1YZMJ%nV4+$&bC?i|^a41l5^{Br? z!{u(;b)dAISr{*um7uu=k)(RI#PC@ie%b_hfeF>^asY^rN%U~eO}XWQ{3VTlNg(4R z=+&x3)#Hx?I}x3S%#j8t*AHUtKfcwq3C_KrijD0nSk0e(oZocT#syH}yAr-bpJs7F zs7(g6WEe_yp(jJogCtZ0ndOE|0q21f}lqy%SBb)8utw1QZ zzOpP?ww>>zyyLsDGWYN89nLzssJ-7-kMuU8C0zuar13L<7AdVCEh|v*h2>UzaZDnW zc_-b1t>sWbO3m0IsQhRLI70?&3+#RGoxL5Zy0gxTUhsv!H1Z17K)Nl+l* za64ZD)zzcEXR6?ipT&dzW5I>h(&{z7qQ~bK0HO>Bz!h)INL?zftet1)%n(6VCt(f~ z8)iXlh_T99hoIGJ93DDDrTdZVZZ!^;sTD4r(+?J>CL?ubP5*f1Qy7rhn{rm~K7q7r zk+6iRS#ZV6I;wm=G2n1&`DEkUlg)?wyiElx7Ez9frvG86enwDQPUQ%MSYl|LjGuN> zgqoeG%Y5gRyY8(~JjY)qYkeUWUGssQ4_)rWme04g@s5nXT1vntUx~&$^e4D@JKcsN^;zi&`7Hhh6hV4rjQ;$HqC< z)0W5~Qq*%9Tt>TM$0wDrj|x1w9z`J`hM$Dw#@VknI+UNGFP$ov98OZgd%+1dJdW7BX0A= ztclgqDQ@TN-R~W&0;-}En;(H4`Fl3uZTr}zqdk@0YcdiV;g2&jGI$EjI=1IHx~Ka9 z&MyG)Q*y=K@lK(cDK{m^fit6u_Om>`9PB$)r%L%|^p?ji=tl?#G$zXvFnJr_LUJo^ z;j}}f^jr%f?svX~upZ*S4 z^2(gm=CB0C@vHMM0R0q5z!al12gFBb6%%us;!mTf2p1ndV*nS=sG(=DdHnB|dElax z;AwM_Hvk5&k4-8+%c2y!+~Gp$hDY~XTzMP(p=v}aB43W_*(dzjc%QR(07jiQgwqYV z&Tid*hgx%=`{2@gE$H48ODijhfu-)0fb!k%0X{Z3%CmGFX_dFiS!B^u|K71%cJ|8! zB{;%u8^Up++1lmyDbaVIC!SzI^o#;HQy=2Sqj&mdAY9FcYw4fft|UVsx46N_>*vXu zK#Lh^-dIPnn{n<1m$?na@(zG|w_e7Ct8||i_=wa>Z_ENg* z2I_b-j;?P{^kh$|GeD>3CF*d!!Srw!T0f=_sg=Eb{i+y6u;isC!k>QY^$~!2PZhs< z0g~Y20~$P)+@Q2L)G$cEH<6@E|0Xi!S)lM}KEyXS#IoPI)e7znnH?|H9J3pr1$Ua> z?~U(Nn^hlfv`m)axE#P`z?N`S(uhr|UY;$@*?T|4lJ=G>AOPEtIbQ*ha6)#!KwAWl}w>K9E8BpEhtjLDH?%*1uU44_wAaTqsOz3U*!@o>8a5?!ExgbdemzssM~db!TtFp`C^DPjPBo1(X1Qq2wh;`q?5s(Ve2(+61)O_=+$sQ~XMv`T+@__d0KnBz z;3CLa5g@4AjT~lMc>vp=Rp%N30F*j*$bnHGjG7O;@gg=;nMxcQVkU++OkFQhTJ?6#rdxB3JDS2&%;X9NL!xm|Mf?STD1lVzGH4r8| z8qG-@at74p{^p1Dfo8zh1AVrYgMWu$&yMRJMFD8T#AaK9!%$YOicklDuf97!< zCJ8&=Uh7?NSz7>=Cq(xLboE$t%{=h0A(E0mXO)4?8W`G=BY`@LVXp^~L3dxr9pj>? zW4f{ek2@VPfdnS~{^r{nv3agBo(B}isoavCgA~vsx~m>tG%+zDG%@i>CVSK)$5-Bu zni?6|!r=$6Z=8;Q5_Aj%4h0_{D0naa_vwF=dDSGL1$uP)A0+*Er#)~Aq#bU~CBcF& z7TmnfKuwh{eLQanVf>yt?M7Mj0R*|Y{B7W$`~X9~iZ)RohCRILylw=f{TNV8}o+$%85jDZZ; zw^iClAR}~tBp1LLLvJ>Np!r^)cts{$pi{F1q0=O=9Y8iC?P@FR=Y%Xh+s+3SMS^nD zyR%@{AmKIJ#mbZHp6O3nNwbs}8{MA9LA#~%-DzrbvNaO-J~McMLNq$io!wp+MDv4# zrHo^+?G*tgbJV*Fbn?*FU_~b&RNP)GZ_RzW0Y`aNgd)Np^j@FfgLWQ`+Ag!{tSo2Q zcO+Eh?-Ie_e#bHS`@4Ob)%%_i*yI*Jly>tGKHf8Q}0t?=;R^_vs$qLGKjF1`3k z0)Z!Sa4J9aoSQo=B3yY~r>K6*o?_GaP>!ByM{LrG(f)MxsBS-7Gv&PNMdJ;oQQ`1Yf>ck+fL-=KHM}$Lf zhDK9)lF5C`n{qlcT|RC8W(z5h_=DiPc<4BHZycZjG4Nv%Th9a z|K;V*8>cLfe{dD>vvSI=@C0SYLCMX0-Qpj!EeMp`9Q<&9jBqLq9 zuK}z6lL&Z#$HK^AT%+%ln3bCq5`Tiy|Ego*0k}6&c8Xc`so-R?@sxnzFemw0)k0qW z&b~-NH$EBnlo61Jz1DIA$GmI@FNXqW5qSTB(Q194^EVk(-akj-_f^dleHYvU90$C{ z>6SG<1mKY&H-tt;KLscR3$KSMkqR1M!(?8K(1AC&sBHB_?TFP}-pZ}IVp?dy`90+k z4fv0U{?RD`#5T?-tqP-%S3rvXz62^ylK{wiZwQ66OGDRB9?ziy>7Q$)UF1LKPM;Ti zBH^fQ?aTkTm*Ec^5_9}C!r>Ja5O<5X?P#3?plmj9VymLHs^J0&N_+BvaMJ0WaBg?; zD3#qOrY-91@_Rd^(v?&WC9|QyFRKe_F*>~#yuclf0F?_%c=#In$8VUF3c#j=uU77F zfceiX)E&UkKUXAx2EwvF0;mzgSDy*4ph5gy1@)BB@X#N+F2oj9sHN!@lHxshoABo` zUGXHn>(sBAAWbslWay(4$E(v5kiNL_L`NhD^sPjlWa$wd5LarV>k1W=goYF^fU8oc zavN!J`;@4K(=NFPN(Ak8s1vO;Cbzx#b&mXg(OcK%pX~tp@98hsS||L3N-y>tHu$~2 zY%4)p;UA&)>MOxrEHvshjma_HoG1vK#U+|h5FM?8^MFm}R*>^vbflI6r7x9hz zq!t@I)x-+vvAsxtLXBj`Bd;(s5Tb|X+_6UQk?5+M_aecQ|J% z!mn0wW7yUk?8KR|E=0zW5GI9`6u+}?3c$OS#Q&82PXUCdqu-rG>s{Wb7h298HyW1< z-pl(gj}F9jY_|DMAhVGm5~x;D4F@b_TVRu_9!5DW5MTYiLcOT+=V2owqv>NTT##fd zrcxqRT~5VlUV9iMo2;4FNFhRW|2a~B_pA^CY?($*48;@;*rO~RzP;j{)|1XTbg-z3 zz?J@O&+`^s8%;Z$KXmF{cYs z{!&tW6s|vizs2u&42gmFYY;1nk*4new?>H7Q@#S{2~>PFBG`D69B*x62%kZw2q1{$HjaZ%CU;gF5 zQp(A^@bJAqVn1$iLNlUQ*^jiif$Q=+CnO|1%aZ^Z^gH4K=7Bil3#A^WMDmUhH3h(@e(gkw zueD&6!tT)Lr_4GHL9|Zbc>Mv*kDzYU8&x~14?S4I6+T7|QM|qsc-gLICZjBM7aXs1 zkX@I&-W0Md4i(9;E3LnQkf2)9R>xq(rW(eWxSw6In}tWd-;exG-r&W9e@A zwdG6ANq;TDB^~pxC7QpR)YV)3H#8w+NK`*C3}J{|4u-tCOQ@l#lxjeL8d~jlyR`&t z%IrL=w4-QZC_|d<_=%#U=kW(bugyM*ywN0Z$ERaTYA&mOYaze?gqcM&Z1-})_@@jN zV~B#R?8N7yPa>f-FR_Ll;v9f!VvR9dpzWp-!>tdef)$z_R%+f0R0vE_sf&eQ23lM{ z=pdE27iP9WPnVY+V3z-LWA9fK#IoTmAUX+Pd?uLsD!P&GNN-52YKCJH5qG=u#gHt9 z7|P>Jav3Xs(4PEO2`|N#<^J2(Xca6V*s`8%1yFQ1)je@K0Yp~ztH9`3^zj4;-St|} zBr8=+LP7p>DRXrl75S%b5gUd|kcGAUcBxxW=t}je(*ffTfcC^p%vnu5%(i}#NZk=4 zr}!y7H5{_?e*nfRQ%;@QcjgPgd8Y|D>b8RW#VL!p@To7Y*Tzd@zu-hI1w~igf?m&! zXRKrrJ&j^i&T<(wWT3+;CFVxfxZ?Vht!E)Xx3n{#*}Syny9(gPGunuIgAfHkrhWj% zExy@QyX9;jv*PKxUmkt1IMMLS zeJCAcm7dv?OtZ4B=t-`e?*%gz&FT=l%Fe@TwUP;CpCxky7`_|KLJKj%&YxER`s{te z`XP~xc>@_~P1q~-g@kMdjmfE-?DT)|^Cw?A{KvDB8%GR|T)%!`I=nLS{xw0tD+Y*T z>EE1opFi)pl8zAUN&KRnAaql`X``ue7HM@Oz7h@(tSey;8>plmFU zc}(W51Z{hvv#ZL!d*vx-S8w5W7E%z$+(eLLK1t45X*Hb;Zh11$lw*esdAnhEXio(A zl5cVPS|TE!#3TJiIui^hv>UT(f1W71fY{qp8N1gJv@K}~s@D2Kef#RD?A|+kz2@rs zfb7+NJWb^?Ze3piq@p@7yYm>+x{`04SO$T1?#az>M1=;D!Zcg*R=p_3GFDl=I+O|hF8gP>kmM2RK1Oageb(jZv=bcWPSOvBY+~*u z^@`VY$uGvSFcF*BgNnJ>@|0HqPvtleJi&W-5%7wa_-J$LOgHSG00;M21J8%3JGajI zhkNGrX|qST++XWF7X2e#!p$sI;#IeSI*&<=2mNW+7>Qcb@aRe)%0$$o1q3Am`a8!U z!ob>HP}4SSAbMsGzrN(Wdl)Nno*8R7c*XsIWEeBPr#fxMW_ z;vf4XB&jJ~vM~F{N?B3hgTT!x1YL&8?z9T;hau)RF%^v~n(r>ogDLiLo6^TOacLMd z`GX^CN$Z-W_bAvBXv*#2*01kIhJN+!rX(!-){{~_H-AK+B%etcg+J`j*QsLn6w7vB zm`rEj!u)#WXxv#=NxL zZH;wtOBr1C#_*|81mv1DF?mO#GcPXCPpzC~SYI zO@2h}EH*}XSP$Jc#l*6B#oiNlpchhukPk}Q1miVGcVd2M+c=qoZ@VNY^qDuf2$~~| zSKNjW2*&z&*e|N=V5t}yb5c;5$ccSHpIavz2{6&iL zvr|z@&6Kli`50#Niwk95JAJ@~GNrv{o1q%sn~M{};DR)lV3!7Y@$km0~1^=Ge{d+}ULceO(GgbQywhnb8pcOhwuz#b{6z}Ok z_7B4X#l75TRlGHeqH3|2LvKmtuBj5L>vt!J3B1*xE(^z4SZ=P zt0o@b#_Ulsivtn}>+5ZQrh2#QnLR2I#PSPfkDPmYMR&=rf1i`RIZJb0EJ z-SVw=1YPmMG4!O`WIOjSq!v=}En-+1A&Qi`Lb7S@yjCc6Y;#c9qaVlcHjnh7VgQp{ zGb7hGW#)0mRprz|(({>yjj|$EY6e;&(SKt6K^B0$6^IvPL)X`yMm7 zQ(t`E+a#NX8iO`NsAl>Zk*k1r9TgQYb5>1l9Z#tlF>;w>=K1iLy2M2}GoL5A9dPqi zO}()RA4PSg0BDfp^AO)+oRzcnRxc_KeUn@sKtLuo9GX`h-tmui3|Kg;bZjwhLT(w2 zBG(gU??b3bMU+7YGtF{^6vXAd8#u1UEVTu!-1Va*mAVn)YK)JjSo3a1|*%9GhUtDW*qBn0X(Id3@1k; zSr47=tUV<=W|k-Ls`oQImvX$JmZytuxg~Fw2aa2 z&9aJtZ7)9Qz3}tFV1S(+s8J6R^`V~C%lr6X3Bw7xis!FkbE5>}5If0jzEqup69SP+?tMzLJCJdW^_a zRgC2r5?1=7cQ|?KI$`OSW-~;89xLOrIISM&aEV+SqG0ACV~j7@reuIOXB^EvWDvq*-dF+Ep=fRw$O};I<`yzQ`wVXgdir|5Y6E zMbE46PFbz~kO9TSPYoN7rqs@wPz+WwcXod8?f$T^zTLfRFgx;<)}W8Gm;osC4lg-J zoi&J1y~ZGt>>MMrn%q(}?}@?{KEg#8E|lOLzf>;fFQzYU^Lquo(gMQPUboVU5Bt}& zRK!JiCscQq_PVm@WgqHv*X8Y#TQ%deG|92D$ARpZ`!A55Vp&|J9&ar}i!94K`1U=@ z9t}dNU8QqmXjNDCL=|48(>VTzp;*X&QjUo;#rDX~YnCWxRXU-AKpMlx8R;gX+P-Uq2{mAU1Ip|JE?@?RHMT&yniX0gj!OglVMnS6m=IRbe-<% ze))wQl*@Ix3+7RZB}sdKc-eH4W08L>*y<`%XQCT9>GS2<`~thJ_sG^LM3-#3RqC9V zGV3qEK>yN5FEb{jr541Ow_R(0FgqaPqEYA$nwr|IchiAWECo?_0S5N^hFZ8z$8`}D z6SE+a3{)!V|IuDI9+=dZ&*Rebi|VVn{KT4V>~kVJL~B0O0;}8#O6&%(#x*qFpVaI4 z!K-oRSdo&zA?HcR|`s{UaQuKCar{^Ck{^)rvI18iq`l5#HYuXAep zuJOeg`uy)#Vc|-*U;&u^Mu|+&8dKO#`GntM%)K+cvX(Nk8IS5{4m(rK1y42hgp^sw zV6`Zs{=2*4X=rrhj&rgF;C%<=^d$bgQDg8v)hs{fd=*!|c6aJ?=h$8&fx0Jzq~cxR zq{-z~H+cwCmQ@)2E_V(iJYWb%@W^<6XXsyOt~j(KG#Xef%jecc34{`RCeGg7o> z_28ugA>f27;bC~GLT%Ga_&hJmM9<)Nvh@PT-ZZomh1N1T^H%{p5^`c>za1Ez`TR(K zu>P4SW}7Cg`g(G!U{VCI#M}J&QGrXgc;BE|U&h5rYL{>O-N~)NrY#F*WY{(saG=D+ z;=H5lAh*PG26gD_ShG5d&ujB1!_B;=Nykd;bDm3@;^H};$N>(RDdN0Mj7AgcZacDJ z^Q#!I{Bq|9i0&W=~0!9uz{Je;SLV7D)taCWlVZigls?bOi1KmI4&t1;ir>SI84vfG>_r<#+aJJPc@fZO zCblnc&}*sjQ%FFsZpwTl(G|KcWa7Xs6|;w&TfMU?^zQ2K{s9$-9x%1rcaBW!Mb$sf z8MUTV51A-QhD(>5_8QH^10**!TMAUp?xO(pLDsBlMjnblO71{lsGTt~^+_HQyWb~i zmQglOXRGF>oK>JP-e zx3bp7KzqO>Fq`%(5$r5&cX>bWV3S*qUcY~-W4el2I zG}!moWW{^H)NS9)P|)&Fdl>I}Bc2ZgO7W2%0n;DWooDo-g4gGApx($bU1TyuyzGJ0 zs=GrZ{G8muP8u)HKO$B@+ZADf^TNbDvpScuwq_=#PbYQd=QD_KpDZJX3^1sO0xG2` z++qkwcEqNw4CX7h0c*w-k?q*xYDG$F^79w)_(+=uLr^ziax-%B^c`#6i}O`6;S>i= zeSzsuyA^vIlkLC(@eB1?gYEb!(H&>_c?=_qlGCCSg?5)GcMGcdPUah2I0ltRawy6#6*p_rYg3gv0^_}Oj$Enx zm?TUgsqt-f6S7?7)LJElj%xEF@5-tvpXaC6tp<9Ot-cy7KC`lyt%w)S99cZu{9I{P z4woB#P>VJRydZdxoG$RgDo%6aatM4}zSzK}#p#iO`q!e1p2CXI*@Wr9?!vQ+6y{5V zv`-c*X~6E=h981xLlN$%othaK(Vm!VMTqTfXg10~7|;-RC)HZ+2oxJ1c&$imbvZb) z!>zD~jy`zAyoQ13pUP{EOcRGn|DL{V9vv{9IX5STr032~@oeuFzlnUQtTJsVID$<+ zE4OL740q*m9z7FaBMBm3;21=C!_lAJr#P2q4{G80sUX z8p`LzIu=jj8A2@H#`z8E7ok|<$>X!i6{7FAEL|B{7!@3Dn=eoxdiOnY!|qUwUy)Ie z^|4LOtC!U9QV|^;tF~N6l5yEv{+7@N4YUS5&>D{a)f$FglJA9lt;RqJeM;-V-&1jT z$-zBJp0?ev=ii3QiE|9{TMF82=Ho3Jlcv|Y$?p}K;rqzyPFn++M6YJWNCnn8^P8*< z)pok$&q4c4Y6M#ttm}3vf%q5??86yck!jTTgD%#^A%9`%ITM>3Ojp5rR={-@an%U% zbX|y?NZd|`(Bg{CS88d?9(=}kc3Zahb})Mga}UvTvcG1b-C4Ze?u;H|GD6i)klZP* zlHLoPUsh~jYj0l5SBuyOjz3Aj5RzusS|Ft(x5u!rHyv+;+3LSOl2M_d?HTB**52(< zgV9y z;m}?yiH+Nq3WYv*Ca4aCXW@2KelN*{$bW>3K{%YaguV?Ct@4=OX0a}J{drlnVoP~O7l9xpP*aA+n zFw1}n+LHFbRQHZmptf>f^7*2e-~%!seRu{`baewjsS11zVgKO8hu3CuZid|{Ae-fKn$A#*3IF^k!^OA@cH z`JKZ`FWp{=l4QW&NkY!nEbq*YVpcyHDMW4f1qKjz8$bmxRWrt0p_l75gXh5zYwgYc znmOp)WUW%_y&qPz1v390$c4in@V<8Iy<<&m4)Q%q?{S082HyM4@^v2 zSufymlpRmnva4HBMP!z@N*Rf#qW&#KzbpSiuT>FF$tz)Ik_%>Z)OQtxAYTN-PuLbS zO42B*-+uM@>j^VsQtXU!n^H0w(mWJ=>FZ;l9-D#bXDH*B zNYm?aGfs~CIz~Za93M12-d?U4FL47~&RvrRru?;NyL#+V>({pdU8xV$vX{il7A1Gp zx<6>}^cOX3&MVd^o;B^|`A#dV##GCge(pVSWZ&&-@9EC}-aQ{4 z&@UD|I5p!3o+H!=JN5iSLVzYy^o5u(LO!fd?EPn zGZJ#*EdRce`+1{Jb^mxHpaIXP@nFz#d-z1q3X7|ZYb#e-Ph*bx0k)Ix{#GHITTcc$OekOP54e9JZSG0KJ;M@In%eh)+y&r?c8`WDH zON9RaF4?66opdFa^06AnVjnS_uE;W>`$$)D-GuHC9b{8yj~q0To#)$`V!|_9Z+_;_ zc2p)M+5?UCg39&?t{on)J%Ir&0YHm##ie`f7r}GZe34sy7^{s*Xs_uP`LmA9cVpNJ z3p<43K&XAp9^APX^^omG?Q~3M^nHLGiTI95=cH{lA<4D9VQ;$u1+#bOJ1FC}UV7fj z0DRcW0o>Lei(b#DZoRGISd#@@qIChFgNvTBc&J(hqI?~2iw;_>2+FUWyCKGvI0U?3 zw_)6}U;!L$3&bfVl}dQ&0sdoDpc@hx)~uu_14z-6rO~m!_Md_-oe1$Z#b#uBN(7=? zW|b*b#L!c$AMq9q82#!#o(jS0WA4f z7S>9@=ok;2166QYIZJW04P^!Box20q`jr z;LK#tfBzla5L-vye(=A>=UCEezcVAGA}kj0gE^mCFF9+tWAz?+pr zpwkeGfLH_uw7u7Cn^|Q(gcoW~oo$NfpqXI? zr=+GRhR2?wRSB@BVxlj^26yen5BbbE0D^4G8oRpbO#l8u{y20nSaNC-Fbr|O*=Hrb zg*d80{d%TYJlJ!Z2^jk<-y4MXCo5hUh5r42)Tv8kmC32LbGcpG~wA8LPA;;sHz7RVi) zoCI#E4s~T>bc_wwZ9W#WGt*tjGBBV>fyv9nXG*FV`9NTB6tf0P#uiO5a4SHOP3Vrh zX&hASeqVo1*YTI`AOFyvD_|6`bE>N=!6|REJZS%OMuT%#q*+VKsK)GumvvprJ2k?5 zj#2o>_Ahf_Bopyq)ER9N6px+Y^}YjIaK}ZfUoZT;XB-LJPssV!N}pEY^4eW}BK9c5 zDX4gue)00gp-b^Zb}$co%d>}PfcNB6_Jjz%PHYinz@Qt)QYxjS-uMi6>W!>4G617hfbh8-_5chp52SuK1!(B7PPVPUXdJ=S(8I;LdcZBj|tN3X25!V=Zz_q3o*}sm`F!GmJ_pw?IkpBL- z4}OmgN>Rh^R&R={-Q3ibi^~Du&bXXH8N}0_7QF$Cy>;R$`nUXoCHsKKe9(fYW?Z>E zb!b>DY8ct4BNI6+zo!F}GCK`3+_6^}PRpo)+eiKjPrSGPg#x$^_1`;NQ5N-JR*I-) zEB!j@Od!}3!%K=}@&QQ3GE>>7SD==6v-~`&=QZ7Fu>xSctEkV%qmj}{^MKEFDST~N z58^Em8xtW+M5Q>_KZ`c)q<~ zd=b)n-#m7{b#EmV&RFoSzhiO_1CgQf+Fy|#DN;2I_jdcBEj_#~-}dlSHkzeww-+pw z!g_u=svZ}iI3qAHd*GCX{wh%;wgTe=rW4@mZVxsCIJuW=qv&GjPMaL--k*UO z{l)3{B!}U!6)^_&N~QRtFL2gf0!|K@a6to)C9CPLk@gNN7bK5c1dvwHj5pEW+Vyb^Y1=a+jTkNI-igFWs1e4tiB@&T@eRAvF zYRNT>9dZpUlkvP40Kr|6hi~fo_St`egpS##(JNZBWLP44^sn9)YtC>KQa&(vTPk+z zlK$;dX1n^x{6g?h1W?cHfm(hM&ZLZhwPPJ{x@H?CKN>5L55q4{kcu#yg-@`VY9zx0 zL5->c;&*k$pGQj>eFWQDuKWYKT~SvF&tv~P(j4LMjsW*FUwiw1x+^c}v+p>-gRRg0 ztKoK|8ej0x=Zo3kQTJl#I4i!}gUwhKllFA4=%GeG+Ns9um|M@ik{S4+m>FN2;ip+tfeED4ABw)JqHB|v@zm-_~P3{NAG}u6B5B^dV4wk{+ z&&`=)9}n0j*A6n^mXbxw3+`aos3(Z^uoSuhj>GcuK8dy~ zVJw#(3yPa5b(S@h9*ez#dSpU(O!NFD;P}l+Np`Q!O@Vf)c%ZmAy9L_(0zB=bHXMA5 zd(LN~OzU_-oUO40+o=uV4&BF03+Lsh*nJvu=#7GI}-*<=T$gRJtlOgl+8uJB|u0;Tk&P1 z{amU5Dl^ST0bgm68?b@k@3H$2e`vO}7kw40EARZ3K^07N7*&s`%_UF=&SU<14Snz$ z7wZSM0Gj9PbnN*M2i_$MKx4fN;Mr`={Ayu>#VbF`1;W|fPmA1~=n=r&3mH}3&rprkHX!8nlj09@C6KdDc?8K`FP zech#jlNfcu8jvd;uuWBVDMm|F7!;bjBOq?UI5s%=lu2n$HB;&M;HY0g;mg=7`%g+G zU>aZW(l3Io7MI|Muj&^l&1>j!aqgU!cX9wio6m2o%~YpW0)bwF2T>kZK9^LKDmb0c zZJQgEeQjT6v7cc4)9G==SyL|x9;D#I#}|MHLQFn^LxcS}P^V*D3#+o=WZ%FM!^B%k zUQzJ(gim7+bb_~Ewu6wvok8$?F9Yi$;7cBRpk^<4I@Sxf0ou{0@cP+oztJXK@0vDHEdJqu^%F zClwAkDl`DJBy?UaB6B>&+HcAY7}*DQM1&DTbpR6gkG!I3Tm3E`0&Oeccl89tE>1^! zB%^wQ z@v7WF6(TQ$s+_uG)>oKq@upg2V09aIQ7K_OCt%chYsJA zd=cf+3Y%CvhUz!U@_y9p2GJ6~tw|1AgPoA)y`E>#DXFB>)61;@9>M{l4TwC9_Jn0m zv&hge9t3k$7mz#OA6EP=BZRU#|EU0W%xVgHcx0uhbtwsZ`745-<&#S>Bf2GErjJ$T z_T`W|>OsUb$f>p1O)C+oB$RyqYxG>O`_TLKh>S>P2obFF6**=3xTmpJSrnO>CfAh6 za1{+^sssp(>OON8ecfoA=77E&SIx7t!r3V$cTDA?d^FRc&M}I`Yppe5;gC3nP(!`x zt}7w0SsD_yb5mV#e*U4humopVY{+}rUTd{H+a(xdJC&|Uhc3?=feZc!LKs^h`p1MVHWy9)3= z5_rx!&AH>mmyEp81x)Hh7}^Zn?OUcTlO^*oAkmx;9Z*SX!ACAiUKP}j!BsbXL~46c z!3x#eC-gO@XRaCfIR(sXS>L(5+0!Kx84lD+N6mKLc(8xS+IT2&N{ef%B~#K4`oV1d zwzTsR^3@oMUqAFnYzBjmAtgPOZ+UeObmj~2fz?u0&t!NBq9t#m;mKI&-N}gc@uN!sBZb)I=@N`rY^w$Shs8h6ig`Is zpa{ri*?AD1tXktIBQ7@ez@k74Kem34pN^YvS&;DpZ$|6XIXX9ib4ai#ZaH?y))M zK{(kqM&-N-iD10jlQ&_}E#Kx^-R14EW_NpZ9L%fbv)05-@U-p zURb4^LQN^{JBT;Y?^a8J*>!=Ec{_Wa7H?%pCJ8G6x2>hutuj$`rsd2?ZQ%y-8aiaT z_QU`ChV8sueBVF#oNTu?wqhfB>{NA11#ZmVUN^j!I?g5nWvIeYuOh*3?g?Y=n;t9q zDA=qH6KAZUd?V65#0QHQ2}#`hY2x)g`~&Vg>_nbBp-cULikj)n68U|S()&hp6}bdV&~ z??A+kd;v_-7)Nniw}JQC+3ov8z>QTU<L*!#ehOpCCDq=TWC@zto_`+WnM8i; z|FD1j9F{m}SH;uV`sQwF=Ej;?l}gQF#d6#|3rn3Ev|)L5bpvBk2-Z#GjWn*xNAsZw z?yG|fWnqo#K@%e9hq>GtHI2?mXNRN~DxJ~R#H9Sf(b=+YKh4Aik;C?7 z_n@Cis#V)jPo^5?d3so0e~Nmb+)ONRR@AC#C52q{vvE$tH8OdYT>oE60&c^6At%Q6 zXDC6vku7R zZv^?`KEK<8Q3+UZ_^ z8Wld(@VK2Gl`EBa5J9;6eYs?TT(0Fc5uBy=TJND#jF)yWe^ZJNbRw4?V!{oAU%6*msT|6Pmr{6*Ed%vYI>dc zbmPnsY@pUXWGPlUnI!p*oaMxBmT>R0ppIPm$eQvzg&+gg0 z8)s4;aFz?lrp#u)^!HuTDDzR?f_kC~1^tWs58JPVvrG>zrS+Z($rxE(u6mW+hIx(TQ}f6o^j*8#6j zPk%#|fB$MW93dxo_Emuai0NkHV+D_k;Jf3_5^{zZ@;f~E#=7#A-Q@ywxz-bx?~KM` zD*QD%H|pFlxR2As#MOG|0W&X-^%S-60eR4Y^25ngw2@hh(3AKIDkAN%p`Toa`mNGa zx4bs<$JxDDnFa@{%1O(4Xv5dl)q9jxP+rA=zXugT5CC6T=yfwIq&+#-=2m!N#~Bp} zJA1PRJ&J2_2wKK(eDt;=I|c@9SNd(|;5I%k*N#p)TWR@Yy#L!U|2~!>D-5PfXZW#l z(x1mtF8SRVU$$a(K8=?A&CEF~yEZ>s{!u7lu$eIr;C149cP_8Y!sU(rALmr$q8Z#h z-AJQ|xNZR0psJ5eQE|yXzK^ngGODXQnpo!lSaLrvr%TQVvycb10@}N2H`0+Mx*#l6 zSjd}GKi&cCA*JmwU;3Nr@8m|@)fArrV@5u`AhywQn>rMv+?8NmUJ+G5%2QcfEsx5t zh}v=km)N!6*X_UB*x&p-bY#xj=Ih2jjk8N2a(3kij(aijoS%*#iyb=LZxdr@E~8w* zjhyX!I0>_qQ(w#)uWgSagty?)aJJhzF>D%atNHQ%U>QzM?NJ@@^I1)MX@o5%I-=zy zi*AMcwA-yEPX9r=aL&Bf?HTshDXS+xxKMH!F~XVNVoO|pxA_^yd`=b(^s-G`KzriG zM=+?QV5+$+wZQo9JOcLB$Gjs0-|O+#dF^O0T!&Mg`l_9fvMT?<3}@E9G(B&qU|Qvo4@4JT+ihM5X9Xt1JF-zLOD-?Bjf$lh}Jf z(M)sNs^-@gaPDkcSl@M}v^)kR;hE}sm}-2*Js}d5c+vKwVW@Of%R<~#%Qe6Balp`c zn-0uQ^HM4ocDY7}%{7Y89n+yCjw&f|Y&x++@m1H7pgQ9%#Rda=xWk86bDdY(E@wD^ zxV;7RAlb+I;X3&dO@B3bwNp0#9|fT2HzFqjT8W~6AfuuYJo-TVQBerXq$lv=vf`t| zxBN~QNG^dbwYqBC4O;_6g@ac|75SSVrh+*oEWBX}>d+Uz>-O;msrW=i3ge!G=6;}F zeIHJ-?VZ~NG_dneKR1Fx0p7qHUbR#x&8J#Z3rmr|eL_=0bulpu;ZqyGN(&qf=N+P= zM_wlrHfnnsfHKWeqAiw65ceACVT)m5v&wktJY)o(xb@vS@zADySJKuja5C|6eTE7w z@qi$pb!W*ADy`of=(~mi*iY^;9Z$g*@Qgzbp5e#FuiXAEef_@2T%R_+U<(F>4I9ja zaOSnvdZ#ef_^`hss2(y*fo4t(+y3=d-GYC?%Rw`g=3uAV)%nEQ}k2U#u2{e7NFrpz= zC`Hsd=Swm;IqGF#qN0`66?#U-W{g9#^G}WUX6kFfiU$Xp3(rzM`!ib}?XGg4H8(C? zuPE^YuHhwaJ#TBcMcEV{^cG6xYAsIT+hYH3Hz*!I02fd1uS$4fJz-8)g_AQ@p;A%4OdGeYWEbzL_7w%zKb;S{XRYtPU9CNbT`kh-fQNH3!K+W%2WZrkn^pu^7RSo;tUMJbPO(W7 zA~#w9(X3X-Z`d&Z<0Fs{P%zhgI6Pwo;c?whTheHyW;{$|`NyaPr4x)n&^#<|8ESeuBv}cT~zopKdqww=B zMxIPZM$mf$id}cW^&;VsX18n|rzjvj7pg`(Yj{%rGt<5$c=~;r@y%xo5Zo64+ytg| zEYlYN=?vCS{%de!IQT)d_~(9p?gyU?kWI{1`t_jrvT-H2WYtJ5r(B&6V!!m1X0G!( zGj2F2xF?MnIS9(}k^TFE#_DgolYGyPjWr8MMJ?Y)-T}ka-LXX%!#&A%AtxjtQrYTb zg6+du-Pn0#Wv5WgoJ6r#4>9-ulY3~Y^Z8v@AoMZ`{ml=}?Y)-XC8qjjXXVrWRdUd8 zW%3`j8T=t6UUaIgCsBbv@&T-Ek#Ft>cs$ddgEjxEGhk1SeX92$CzUMeAhZXw?q?}c zqi=s$TWx+ml~8-*vJ(Fr4g9fUKOpbkmHN~oymIK|SGm})D)SnUo`@J&7(0unT|Lxi z*-p(`apc}|Hg-NVF|$<;7BQ!NhZ&~8eYD<4x(_`CXi(WjFqGF2>iPm+NkJ=i8$?)r)H)w90VV!qKx_oOu(V?FhfGbK==NiI* zM_iz^wb9jjQEv={)vWC2vik$QR>HQ1Q~dozG5~1rc9bpO8eO#IkOTwgylV81a6taJ zIt|&@k4+3(c@V6{vaLLKvGEeIpYmS(Uk zZ#Ly-CUtNiN0Bg^U^A!%B4RGeZ&`X0c>kaF&N3{jw(a*Yj=~5^DkwT=2hR^q>1(7z&Au#WQE)fKy*s&(CB*_qgYvb4p`JBPth*`3d0{X-+&^6cy{ zb987ijkVh@Xf)mXC6UUl@k=jpuakmcO6Vz$^tR0{AINMoymm8M!h-P1vWA=Z7zkmK zlrwJG2X%SL=qy=#YK%N7@#(eUOQKMm{Mcl*_zijUS8#RT#kFYQkmEd)d^2|ixR?nW zyP{A|@B1vm4G9^{hnpv$s}gBh0oL6*ny$9*KU)82Jm1l~zK5j{>gbf->bd%_g3mQ# z)#jF2+*-@huEN2w&ugE7+r?Mr=pqQ-WM1l={@ZSHSjn_zwXZ|X<1^LaMP>$qb=&~gw>miz5(A( zPQEG++}t}kbMe}h(#}Q7LeP|d)m*Y=+xa0YdAt9%ZfEv$JsUtv@BIFuIsLDkPjk+X zXsQVjpkk+jRW6eSOebrwoujX6ufn z;@rM69cwwA$rEAHc~|%T-4jzTV5V5yTwb;Jqs8#nLt$MZ@WbB`dM$2P@x^D>T%G-p zm}(L2K*@CXf9usgB1Pw0-UM+NXiEHfe(Ae*(Ey0*CSF|5&DOQrm!3}Z{}57Zg{cX< z#`xWn6Y${dfR43NV5HaTwC4__QXfV$QW2v#Kh!GV(E*D0M_q@C0xOj3vvd0C5U*DOv~g%r8_KgZ za{u%7|8xERXZ`%o^Yj1a{$U93Uw~eC${-a{q%i`HRHqFfdHl@Y1BZFDaQVPSs=i?i zCR*NJQNh>qaA+T#WpRFsXn9{_L@Xg=?hksF3JDljmV#<&#RouiEPpKvc~>VnOUAEc zfQrRCgp)X>BY-)xsQPt>dkl>2-UR+1$Pj+>@t&S(z$^;qrZ7Br0<0(RQxVi9%Njl_3H3m3mBP^3fN3nw{q|>|{b)a( z>l0IhpKI;#2kq+AIy>)6quLR+9-;CM>)Vh~O{%$gIg;WcV`RsJ0QC2YF@~ znZr7O8$^%3Em$bg4U#s!+@dMW5}rqvJ$D8qvUxUJV5F{dS*D6{6FpmNuhW4{eWvBa zrQc{M+^I<({8H6I(B)6XzjCfFr!i~EQ6ByK8OVO*O)t*Cp@bKiAv)+Nv5e%Z0C9ASS>qbXRv`Wu02 zg8?#PeXl>tbRpL7?SVRo@gOK2b#Fo>d)Z$lt6H2%8<*335Xbrd_NHc)7rr}a;n9%0 zfe|x&lwTdSIc81c&15a-_;8=0kt3Yhe`)4|!KAF{kD%)D>GgGcsRj!RFrhx_5@+ug#WsxHHhGAk#X0xrTiu1Wp*qfH@iPaD%0lki8z3645WC8S zH4FSh2BcNJC^WJJkkhtj!TR>tSkIF6dPp7(v<#@-uL2Tpem``6>&a8bd|8`BHfYTTo+Fp z-&*@YL&-E$QCFT^&5u8q%Qkc(nx+==QomR{=BW{ddyIq3bx_XK%h zVXym(BBpMLXO{HhIkyZlXA9UaW&?ygO}z>nITG53ccxMw02zpKhTvaT1^Gq0tz-Q| zuugT;wfnBF;1qGlPC}@Q6UBO|QEcdE{k7rsMe1C^T(!T%D=iWF8c;6_=}Gx9y(L&q z_C9E%EO3_GP_7XmUgxmFah|bozxd2hLH)I509`9DzQ4$ac1gO`d2rIbt>IajWtp8@ z$0^K{U3`2CSBW-mKbkDiDBslU;8o_`uj+LU`i~XugYc)ms-i*l`>TL{oX^udq$;$y z|8pS%W$8V}Hq74?Lp{yFjxOB>292~eB^NI*KQn1l4aUHcvy|F?j_`t>dwFFoNsgUz zk9w3*7@bB0g^CSnf`#~06AX(SfJNP~UY#O4;~=Q!6?c_B*`rv5C3X zqnCaIhzi)E8P{`mh7b3LHE;X5JfebSy=EJ^sq+DC|ion`d%guEo({sdEk6?TKA^l>MV{ zx}KpCO~FlB++*;hTQ_yp15Avx$j+6pZ+$ojGV+|_nTs?+`?c3CGr>1C`7T=X zh5m$7gt(}MG8A8s0uKBm$EEiU4GoSNS=|%R^hx^qLl^l0Kbvg&z;Wd2$(V-?up(>~ zAn|(zg#KL6Ywz6AR+TdXuX)eZFtuuLx9gOmnN{<<{6E@|feK;)Evy&rbBe5Z-e=#G zgnTwv=e#mRgU~>lr)zPdPPt!+P-?<8H;QVc=BQA-QlJQhDDDnjA=f`E7{!jd8QgH^ z$*)Fs&wAU$dyPl$%y&8myvds$lv~~a@)SW5`Vjz1Slxr0K$rY7k;bS!2o(J;*WQad zLOWapY*g_(=xchZYp38`d>V=Q{ebZV`xEA{$Y-_BSOg93gk7IpX%ffUMYJ~K>_Mu# z!CL^;h}!sjy+pEh^3TgI>5c58B(syZLbxOs1eTa6&D;0k>728`^u5@%7XImA?7=Kr zTk)+m(EX>Z#<&j2$Qy3PIz`e<#lC5PrPAs%cxSL*pI%a>|8}Fe5mvMoQ}$%E8t$S! zF(S{oH+tvH@ta3mcGjkF*shlXb z-*EEdnti8Bv2|)OpjfBbwVFH_wHInJn>t`VmN92EhR$B4DKW<{DjG?l+oqdh)%MSt z@aNfd6b__I-rKx9EVlN!P4awXSi$lrN>GiD0dW9K0pVnK8}=VCmPL? zrM_QlA&$&v)KL_svg;6`A4P#=4veGffYO;BakBJQS%)B2x}<5dR7Fepw{=!Zv+Kc` z;!x*%>n{<uOF>7V;ht~*#NK~tVCY`tz4jlwe7~6CDbb+ zU+Jgvz4-0wN$uWELwS3Xmmrhdk$2b-Atz!1AT^gzJSF=;|C){5=Gp%4C=E@h|2o!4 zUC2Zc3fRfsJ#*YYUQY)fBj8t=r0B zPa~UuolW?&25fCfg|`U2kYGKhaVKk9bDHosW_B3{hFt%eO9DPC|JO&K#~ z&DibSD`1p&?w36XU6yPHr@Xk!rS^0c8KAEl`$K1~olF9$GXL}GAemRb9(!h$y z&(1^!G9c1DxB`DU(CwwMjEz(~CV*OBC#6Jq=rrzHJ1P331qp+W*x#->SIE=7KkmFOFPy7=7eaf zv5pa+_B6Nh?Kg&hSj&u6D}TnVY1tHCkIMTkYac|uUhBE|d2iw&74ho%5ze`%ZIe%Y z*3^Xr-CLhRub3IVe|lW(X-S>8ukIC?`#JUkslx1DJW@{#UeGEH`t|Zc`$V=)di#tF zl`T)FZO6{vm)^fZSvetJNm=CST4BE~WSgo_*KnC!1V1B>088!UjZ3H_ej3OTRJ(HG zm-Y9Ke$Q?Ex%96fbIfx*qBtdkp%z!d@e6u=cc@JY?bk1GC7knhoW1bln@&3#l^t(O zcbodv+Eu4YHDB&Lw|>Hc$h+gd_I}^yIoGnIXOPb%hm6kqc6O0@g;<91H>45S3=x*W z>8h3y>|E2>^MOi7H+pEMeEACJhVYW@OhPlEa_GjVU>3o%)7&*!4D;p`23o@7`0`)- zPo|vu#o}(ee8-DdBjhA=Xp^=RO4OUUZ}9pA6Zt= z$vS;U_Mv`>rcRWfLWCd(&zC00zs!2|ThqH-B9QJa)h$i$`f}tg9{RJL+h{%35GF!S z__&IIqMQUGTwA4eZYmlwu|&(Rt|D9BjxRJsh#~nU8~E8TQySe8U|K8px@i(uuY~4v z#Q6j7OCHh?%QfzLWPBk&-}{$r$CMN{y-%k4Ob;K6-@3M{`^1PuEy*rm?ZI#!oTo+S zn-JO2?W8{mvrTl9PTqJGswM^*o*jm{$v0W{4kzLopp{$b{c^Ln?&)@aL3k z%OA&*-h?9w}x4efb>HIm2KYe~4th(50PP&s7I=7)z;&hUa*yAY<7AARyIA626Y zV>n(iM0@xiWMowkz8=wH>-VNn^_D~R+oxCXuC!2>h-%YR%=kl&3$IFIgY=qPdgjs^ zu^9R92jixBUo)$&U<_8hUXyJW&z&Y3=!HK!(@Sx;&()9OFI(u! zlgi!y%ah8WC>pq*HC}FImK2^x+7c(Jez}p7>w|#)aig6KP1?68{;V^x^75-KrN z_-}o2N@Wu2!VS7y?>E(iZWpwbYtM@<&NFeWtEPF4ax8?P8GPM_ycmcIj!SfYKPBBb z$-@iL?o?$xYtPK6^QA+}vCb2wnF+G5TC|D1CzI(rkudibk(ZZuE0wo$#nk zf)$>a*w?c~oN-OEefM4_>*C)E9RF4CxFE-2a|D@<+MOIZLwU*XJ@e$&CFCXibtR~? z1*-VOLYbc_cR#1|s?e4k7d7c}lYF6Hy^{1k2WesB_Z=&N4(YIKn<+EMTol(T+JWQP zWxq`672~B0M$$*$yal(>4jb6Ih1cE-@@->yj!Z3~|Zz_tw_? zsuNgJcTx}{f-++P;|$JWGyb09yvtB|N_=HFe%Q&2mZyhVpdBUYx4%(;jP$+fVn5$h zp>YQnS?!$kAZP8P{_~Xk(_V7)sZV^7)Qt@;DNI~tK{%O)%%wV`IlPnx2j2UDqxZLS z??Yp&@+BkLzEP%L{r$5oq(|lLde;{fBb7|gxnFd!jYOh6`UUC)R~kJ$rcu!CCEnP% zC%Xg^^IBbowf<}d)y-&qV(7PByt^G)B(+1n-yAJvzHdx!5lzn)J23pVS-QAOYz%FV zb0=T4{T%5%`|QlW)xzN7Oo9h!3UNqJA#2=5lSeM#>KW-nhd8AR2Ik&dAU?h#wlmd8 zH?>87*;9tnBC|e?ojY9?!jQ&es-RVEX#G0=hzFZZzWmhDW;`2`l82&)xwNIFr&`DA zq}J3xAoE3l$T=-h>1%|Ax@ zv>CdHcLG1Y$~v@eXiUxESwHMLYE+}b;MuV$`pFPmp!3%k#&nhI349AG`hAVln8+uTHJSei6R`q}BXWusL(Ji-0Dv={hR z?fD^;Ami8dduFTxiyxU6)hg+NTwt<<=%-X@y5JNhYxR-f@ zvaW9=XWLtq4{vZ-f+-)%q94ci&nc5Tde2RLo+&r9Mg;x*H+J^y zUbEn~7}eidHS!~#mD$bO+~Qb9yV6G2$&4%b1!sMiyoZ=VmI-qQ-@^HNtD)tDCoVol zWJv$+*vuvalJpYNZY-nMh75`)*}zd&&REI2-Ke+r%1U+-QqTe$2#03Kuw>uR)f|ny z{njS2S2)nuy@*R^`p)5kc<%KIsY-hyW-D@SU>)He*VId6>r>;RX;z?)X4z@4RP9;u z=!*(c;-O@$lm6!1?~Im2%{EHDS(qGg$lDDf_ITJ9^;ViLF%V0dq;rcNU3W-{xMNu9 z=72Q@6AB^hgz^YF=KM^PJDm5OVT3Jt<5u{1HB8wzXLbCHID{NMQ@#Muq>Jc`M|p#c zTn<7OQreGnA}P4beqN2y5g^S)mn28m38)qF(d~#&gAIdI(OdbAt=OJ!9*1$kyt>TV zOH$d?Q+0f{WQm5OgnQQ0Du)Ss<`Vx!vO3iNJwU@xeuQ?6uMnbl{X&{6 zC8aB3Nu$Z9xIe};Z#IO|&sK!_j&aaZDueVZ3X03ySS9&81p-95^Axf1+*+|73iZ;6 zFp-BRD^e>2uaKEJpI0Mb6J}4EWXTm zcqW8N(dg&LK!ut$xX8St`80-$qlu2NIRxN6YRkz^8=y>HOsm-7M+GQ0s_v&^Zc%Lq zQS88Ex{FVe!Kg@`z*1D!MVgK6ND{?@2%Vv_R~esrcpL52%S${{`=B5*pM&#&9cnkQ z)$Ok!s%rYaaiL~DnU#=>M4?9y;3h^ZVbyG=y`H=3#}i({UY3_q+I8bQ8eBJ`xM_bf z*M)p5_WsbSIMAKvYuxKDOR_V#Fw45m@w51ov|#%Z5TyMogFqcRZx-2F7C19e>*W(4 z*ho{Me*pYO7eh3MvcQOS4`*?;)otL5fCM2h)ylmwo_q?^ZN`?Pg?l|dJWw%Rv8%&rpx4U zNBxqJf&A-kTv{!q^CF*Gv-cI3BeRNri_2sEULvbi>3=u{nA%VmPGtE#Nt)h`u3^O< zg9ru}vTvp(WPM9lp+&vPbbUcDf!5R1lDV~y8c!Hnh&G2gn)lq@jU2w6>V^ToVZPk< zs=H5HlR4c_z_OH6wNi}S^FkO|w-5OAQ1Qo}4z6Ers9;hk1aXx`;RzGSW0(`?xrXhD zKs%}F@>7{5_M2n_44*kAw2>JE)kX2Do%KL%R4mxF{AuevU|8mRulUPPTy5z^!jP?3 z;6BI-y6GjEi9T3UHVszLV z{#;SY`1g+Ts9EZz{|C#l`mSQNzzuE^^kdN;m`f>AmA zl!kt;Xi-OQ;fC#b4aF0YdR(<%q390j6K$L!ui5)}O@$xjr|hC=fBE~TotMwts~4=z zI&pnKc*zo^8k~s4Na^!<1s{(e3L_DG>)7&T^iI;ydS)SxU9EG4etBLzxjoIL!x;~X z=CzM#HsV#roB+7zq%`x%CPDXK^}-lr^v=tusc*%J-l8_YVS>V)tQ6>(0biPi)T@&3 zQaq|X6QKpz+1dB2@ZYkH>N)yp7< zv@SXSd8qi4cP2}rxQpTs-g+0+*eHT#llaa|gd561sj`t&rxwv(O zl9zz?I7_B%EvcSnOMg+@A@xOKvLU0qu^-a6qPIZImaar6>t~=jfJX*k_3b7E#kswIM}rE|9F1Y&3BX!iyZ+tmrpIe}oRByme9bLC9u znAjw^vkat1yW>reyPh@}l|K6G<9R+PsVC8{AEwlubNtSovENHNO*{!xOybr!wwn4l z8dW_;suX=>Xjh4WWKk@AT*yv=%v>ethUdW~px6y__x9d2GA=QU4kYdci%n(y$GNV~m;dz_#g`+GaamVuJSBLvQjg&G zZT#M3vUW+scZZ3@wsi`!p!kH9+9r&@Mx6hN zeM)%9P}ic(M|6Gk1jeg$TAs}+!1RnA$gi45c$}RZB`qAt8@|&hU?-nhB0cJlbgdja zmtsmyr?+dz6*%$ssqL>^>+rhuJ5N4*Bwful4E&m|$zB@dB2{8XVzs=nxqkB14RYB7 zS~ICunF*I;wmj?*PV>ct?aqD5qj5r%9L$A(Z&&*u#^{A9MNdvh-ljUVirab?QJ?t5 zd0M!EkZR3M-Aq%8x3)*ey)N0Ayk3n@GdD7D3@qbghl z`b|sX9%fmtYCh`oCo9ZB6`+P4{?=5QP+?H^e|O1io>On1j6g{;w5-|HS8%)aCyi6# zcGi$PX#p!+a{*aD@!X0R_W5=Ijut)4wwI`P0?|xsm*La#TrL5Te9r2=k^)2;5rPO7*KL6Wtz7sb`+NG9qU`;|{ zHGs0rejjQq8lWgmhp!CsxCF8XNnm!x#_zXKa&r1&nZczBvHIq9`@h2$lV``JZJu$& zsbs`6q*AgSchavxeh1(;j*7pOfX9pOfY$<;0*<(Uz5c)aIOL>1!r-(s!ui7daE$X% z4+8`q-uxd3+9@q_-W}6vWW60w`BwYvwlX>ka*hu$mHzR;-p>7AcQBs%1B^NEP6xvZ z9#6#T=EB07+?E@P;B006T*I~XQM(uOVPPMDgYrt_ZPOSo8M~Qnq&&^b}a$p1n#;kF^?#CZL-LnM} zo0LoTpguoK@K}6LfT#Pw%@M2Jcb+pP!<`G9*l3uHBTxcRLHA(EY^I?_+RoL%zd#lM zgK_@=q7K9WT+n~5z;F7oN20Rv_*}>!~XolVeQ?MVL ziYEag%Y*iRYq{GaN{bJ=*tQB_?>mNxejt@cf8`w?#u|Ni zVjE0cyPpE)Qd)#_Y~}~u<=n2Ja$hK1W7aZJIJ!NII{k0e0~2;cdiZL%d7g?^Balmc z)1=R`c0v|mRbhrj9(7@B@gA&%^4^4sQe)fpfb5A-C`o9ZIHX?H7lPZ!mwUWg%{hwH zO^8)CY}FnM*Ecr$W&IwmKu>?S^S6Y1uctF^pMTSJM^zL)I8ITPi_>63`2jp<>GHun z1M7^0J3re`3mSCo46aY;R`1@$h6#rc$sypdn)D9R#QL0ZdnBN_xv*YCnC zMXBn!2QU{fYQSn2CM7L^!G;^k#}3XlvD|ANrW%U4{O_9|{46HZClsL~JfA^M_Tj1u zdq8RRk^0y^Q2XSb7SIzONG^u4D6oye{R*j}b!L1h`xK~Ta3M|IAc+3}M_YRrc2?S5tBS-rgupK=M?C;QiQT~3sPFDs zU%bnANZbYjAVV*pO#1}0grcOwEix+}q&PNTOi|i{72URgB~$Pr6@2l3@4-gMjTrp~ozZ_jM3{xigc51bRU|JIP zo)ewUWF;f8cZCD@Ey?m;m57M|gdJp}Y+@z#~e z$=rKJ?V6H3#C^Pp zHBd7>Utli3jURa#zeU^FPS$#A;%yw5^+i8Wv^C$V3ri96Y#=5g#LIg3m5b!2H%;Af z?ZUg&bDIVyb))n)w%)HB@J;?{F88lwPu$hBk1!A44Rmty_Z!2nd1O0Hd?yfMz0G}9hL`b+-0}e0L6W; zqdi{-b^z!H)>9qr$RyvTwfOGB6fm*6eirT`9ahsxsjGr3kJDmdxm zTjWxeDcfBT1^h$!HAw*3&XuWT6CU};e!?qCwvd23Y#`wJ1whaP7l|rn2e4#d_4Xn_ zxR&)hcWRhB0ui8R#`+cR#IF(eh|MtC)lVPEe9jPGxEGuj1i?Q2EVpkvWu>vQ{X?sj=3)&piei1jzf~&&4Tz zqz+z1jkvtJ0H=HF6sE>#3<#U;?|`w_&oDp<-l!gf=(Zy`g?e(&=6n$4O?BCI~<6yCC87_$BvUC8XN(-kys zmT+qJ0zXHFbv4zXEaDwfKAk?>?7_CVENXf~hgws`lnsy*tnp=b>MudNeL$@0naq2C zE{+Wcb)^0jW?SZT6nZZ#ib+tNM}*lT^jZ%q^dUp|5=*)#>%M!rjLr&gHU>GaAv0DEdxr?@#j%3?3l z2dLdX-SBmpbb8eVp5WLZHuJNj@k)m0!w;i160T~;&yxe3E|{kk!L2(H;)9Ym@+(7X;uR8o zwn|&znv36cxZ;btvdS!l>(iN~oY}1sNqyG_>IGla5zm1LAuO89i1tB!fy$3pA`>35 z@>}6tT)6H|MIQnR`5A>+#TNRS^ZbCM?*CC4*1SLe_tR?5QWfGX446sa)@`J=O&D}FRrrjhY10(x4; zKJB9OJUHp-Z0@IQI9GFj!Hm=q{-zUwJ8vV3&o|X|ZY8TQvY|y)Ii7n!`ojB)^k-QJ zag*QXk%f4(lrdi6u)E%(N%1W~oGnG+NWFru(eL`x0+fzXLSX^OQ&sFVl-`@+C`bsS3-2gxo9^g~bqgtr*#UL$nVVB# z`O)>1@_Q0OdQsHeeXX1L+o|KXAY%RyP>%nc(f8$4e87;+E8l=`3K)?N@Zo8Qw0SFo z80j@~(!g?zyJV6zr7~oWPuUIqN_)!8Xwap+MDN#tJdkX6e}gHKb*RGnMbMXlQ1RAn z|NZtkhbq*s&XZWt=WI>%jNHX)eqV||X0Bnf4ZWa>{YfJSjoYl}LpJ50+C;e$J)k&lgz!0&|E9H zA4KNrWohDGq(SeWZ#vs@)yq-vCijl7$CZJWHBmfA@6}$#JO#!VQA{NpRFrIoGg97C$3N>`o(9N+E>z7cG&5(15gLxwr|xG*;|;h-s7hJg%@ z&2YX&GS(;m0LXd`dny3ewPj`8*6|gzF7PK@ZWEsFwaW2IFVI9_PTMgrjCJ+J2pT2A zNCWyrBkUnOi1~Ge#2AHNzSWruh1BK4- zk%GP6o|qh0u}NKP5;iXVA?7DKk53$bhL!pdpKLTKy#*Ap+RPaFf_LeD_*y;?o7K9h)o_8eA$<3~yR6Rm)Rj z^XbgLAfo;(S}J)F17v?WGWysr)lmlL$#4Qq0^|BiIp^z!{aBrlhYEvY-mZpuB)r`R zo=oMaHzaZWFfJ+IRz2~a&-!vcy=Y{TbM=brfFj zzwi^;a?QOAN zt4aGN_=Z1O%Q3P|e$;8d%zf%9NwrWY8msAZ^+eDe@pbzBI&UU{@R8}X3I+__>|D41 zd}{|$b@cuIu6yz2SL74(h2HCznlR^PNuj$EjW!iSgz`^nLb1~p^-mScWU835!%e&r z^~pgca`tJv!fs#{H$8grx$XMFJJ%DWtii~>(em+dC-v1ZH2YQ-fBN!E+Y`|4?=H>0 zn|h7-Ijaf>b^)pH@Cw$q&)S!`D#)bxTqNA%Ht~n0+mcpHa?QkRn~(4~?F7+!T_ORV zj})z*)4|qlAEmg#*i@g;P8>k0KH3HzoPS%sH3N*`yofN)O8R5z<`?U8new~4S(>3% z5oz5Ra``MG#3$G1t?9FzG{#NI*ooR?oc_f3T<;m4A6Yx|UeV9rm=i6|U&+bE$hCJN zgaJkG*NW`ENIO;cLs~+KyDTE8`E@apT7E^fJoN%Rp* z4cyjR@fH^->t9gSq?e*w(;3c6U_r%Y?r8Wz#_blx{(Xnr57}VV1ol$bm&R-CwfnnT z4>l~wJ46tstvhoUMAFpVTzM$vYj{w46MKB5#^YsQHJ+~OvIVpE;G+Iu=9HK1ZhQXY zcuGvsFEpQN2BiPH}~k(Grf)#Vou7gr?rbJ0)tE z+MhVDc^=}=ZJzfki06NXR3C{b^;S|bafz*@pKQ)vf-L5lFjJ%bk8c>yz7vczd7D)a z(&8wRMW+LuSm<+B+iUHeu&nnnOqq$fRRlx1U`gU;kcEU%1{J zk~NB#MfeuE|3U2l3tEL(8OPozE9#PtUaFj60E?TBM5byWOae~fU>5l#aP=#+DlC~C zB+dN8xx0Q@mSLcy1sc2hVTjWv9<5Jntu&fL$l?B3Pcu#>7}+(VXEt3}c_Oz+LZ!fl z(Bax{ZuC(k{23=Xdh6U$X&~0Fo9SUr2R>~}_vE{VXQaLH8&d`r)pJXlBYk7LZBy6O z16OE*w1->FQdP?Vemtcm!l9#VJW8$k!GK2~Mrdb1)1bm=5~>MGuGt_0Qj<$h!#Wtc zw!*!d(D%k{L7P`yZr$iCU zSAcrWR9XcNn=INlS3510>`x#n=IQF(g-dq0YS|gDuO9@*r%WNK$gO+e%>2SmLw?PK z*`Ft?Z{?-lSQUlo=Nn}mUb$!&>I8=QG3+!@wSOv&*f!ZC^XpyPc*T`i0IJy+<@b_D zxX!GC`rG@ty}kp8Uxw#QT?utRC$zU>k&p{>lMR5k!sDKN#XH;OTo%NOV!D1|`5M;A zk5k8vB{#JMpzi%D@*AgL;ut}B_RCOqnnpqFM@S|~MzXB*(^CTup^-mE6I7=i2ua6# zm*M$4?ziYYr>+w{-VQciJ3A*@$t+`}1G_8ndB@0*+-)kgetMTlSKIn>TkqB48)02- zRex2uISeJW6QkY5R-VimHvqqzYK}=$*~8Sbct>`TS1eoMo&x_02h(jX!*d#3fXjth zr$o&!?9GAjSb3H%z3ug_fj;oqP|bdBAO;_DXo1GWho}g&Z$5CQ#vV4rp5fVrg1CX# zw85LxrAwPvzwUF=(x1+|jZhxUG03<6W^%eq4A z_uT5(hJ<`&gU&`i8g24A$p0g)^$3R+bfj>+!MBlE-%vZ*Y56#Bz3?8r!E-T&}56sraMAJ#CdCdv_J3yfh=-q~WsR z2yj-s7=x#>g(a??Aq z3~6#h9b*~^pK$yoD3n?a67tvPk1q9dFGTV!e*yD}+G(oHlM3wiUDd-ojMwlxqLfn- z;{80slAK5_^TF*`wwt@-{iYD=z)9d|Lt+@FDV+7*duyqArm5tIaye?yeooTX#XL0< zFGYt-WHhIZe^!&V6*9#saWNq?DfLVDf)p7b+1XA}m8ke6jH|5s;G5KpZ}+PkLwd43 zY?H=49S)53la)Vj>J!!!NcFEh_%KDUhu({|;%m*oExn$Vz>&IRw7DDB3y&B1$%f9| z*lSpurmc2D=5f^egB zJjdZVcVNQoJF^&Sv9`Cn<$v-<_W8uGE^GmZ$G{3n_1X-d7Ng;jMrLkZ@@iUYFvI@m023DSg({+5IW2K~Q zfAgxkoxSD>k-G^aF3d4WbP25k?^f z`uN-(^X*Q)h&x)b$J8rghdz2C<0(6PM;f_1{J}nJU0SHe8Qa$-ShglCRJAM91vSc? zaNNsT(<*7%6)E0H;%=Dcl^2p{Ttcgk60eATVo_;l+mxIU?pzT6gd>^o%WkHO_X%$} zeERX^g$D&T%{y;DbKe2@N1&}>N&}bEMytobae*m>1}b7=FJi#! zUk}5>$>*RVF6r80EK2z#_4ni970*G{KP*x&i_Nr zBzI`bJ&{(b!(%4jF*oaAD|M{B|TUZ`Qf-g*iNpyb;XIh_uzpH4U z*2D8}?^F*1U#`(!_7wMz(trGN8s!OUCGdT2B4;e)|D;i}qa2ayKI-u2{`Kv-wZo)>x);2&05Qz=)$#P5Frky(8; delta 57884 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 diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testWebViewWithManipulatingNavigationDelegate.macos.png b/Tests/SnapshotTestingTests/__Snapshots__/SnapshotTestingTests/testWebViewWithManipulatingNavigationDelegate.macos.png index f6fd0490cc70159e324432f223733c19b58cc5ac..ab2073c852b6f9c01aa23eda0e87cda3fadf7c8a 100644 GIT binary patch delta 57876 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 delta 57884 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 From f6c51fa7609b1057ca5420127440413c54971ff6 Mon Sep 17 00:00:00 2001 From: mbrandonw Date: Mon, 8 Jul 2024 20:22:29 +0000 Subject: [PATCH 11/15] Run swift-format --- Sources/SnapshotTesting/Diffing.swift | 2 +- .../SnapshotTestingConfiguration.swift | 20 +- .../SnapshotTesting/SnapshotsTestTrait.swift | 2 +- .../AssertInlineSnapshotSwiftTests.swift | 504 +++++++++--------- .../SnapshotTestingTests.swift | 2 +- .../SnapshotsTraitTests.swift | 57 +- .../WithSnapshotTestingTests.swift | 3 +- 7 files changed, 294 insertions(+), 296 deletions(-) diff --git a/Sources/SnapshotTesting/Diffing.swift b/Sources/SnapshotTesting/Diffing.swift index 357159fff..c189578ec 100644 --- a/Sources/SnapshotTesting/Diffing.swift +++ b/Sources/SnapshotTesting/Diffing.swift @@ -14,7 +14,7 @@ public struct Diffing { public var diff: (Value, Value) -> (String, [XCTAttachment])? /// Creates a new `Diffing` on `Value`. - /// + /// /// - Parameters: /// - toData: A function used to convert a value _to_ data. /// - fromData: A function used to produce a value _from_ data. diff --git a/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift b/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift index 93c2e7122..28cba97fe 100644 --- a/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift +++ b/Sources/SnapshotTesting/SnapshotTestingConfiguration.swift @@ -61,7 +61,7 @@ public func withSnapshotTesting( public struct SnapshotTestingConfiguration: Sendable { @_spi(Internals) @TaskLocal public static var current: Self? - + /// The diff tool use to print helpful test failure messages. /// /// See ``DiffTool-swift.struct`` for more information. @@ -79,7 +79,7 @@ public struct SnapshotTestingConfiguration: Sendable { self.diffTool = diffTool self.record = record } - + /// The record mode of the snapshot test. /// /// There are 4 primary strategies for recording: ``Record-swift.struct/all``, @@ -87,7 +87,7 @@ public struct SnapshotTestingConfiguration: Sendable { /// ``Record-swift.struct/failed`` public struct Record: Equatable, Sendable { private let storage: Storage - + public init?(rawValue: String) { switch rawValue { case "all": @@ -114,7 +114,7 @@ public struct SnapshotTestingConfiguration: Sendable { /// Records only the snapshots that are missing from disk. public static let missing = Self(storage: .missing) - /// Does not record any snapshots. If a snapshot is missing a test failure will be raised. This + /// Does not record any snapshots. If a snapshot is missing a test failure will be raised. This /// option is appropriate when running tests on CI so that re-tries of tests do not /// surprisingly pass after snapshots are unexpectedly generated. public static let never = Self(storage: .never) @@ -130,14 +130,14 @@ public struct SnapshotTestingConfiguration: Sendable { case never } } - + /// Describes the diff command used to diff two files on disk. /// /// This type can be created with a closure that takes two arguments: the first argument is /// is a file path to the currently recorded snapshot on disk, and the second argument is the /// file path to a _failed_ snapshot that was recorded to a temporary location on disk. You can /// use these two file paths to construct a command that can be used to compare the two files. - /// + /// /// For example, to use ImageMagick's `compare` tool and pipe the result into Preview.app, you /// could create the following `DiffTool`: /// @@ -193,22 +193,22 @@ public struct SnapshotTestingConfiguration: Sendable { } @available( - iOS, + iOS, deprecated: 9999, message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." ) @available( - macOS, + macOS, deprecated: 9999, message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." ) @available( - tvOS, + tvOS, deprecated: 9999, message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." ) @available( - watchOS, + watchOS, deprecated: 9999, message: "Use '.all' instead of 'true', and '.missing' instead of 'false'." ) diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift index 4a392ff16..6b4b82f77 100644 --- a/Sources/SnapshotTesting/SnapshotsTestTrait.swift +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -19,7 +19,7 @@ ) ) } - + /// Configure snapshot testing in a suite or test. /// /// - Parameter configuration: The configuration to use. diff --git a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift index 15a1f2eb2..448925cd5 100644 --- a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift +++ b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift @@ -1,307 +1,307 @@ #if canImport(Testing) -import Testing -import Foundation -import InlineSnapshotTesting -@_spi(Experimental) import SnapshotTesting - -@Suite( - .snapshots( - record: .missing + import Testing + import Foundation + import InlineSnapshotTesting + @_spi(Experimental) import SnapshotTesting + + @Suite( + .snapshots( + record: .missing + ) ) -) -struct AssertInlineSnapshotTests { - @Test func inlineSnapshot() { - assertInlineSnapshot(of: ["Hello", "World"], as: .dump) { - """ - ▿ 2 elements - - "Hello" - - "World" - - """ - } - } - - @Test func inlineSnapshot_NamedTrailingClosure() { - assertInlineSnapshot( - of: ["Hello", "World"], as: .dump, - matches: { + struct AssertInlineSnapshotTests { + @Test func inlineSnapshot() { + assertInlineSnapshot(of: ["Hello", "World"], as: .dump) { """ ▿ 2 elements - "Hello" - "World" """ - }) - } - - @Test func inlineSnapshot_Escaping() { - assertInlineSnapshot(of: "Hello\"\"\"#, world", as: .lines) { - ##""" - Hello"""#, world - """## + } } - } - - @Test func customInlineSnapshot() { - assertCustomInlineSnapshot { - "Hello" - } is: { - """ - - "Hello" - """ + @Test func inlineSnapshot_NamedTrailingClosure() { + assertInlineSnapshot( + of: ["Hello", "World"], as: .dump, + matches: { + """ + ▿ 2 elements + - "Hello" + - "World" + + """ + }) } - } - @Test func customInlineSnapshot_Multiline() { - assertCustomInlineSnapshot { - """ - "Hello" - "World" - """ - } is: { - #""" - - "\"Hello\"\n\"World\"" - - """# + @Test func inlineSnapshot_Escaping() { + assertInlineSnapshot(of: "Hello\"\"\"#, world", as: .lines) { + ##""" + Hello"""#, world + """## + } } - } - @Test func customInlineSnapshot_SingleTrailingClosure() { - assertCustomInlineSnapshot(of: { "Hello" }) { - """ - - "Hello" + @Test func customInlineSnapshot() { + assertCustomInlineSnapshot { + "Hello" + } is: { + """ + - "Hello" - """ + """ + } } - } - @Test func customInlineSnapshot_MultilineSingleTrailingClosure() { - assertCustomInlineSnapshot( - of: { "Hello" } - ) { - """ - - "Hello" + @Test func customInlineSnapshot_Multiline() { + assertCustomInlineSnapshot { + """ + "Hello" + "World" + """ + } is: { + #""" + - "\"Hello\"\n\"World\"" - """ + """# + } } - } - @Test func customInlineSnapshot_NoTrailingClosure() { - assertCustomInlineSnapshot( - of: { "Hello" }, - is: { + @Test func customInlineSnapshot_SingleTrailingClosure() { + assertCustomInlineSnapshot(of: { "Hello" }) { """ - "Hello" """ } - ) - } - - @Test func argumentlessInlineSnapshot() { - func assertArgumentlessInlineSnapshot( - expected: (() -> String)? = nil, - file: StaticString = #filePath, - function: StaticString = #function, - line: UInt = #line, - column: UInt = #column - ) { - assertInlineSnapshot( - of: "Hello", - as: .dump, - syntaxDescriptor: InlineSnapshotSyntaxDescriptor( - trailingClosureLabel: "is", - trailingClosureOffset: 1 - ), - matches: expected, - file: file, - function: function, - line: line, - column: column - ) } - assertArgumentlessInlineSnapshot { - """ - - "Hello" + @Test func customInlineSnapshot_MultilineSingleTrailingClosure() { + assertCustomInlineSnapshot( + of: { "Hello" } + ) { + """ + - "Hello" - """ + """ + } } - } - @Test func multipleInlineSnapshots() { - func assertResponse( - of url: () -> String, - head: (() -> String)? = nil, - body: (() -> String)? = nil, - file: StaticString = #filePath, - function: StaticString = #function, - line: UInt = #line, - column: UInt = #column - ) { - assertInlineSnapshot( - of: """ - HTTP/1.1 200 OK - Content-Type: text/html; charset=utf-8 - """, - as: .lines, - message: "Head did not match", - syntaxDescriptor: InlineSnapshotSyntaxDescriptor( - trailingClosureLabel: "head", - trailingClosureOffset: 1 - ), - matches: head, - file: file, - function: function, - line: line, - column: column - ) - assertInlineSnapshot( - of: """ - - - - - Point-Free - - - -

What's the point?

- - - """, - as: .lines, - message: "Body did not match", - syntaxDescriptor: InlineSnapshotSyntaxDescriptor( - trailingClosureLabel: "body", - trailingClosureOffset: 2 - ), - matches: body, - file: file, - function: function, - line: line, - column: column + @Test func customInlineSnapshot_NoTrailingClosure() { + assertCustomInlineSnapshot( + of: { "Hello" }, + is: { + """ + - "Hello" + + """ + } ) } - assertResponse { - """ - https://www.pointfree.co/ - """ - } head: { - """ - HTTP/1.1 200 OK - Content-Type: text/html; charset=utf-8 - """ - } body: { - """ - - - - - Point-Free - - - -

What's the point?

- - - """ - } - } + @Test func argumentlessInlineSnapshot() { + func assertArgumentlessInlineSnapshot( + expected: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) { + assertInlineSnapshot( + of: "Hello", + as: .dump, + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "is", + trailingClosureOffset: 1 + ), + matches: expected, + file: file, + function: function, + line: line, + column: column + ) + } - @Test func asyncThrowing() async throws { - func assertAsyncThrowingInlineSnapshot( - of value: () -> String, - is expected: (() -> String)? = nil, - file: StaticString = #filePath, - function: StaticString = #function, - line: UInt = #line, - column: UInt = #column - ) async throws { - assertInlineSnapshot( - of: value(), - as: .dump, - syntaxDescriptor: InlineSnapshotSyntaxDescriptor( - trailingClosureLabel: "is", - trailingClosureOffset: 1 - ), - matches: expected, - file: file, - function: function, - line: line, - column: column - ) + assertArgumentlessInlineSnapshot { + """ + - "Hello" + + """ + } } - try await assertAsyncThrowingInlineSnapshot { - "Hello" - } is: { - """ - - "Hello" + @Test func multipleInlineSnapshots() { + func assertResponse( + of url: () -> String, + head: (() -> String)? = nil, + body: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) { + assertInlineSnapshot( + of: """ + HTTP/1.1 200 OK + Content-Type: text/html; charset=utf-8 + """, + as: .lines, + message: "Head did not match", + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "head", + trailingClosureOffset: 1 + ), + matches: head, + file: file, + function: function, + line: line, + column: column + ) + assertInlineSnapshot( + of: """ + + + + + Point-Free + + + +

What's the point?

+ + + """, + as: .lines, + message: "Body did not match", + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "body", + trailingClosureOffset: 2 + ), + matches: body, + file: file, + function: function, + line: line, + column: column + ) + } - """ + assertResponse { + """ + https://www.pointfree.co/ + """ + } head: { + """ + HTTP/1.1 200 OK + Content-Type: text/html; charset=utf-8 + """ + } body: { + """ + + + + + Point-Free + + + +

What's the point?

+ + + """ + } } - } - @Test func nestedInClosureFunction() { - func withDependencies(operation: () -> Void) { - operation() - } + @Test func asyncThrowing() async throws { + func assertAsyncThrowingInlineSnapshot( + of value: () -> String, + is expected: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) async throws { + assertInlineSnapshot( + of: value(), + as: .dump, + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "is", + trailingClosureOffset: 1 + ), + matches: expected, + file: file, + function: function, + line: line, + column: column + ) + } - withDependencies { - assertInlineSnapshot(of: "Hello", as: .dump) { + try await assertAsyncThrowingInlineSnapshot { + "Hello" + } is: { """ - "Hello" """ } } - } - @Test func carriageReturnInlineSnapshot() { - assertInlineSnapshot(of: "This is a line\r\nAnd this is a line\r\n", as: .lines) { - """ - This is a line\r - And this is a line\r + @Test func nestedInClosureFunction() { + func withDependencies(operation: () -> Void) { + operation() + } + + withDependencies { + assertInlineSnapshot(of: "Hello", as: .dump) { + """ + - "Hello" - """ + """ + } + } } - } - @Test func carriageReturnRawInlineSnapshot() { - assertInlineSnapshot(of: "\"\"\"#This is a line\r\nAnd this is a line\r\n", as: .lines) { - ##""" - """#This is a line\##r - And this is a line\##r + @Test func carriageReturnInlineSnapshot() { + assertInlineSnapshot(of: "This is a line\r\nAnd this is a line\r\n", as: .lines) { + """ + This is a line\r + And this is a line\r - """## + """ + } + } + + @Test func carriageReturnRawInlineSnapshot() { + assertInlineSnapshot(of: "\"\"\"#This is a line\r\nAnd this is a line\r\n", as: .lines) { + ##""" + """#This is a line\##r + And this is a line\##r + + """## + } } } -} - -private func assertCustomInlineSnapshot( - of value: () -> String, - is expected: (() -> String)? = nil, - file: StaticString = #filePath, - function: StaticString = #function, - line: UInt = #line, - column: UInt = #column -) { - assertInlineSnapshot( - of: value(), - as: .dump, - syntaxDescriptor: InlineSnapshotSyntaxDescriptor( - trailingClosureLabel: "is", - trailingClosureOffset: 1 - ), - matches: expected, - file: file, - function: function, - line: line, - column: column - ) -} + + private func assertCustomInlineSnapshot( + of value: () -> String, + is expected: (() -> String)? = nil, + file: StaticString = #filePath, + function: StaticString = #function, + line: UInt = #line, + column: UInt = #column + ) { + assertInlineSnapshot( + of: value(), + as: .dump, + syntaxDescriptor: InlineSnapshotSyntaxDescriptor( + trailingClosureLabel: "is", + trailingClosureOffset: 1 + ), + matches: expected, + file: file, + function: function, + line: line, + column: column + ) + } #endif diff --git a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift index 95a66b18f..047f6af94 100644 --- a/Tests/SnapshotTestingTests/SnapshotTestingTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotTestingTests.swift @@ -23,7 +23,7 @@ import XCTest final class SnapshotTestingTests: XCTestCase { override func invokeTest() { withSnapshotTesting( - record: .missing, + record: .missing, diffTool: .ksdiff ) { super.invokeTest() diff --git a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift index a3a7ad2f5..0d2a685d2 100644 --- a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift @@ -1,54 +1,53 @@ #if compiler(>=6) && canImport(Testing) -@_spi(Experimental) import Testing -@_spi(Experimental) @_spi(Internals) import SnapshotTesting + @_spi(Experimental) import Testing + @_spi(Experimental) @_spi(Internals) import SnapshotTesting - -struct SnapshotsTraitTests { - @Test(.snapshots(diffTool: "ksdiff")) - func testDiffTool() { - #expect( - SnapshotTestingConfiguration.current? - .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") - == "ksdiff old.png new.png" - ) - } - - @Suite(.snapshots(diffTool: "ksdiff")) - struct OverrideDiffTool { - @Test(.snapshots(diffTool: "difftool")) - func testDiffToolOverride() { + struct SnapshotsTraitTests { + @Test(.snapshots(diffTool: "ksdiff")) + func testDiffTool() { #expect( SnapshotTestingConfiguration.current? .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") - == "difftool old.png new.png" + == "ksdiff old.png new.png" ) } - @Suite(.snapshots(record: .all)) - struct OverrideRecord { - @Test - func config() { + @Suite(.snapshots(diffTool: "ksdiff")) + struct OverrideDiffTool { + @Test(.snapshots(diffTool: "difftool")) + func testDiffToolOverride() { #expect( SnapshotTestingConfiguration.current? .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") - == "ksdiff old.png new.png" + == "difftool old.png new.png" ) - #expect(SnapshotTestingConfiguration.current?.record == .all) } - @Suite(.snapshots(record: .failed, diffTool: "diff")) - struct OverrideDiffToolAndRecord { + @Suite(.snapshots(record: .all)) + struct OverrideRecord { @Test func config() { #expect( SnapshotTestingConfiguration.current? .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") - == "diff old.png new.png" + == "ksdiff old.png new.png" ) - #expect(SnapshotTestingConfiguration.current?.record == .failed) + #expect(SnapshotTestingConfiguration.current?.record == .all) + } + + @Suite(.snapshots(record: .failed, diffTool: "diff")) + struct OverrideDiffToolAndRecord { + @Test + func config() { + #expect( + SnapshotTestingConfiguration.current? + .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + == "diff old.png new.png" + ) + #expect(SnapshotTestingConfiguration.current?.record == .failed) + } } } } } -} #endif diff --git a/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift b/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift index b6f6c6f57..0116964ec 100644 --- a/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift +++ b/Tests/SnapshotTestingTests/WithSnapshotTestingTests.swift @@ -1,6 +1,5 @@ -import XCTest - @_spi(Internals) @testable import SnapshotTesting +import XCTest class WithSnapshotTestingTests: XCTestCase { func testNesting() { From 63d3b45dd249878a41c56274a748ca2c1c9c5230 Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:23:25 -0400 Subject: [PATCH 12/15] Fix recordIssue for Xcode beta 3. (#869) * Fix recordIssue for Xcode beta 3. * wip * wip * fix * wip --------- Co-authored-by: Stephen Celis --- .../AssertInlineSnapshot.swift | 98 +++++++++++++------ Sources/SnapshotTesting/AssertSnapshot.swift | 70 +++++++++---- .../Internal/Deprecations.swift | 22 +++-- .../Internal/RecordIssue.swift | 18 ++-- .../AssertInlineSnapshotSwiftTests.swift | 27 +++-- .../InlineSnapshotTestingTests.swift | 27 +++-- 6 files changed, 180 insertions(+), 82 deletions(-) diff --git a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift index bc78be83e..9249b27fe 100644 --- a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift +++ b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift @@ -23,14 +23,16 @@ import Foundation /// - expected: An optional closure that returns a previously generated snapshot. When omitted, /// the library will automatically write a snapshot into your test file at the call sight of /// the assertion. - /// - file: The file where the assertion occurs. The default is the filename of the test case - /// where you call this function. + /// - fileID: The file ID in which failure occurred. Defaults to the file ID of the test case in + /// which this function was called. + /// - file: The file in which failure occurred. Defaults to the file path of the test case in + /// which this function was called. /// - function: The function where the assertion occurs. The default is the name of the test /// method where you call this function. - /// - line: The line where the assertion occurs. The default is the line number where you call - /// this function. - /// - column: The column where the assertion occurs. The default is the line column you call - /// this function. + /// - line: The line number on which failure occurred. Defaults to the line number on which this + /// function was called. + /// - column: The column on which failure occurred. Defaults to the column on which this + /// function was called. public func assertInlineSnapshot( of value: @autoclosure () throws -> Value?, as snapshotting: Snapshotting, @@ -39,7 +41,8 @@ import Foundation timeout: TimeInterval = 5, syntaxDescriptor: InlineSnapshotSyntaxDescriptor = InlineSnapshotSyntaxDescriptor(), matches expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -70,15 +73,29 @@ import Foundation loaded. If a timeout is unavoidable, consider setting the "timeout" parameter of "assertInlineSnapshot" to a higher value. """, - file: file, - line: line + fileID: fileID, + filePath: filePath, + line: line, + column: column ) return case .incorrectOrder, .interrupted, .invertedFulfillment: - recordIssue("Couldn't snapshot value", file: file, line: line) + recordIssue( + "Couldn't snapshot value", + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) return @unknown default: - recordIssue("Couldn't snapshot value", file: file, line: line) + recordIssue( + "Couldn't snapshot value", + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) return } } @@ -88,7 +105,7 @@ import Foundation record != .missing || expected != nil else { // NB: Write snapshot state before calling `XCTFail` in case `continueAfterFailure = false` - inlineSnapshotState[File(path: file), default: []].append( + inlineSnapshotState[File(path: filePath), default: []].append( InlineSnapshot( expected: expected, actual: actual, @@ -119,8 +136,10 @@ import Foundation Re-run "\(function)" to assert against the newly-recorded snapshot. """, - file: file, - line: line + fileID: fileID, + filePath: filePath, + line: line, + column: column ) return } @@ -131,8 +150,10 @@ import Foundation """ No expected value to assert against. """, - file: file, - line: line + fileID: fileID, + filePath: filePath, + line: line, + column: column ) return } @@ -147,25 +168,34 @@ import Foundation \(difference.indenting(by: 2)) """, - file: file, + fileID: fileID, + file: filePath, line: line, column: column ) } catch { - recordIssue("Threw error: \(error)", file: file, line: line) + recordIssue( + "Threw error: \(error)", + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) } } } #else @available(*, unavailable, message: "'assertInlineSnapshot' requires 'swift-syntax' >= 509.0.0") public func assertInlineSnapshot( - of value: @autoclosure () throws -> Value, + of value: @autoclosure () throws -> Value?, as snapshotting: Snapshotting, message: @autoclosure () -> String = "", + record isRecording: Bool? = nil, timeout: TimeInterval = 5, syntaxDescriptor: InlineSnapshotSyntaxDescriptor = InlineSnapshotSyntaxDescriptor(), matches expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -242,20 +272,23 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { /// /// - Parameters: /// - message: An optional description of the assertion, for inclusion in test results. - /// - file: The file where the assertion occurs. The default is the filename of the test case - /// where you call `assertInlineSnapshot`. - /// - line: The line where the assertion occurs. The default is the line number where you call - /// `assertInlineSnapshot`. - /// - column: The column where the assertion occurs. The default is the column where you call - /// `assertInlineSnapshot`. + /// - fileID: The file ID in which failure occurred. Defaults to the file ID of the test case + /// in which this function was called. + /// - file: The file in which failure occurred. Defaults to the file path of the test case in + /// which this function was called. + /// - line: The line number on which failure occurred. Defaults to the line number on which + /// this function was called. + /// - column: The column on which failure occurred. Defaults to the column on which this + /// function was called. public func fail( _ message: @autoclosure () -> String = "", - file: StaticString, + fileID: StaticString, + file filePath: StaticString, line: UInt, column: UInt ) { var trailingClosureLine: Int? - if let testSource = try? testSource(file: File(path: file)) { + if let testSource = try? testSource(file: File(path: filePath)) { let visitor = SnapshotVisitor( functionCallLine: Int(line), functionCallColumn: Int(column), @@ -267,8 +300,10 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { } recordIssue( message(), - file: file, - line: trailingClosureLine.map(UInt.init) ?? line + fileID: fileID, + filePath: filePath, + line: trailingClosureLine.map(UInt.init) ?? line, + column: column ) } @@ -279,7 +314,8 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { @available(*, unavailable, message: "'assertInlineSnapshot' requires 'swift-syntax' >= 509.0.0") public func fail( _ message: @autoclosure () -> String = "", - file: StaticString, + fileID: StaticString, + file filePath: StaticString, line: UInt, column: UInt ) { diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 737f607bb..b2d473d38 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -45,21 +45,27 @@ public var _record: SnapshotTestingConfiguration.Record = { /// - name: An optional description of the snapshot. /// - recording: Whether or not to record a new reference. /// - timeout: The amount of time a snapshot must be generated in. -/// - file: The file in which failure occurred. Defaults to the file name of the test case in +/// - fileID: The file ID in which failure occurred. Defaults to the file ID of the test case in +/// which this function was called. +/// - file: The file in which failure occurred. Defaults to the file path of the test case in /// which this function was called. /// - testName: The name of the test in which failure occurred. Defaults to the function name of /// the test case in which this function was called. /// - line: The line number on which failure occurred. Defaults to the line number on which this /// function was called. +/// - column: The column on which failure occurred. Defaults to the column on which this function +/// was called. public func assertSnapshot( of value: @autoclosure () throws -> Value, as snapshotting: Snapshotting, named name: String? = nil, record recording: Bool? = nil, timeout: TimeInterval = 5, - file: StaticString = #file, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, testName: String = #function, - line: UInt = #line + line: UInt = #line, + column: UInt = #column ) { let failure = verifySnapshot( of: try value(), @@ -67,12 +73,20 @@ public func assertSnapshot( named: name, record: recording, timeout: timeout, - file: file, + fileID: fileID, + file: filePath, testName: testName, - line: line + line: line, + column: column ) guard let message = failure else { return } - recordIssue(message, file: file, line: line) + recordIssue( + message, + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) } /// Asserts that a given value matches references on disk. @@ -83,20 +97,26 @@ public func assertSnapshot( /// comparing values. /// - recording: Whether or not to record a new reference. /// - timeout: The amount of time a snapshot must be generated in. -/// - file: The file in which failure occurred. Defaults to the file name of the test case in +/// - fileID: The file ID in which failure occurred. Defaults to the file ID of the test case in +/// which this function was called. +/// - file: The file in which failure occurred. Defaults to the file path of the test case in /// which this function was called. /// - testName: The name of the test in which failure occurred. Defaults to the function name of /// the test case in which this function was called. /// - line: The line number on which failure occurred. Defaults to the line number on which this /// function was called. +/// - column: The column on which failure occurred. Defaults to the column on which this function +/// was called. public func assertSnapshots( of value: @autoclosure () throws -> Value, as strategies: [String: Snapshotting], record recording: Bool? = nil, timeout: TimeInterval = 5, - file: StaticString = #file, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, testName: String = #function, - line: UInt = #line + line: UInt = #line, + column: UInt = #column ) { try? strategies.forEach { name, strategy in assertSnapshot( @@ -105,9 +125,11 @@ public func assertSnapshots( named: name, record: recording, timeout: timeout, - file: file, + fileID: fileID, + file: filePath, testName: testName, - line: line + line: line, + column: column ) } } @@ -119,20 +141,26 @@ public func assertSnapshots( /// - strategies: An array of strategies for serializing, deserializing, and comparing values. /// - recording: Whether or not to record a new reference. /// - timeout: The amount of time a snapshot must be generated in. -/// - file: The file in which failure occurred. Defaults to the file name of the test case in +/// - fileID: The file ID in which failure occurred. Defaults to the file ID of the test case in +/// which this function was called. +/// - file: The file in which failure occurred. Defaults to the file path of the test case in /// which this function was called. /// - testName: The name of the test in which failure occurred. Defaults to the function name of /// the test case in which this function was called. /// - line: The line number on which failure occurred. Defaults to the line number on which this /// function was called. +/// - column: The column on which failure occurred. Defaults to the column on which this function +/// was called. public func assertSnapshots( of value: @autoclosure () throws -> Value, as strategies: [Snapshotting], record recording: Bool? = nil, timeout: TimeInterval = 5, - file: StaticString = #file, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, testName: String = #function, - line: UInt = #line + line: UInt = #line, + column: UInt = #column ) { try? strategies.forEach { strategy in assertSnapshot( @@ -140,9 +168,11 @@ public func assertSnapshots( as: strategy, record: recording, timeout: timeout, - file: file, + fileID: fileID, + file: filePath, testName: testName, - line: line + line: line, + column: column ) } } @@ -205,9 +235,11 @@ public func verifySnapshot( record recording: Bool? = nil, snapshotDirectory: String? = nil, timeout: TimeInterval = 5, - file: StaticString = #file, + fileID: StaticString = #fileID, + file filePath: StaticString = #file, testName: String = #function, - line: UInt = #line + line: UInt = #line, + column: UInt = #column ) -> String? { CleanCounterBetweenTestCases.registerIfNeeded() @@ -217,7 +249,7 @@ public func verifySnapshot( ?? _record return withSnapshotTesting(record: record) { () -> String? in do { - let fileUrl = URL(fileURLWithPath: "\(file)", isDirectory: false) + let fileUrl = URL(fileURLWithPath: "\(filePath)", isDirectory: false) let fileName = fileUrl.deletingPathExtension().lastPathComponent let snapshotDirectoryUrl = diff --git a/Sources/SnapshotTesting/Internal/Deprecations.swift b/Sources/SnapshotTesting/Internal/Deprecations.swift index debb08dac..ce93f2f7f 100644 --- a/Sources/SnapshotTesting/Internal/Deprecations.swift +++ b/Sources/SnapshotTesting/Internal/Deprecations.swift @@ -14,9 +14,11 @@ public func _assertInlineSnapshot( record recording: Bool = false, timeout: TimeInterval = 5, with reference: String, - file: StaticString = #file, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, testName: String = #function, - line: UInt = #line + line: UInt = #line, + column: UInt = #column ) { let failure = _verifyInlineSnapshot( @@ -25,12 +27,14 @@ public func _assertInlineSnapshot( record: recording, timeout: timeout, with: reference, - file: file, + fileID: fileID, + file: filePath, testName: testName, - line: line + line: line, + column: column ) guard let message = failure else { return } - recordIssue(message, file: file, line: line) + recordIssue(message, fileID: fileID, filePath: filePath, line: line, column: column) } @available( @@ -44,9 +48,11 @@ public func _verifyInlineSnapshot( record recording: Bool = false, timeout: TimeInterval = 5, with reference: String, - file: StaticString = #file, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, testName: String = #function, - line: UInt = #line + line: UInt = #line, + column: UInt = #column ) -> String? { @@ -94,7 +100,7 @@ public func _verifyInlineSnapshot( // If that diff failed, we either record or fail. if recording || trimmedReference.isEmpty { - let fileName = "\(file)" + let fileName = "\(filePath)" let sourceCodeFilePath = URL(fileURLWithPath: fileName, isDirectory: false) let sourceCode = try String(contentsOf: sourceCodeFilePath) var newRecordings = recordings diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift index 76f0a4c86..01c700df8 100644 --- a/Sources/SnapshotTesting/Internal/RecordIssue.swift +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -7,20 +7,26 @@ import XCTest @_spi(Internals) public func recordIssue( _ message: @autoclosure () -> String, - file: StaticString = #filePath, - line: UInt = #line + fileID: StaticString, + filePath: StaticString, + line: UInt, + column: UInt ) { #if canImport(Testing) if Test.current != nil { Issue.record( Comment(rawValue: message()), - filePath: file.description, - line: Int(line) + sourceLocation: SourceLocation( + fileID: fileID.description, + filePath: filePath.description, + line: Int(line), + column: Int(column) + ) ) } else { - XCTFail(message(), file: file, line: line) + XCTFail(message(), file: filePath, line: line) } #else - XCTFail(message(), file: file, line: line) + XCTFail(message(), file: filePath, line: line) #endif } diff --git a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift index 448925cd5..0a193452c 100644 --- a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift +++ b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift @@ -102,7 +102,8 @@ @Test func argumentlessInlineSnapshot() { func assertArgumentlessInlineSnapshot( expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -115,7 +116,8 @@ trailingClosureOffset: 1 ), matches: expected, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -135,7 +137,8 @@ of url: () -> String, head: (() -> String)? = nil, body: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -152,7 +155,8 @@ trailingClosureOffset: 1 ), matches: head, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -178,7 +182,8 @@ trailingClosureOffset: 2 ), matches: body, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -215,7 +220,8 @@ func assertAsyncThrowingInlineSnapshot( of value: () -> String, is expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -228,7 +234,8 @@ trailingClosureOffset: 1 ), matches: expected, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -284,7 +291,8 @@ private func assertCustomInlineSnapshot( of value: () -> String, is expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -297,7 +305,8 @@ trailingClosureOffset: 1 ), matches: expected, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column diff --git a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift index 70bace93c..42198acbf 100644 --- a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift +++ b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift @@ -102,7 +102,8 @@ final class InlineSnapshotTestingTests: XCTestCase { func testArgumentlessInlineSnapshot() { func assertArgumentlessInlineSnapshot( expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -115,7 +116,8 @@ final class InlineSnapshotTestingTests: XCTestCase { trailingClosureOffset: 1 ), matches: expected, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -135,7 +137,8 @@ final class InlineSnapshotTestingTests: XCTestCase { of url: () -> String, head: (() -> String)? = nil, body: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -152,7 +155,8 @@ final class InlineSnapshotTestingTests: XCTestCase { trailingClosureOffset: 1 ), matches: head, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -178,7 +182,8 @@ final class InlineSnapshotTestingTests: XCTestCase { trailingClosureOffset: 2 ), matches: body, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -215,7 +220,8 @@ final class InlineSnapshotTestingTests: XCTestCase { func assertAsyncThrowingInlineSnapshot( of value: () -> String, is expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -228,7 +234,8 @@ final class InlineSnapshotTestingTests: XCTestCase { trailingClosureOffset: 1 ), matches: expected, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column @@ -284,7 +291,8 @@ final class InlineSnapshotTestingTests: XCTestCase { private func assertCustomInlineSnapshot( of value: () -> String, is expected: (() -> String)? = nil, - file: StaticString = #filePath, + fileID: StaticString = #fileID, + file filePath: StaticString = #filePath, function: StaticString = #function, line: UInt = #line, column: UInt = #column @@ -297,7 +305,8 @@ private func assertCustomInlineSnapshot( trailingClosureOffset: 1 ), matches: expected, - file: file, + fileID: fileID, + file: filePath, function: function, line: line, column: column From c097f955b4e724690f0fc8ffb7a6d4b881c9c4e3 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Fri, 12 Jul 2024 13:09:30 -0700 Subject: [PATCH 13/15] Point updated packages to swiftlang organization (#873) --- Package.resolved | 6 +++--- Package.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.resolved b/Package.resolved index a8fd58785..c3a7d4a7d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -3,10 +3,10 @@ { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax", + "location" : "https://github.com/swiftlang/swift-syntax", "state" : { - "revision" : "303e5c5c36d6a558407d364878df131c3546fad8", - "version" : "510.0.2" + "revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c", + "version" : "600.0.0-prerelease-2024-06-12" } } ], diff --git a/Package.swift b/Package.swift index 6d013b163..3ea312104 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/apple/swift-syntax", "509.0.0"..<"601.0.0-prerelease") + .package(url: "https://github.com/swiftlang/swift-syntax", "509.0.0"..<"601.0.0-prerelease") ], targets: [ .target( From 7690accb42b4adfadbdfeee86a27a7ae761f3303 Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:57:01 -0500 Subject: [PATCH 14/15] Fixed .failed record mode in inline snapshots. (#874) * Fixed .failed record mode in inline snapshots. * wip * wip * add some test coverage * wip --- .../AssertInlineSnapshot.swift | 54 ++++++++------- .../InlineSnapshotTestingTests.swift | 66 ++++++++++++++++++- 2 files changed, 97 insertions(+), 23 deletions(-) diff --git a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift index 9249b27fe..6a3f7996b 100644 --- a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift +++ b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift @@ -100,22 +100,25 @@ import Foundation } } let expected = expected?() - guard - record != .all, - record != .missing || expected != nil - else { + func recordSnapshot() { // NB: Write snapshot state before calling `XCTFail` in case `continueAfterFailure = false` inlineSnapshotState[File(path: filePath), default: []].append( InlineSnapshot( expected: expected, actual: actual, - wasRecording: record == .all, + wasRecording: record == .all || record == .failed, syntaxDescriptor: syntaxDescriptor, function: "\(function)", line: line, column: column ) ) + } + guard + record != .all, + (record != .missing && record != .failed) || expected != nil + else { + recordSnapshot() var failure: String if syntaxDescriptor.trailingClosureLabel @@ -162,12 +165,19 @@ import Foundation else { return } let message = message() - syntaxDescriptor.fail( - """ + var failureMessage = """ \(message.isEmpty ? "Snapshot did not match. Difference: …" : message) - + \(difference.indenting(by: 2)) - """, + """ + + if record == .failed { + recordSnapshot() + failureMessage += "\n\nA new snapshot was automatically recorded." + } + + syntaxDescriptor.fail( + failureMessage, fileID: fileID, file: filePath, line: line, @@ -352,27 +362,27 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { } } - private struct File: Hashable { - let path: StaticString - static func == (lhs: Self, rhs: Self) -> Bool { +@_spi(Internals) public struct File: Hashable { + public let path: StaticString + public static func == (lhs: Self, rhs: Self) -> Bool { "\(lhs.path)" == "\(rhs.path)" } - func hash(into hasher: inout Hasher) { + public func hash(into hasher: inout Hasher) { hasher.combine("\(self.path)") } } - private struct InlineSnapshot: Hashable { - var expected: String? - var actual: String? - var wasRecording: Bool - var syntaxDescriptor: InlineSnapshotSyntaxDescriptor - var function: String - var line: UInt - var column: UInt +@_spi(Internals) public struct InlineSnapshot: Hashable { + public var expected: String? + public var actual: String? + public var wasRecording: Bool + public var syntaxDescriptor: InlineSnapshotSyntaxDescriptor + public var function: String + public var line: UInt + public var column: UInt } - private var inlineSnapshotState: [File: [InlineSnapshot]] = [:] + @_spi(Internals) public var inlineSnapshotState: [File: [InlineSnapshot]] = [:] private struct TestSource { let source: String diff --git a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift index 42198acbf..40b2154cf 100644 --- a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift +++ b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift @@ -1,5 +1,5 @@ import Foundation -import InlineSnapshotTesting +@_spi(Internals) import InlineSnapshotTesting import SnapshotTesting import XCTest @@ -286,6 +286,70 @@ final class InlineSnapshotTestingTests: XCTestCase { """## } } + +#if canImport(Darwin) + func testRecordFailed_IncorrectExpectation() throws { + let initialInlineSnapshotState = inlineSnapshotState + defer { inlineSnapshotState = initialInlineSnapshotState } + + XCTExpectFailure { + withSnapshotTesting(record: .failed) { + assertInlineSnapshot(of: 42, as: .json) { + """ + 4 + """ + } + } + } issueMatcher: { + $0.compactDescription == """ + failed - Snapshot did not match. Difference: … + + @@ −1,1 +1,1 @@ + −4 + +42 + + A new snapshot was automatically recorded. + """ + } + + XCTAssertEqual(inlineSnapshotState.count, 1) + XCTAssertEqual( + String(describing: inlineSnapshotState.keys.first!.path) + .hasSuffix("InlineSnapshotTestingTests.swift"), + true + ) + } + #endif + +#if canImport(Darwin) + func testRecordFailed_MissingExpectation() throws { + let initialInlineSnapshotState = inlineSnapshotState + defer { inlineSnapshotState = initialInlineSnapshotState } + + XCTExpectFailure { + withSnapshotTesting(record: .failed) { + assertInlineSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription == """ + failed - Automatically recorded a new snapshot. Difference: … + + @@ −1,1 +1,1 @@ + − + +42 + + Re-run "testRecordFailed_MissingExpectation()" to assert against the newly-recorded snapshot. + """ + } + + XCTAssertEqual(inlineSnapshotState.count, 1) + XCTAssertEqual( + String(describing: inlineSnapshotState.keys.first!.path) + .hasSuffix("InlineSnapshotTestingTests.swift"), + true + ) + } + #endif } private func assertCustomInlineSnapshot( From 2d0d95e5c5317d0f129fdca4255931c09a457652 Mon Sep 17 00:00:00 2001 From: mbrandonw Date: Thu, 18 Jul 2024 19:57:36 +0000 Subject: [PATCH 15/15] Run swift-format --- .../AssertInlineSnapshot.swift | 26 ++--- .../InlineSnapshotTestingTests.swift | 106 +++++++++--------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift index 6a3f7996b..1ca6ddf8e 100644 --- a/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift +++ b/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift @@ -167,7 +167,7 @@ import Foundation let message = message() var failureMessage = """ \(message.isEmpty ? "Snapshot did not match. Difference: …" : message) - + \(difference.indenting(by: 2)) """ @@ -362,24 +362,24 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable { } } -@_spi(Internals) public struct File: Hashable { - public let path: StaticString - public static func == (lhs: Self, rhs: Self) -> Bool { + @_spi(Internals) public struct File: Hashable { + public let path: StaticString + public static func == (lhs: Self, rhs: Self) -> Bool { "\(lhs.path)" == "\(rhs.path)" } - public func hash(into hasher: inout Hasher) { + public func hash(into hasher: inout Hasher) { hasher.combine("\(self.path)") } } -@_spi(Internals) public struct InlineSnapshot: Hashable { - public var expected: String? - public var actual: String? - public var wasRecording: Bool - public var syntaxDescriptor: InlineSnapshotSyntaxDescriptor - public var function: String - public var line: UInt - public var column: UInt + @_spi(Internals) public struct InlineSnapshot: Hashable { + public var expected: String? + public var actual: String? + public var wasRecording: Bool + public var syntaxDescriptor: InlineSnapshotSyntaxDescriptor + public var function: String + public var line: UInt + public var column: UInt } @_spi(Internals) public var inlineSnapshotState: [File: [InlineSnapshot]] = [:] diff --git a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift index 40b2154cf..c1a060b1e 100644 --- a/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift +++ b/Tests/InlineSnapshotTestingTests/InlineSnapshotTestingTests.swift @@ -287,68 +287,68 @@ final class InlineSnapshotTestingTests: XCTestCase { } } -#if canImport(Darwin) - func testRecordFailed_IncorrectExpectation() throws { - let initialInlineSnapshotState = inlineSnapshotState - defer { inlineSnapshotState = initialInlineSnapshotState } - - XCTExpectFailure { - withSnapshotTesting(record: .failed) { - assertInlineSnapshot(of: 42, as: .json) { - """ - 4 - """ + #if canImport(Darwin) + func testRecordFailed_IncorrectExpectation() throws { + let initialInlineSnapshotState = inlineSnapshotState + defer { inlineSnapshotState = initialInlineSnapshotState } + + XCTExpectFailure { + withSnapshotTesting(record: .failed) { + assertInlineSnapshot(of: 42, as: .json) { + """ + 4 + """ + } } + } issueMatcher: { + $0.compactDescription == """ + failed - Snapshot did not match. Difference: … + + @@ −1,1 +1,1 @@ + −4 + +42 + + A new snapshot was automatically recorded. + """ } - } issueMatcher: { - $0.compactDescription == """ - failed - Snapshot did not match. Difference: … - - @@ −1,1 +1,1 @@ - −4 - +42 - - A new snapshot was automatically recorded. - """ - } - XCTAssertEqual(inlineSnapshotState.count, 1) - XCTAssertEqual( - String(describing: inlineSnapshotState.keys.first!.path) - .hasSuffix("InlineSnapshotTestingTests.swift"), - true - ) - } + XCTAssertEqual(inlineSnapshotState.count, 1) + XCTAssertEqual( + String(describing: inlineSnapshotState.keys.first!.path) + .hasSuffix("InlineSnapshotTestingTests.swift"), + true + ) + } #endif -#if canImport(Darwin) - func testRecordFailed_MissingExpectation() throws { - let initialInlineSnapshotState = inlineSnapshotState - defer { inlineSnapshotState = initialInlineSnapshotState } + #if canImport(Darwin) + func testRecordFailed_MissingExpectation() throws { + let initialInlineSnapshotState = inlineSnapshotState + defer { inlineSnapshotState = initialInlineSnapshotState } - XCTExpectFailure { - withSnapshotTesting(record: .failed) { - assertInlineSnapshot(of: 42, as: .json) - } - } issueMatcher: { - $0.compactDescription == """ - failed - Automatically recorded a new snapshot. Difference: … + XCTExpectFailure { + withSnapshotTesting(record: .failed) { + assertInlineSnapshot(of: 42, as: .json) + } + } issueMatcher: { + $0.compactDescription == """ + failed - Automatically recorded a new snapshot. Difference: … - @@ −1,1 +1,1 @@ - − - +42 + @@ −1,1 +1,1 @@ + − + +42 - Re-run "testRecordFailed_MissingExpectation()" to assert against the newly-recorded snapshot. - """ - } + Re-run "testRecordFailed_MissingExpectation()" to assert against the newly-recorded snapshot. + """ + } - XCTAssertEqual(inlineSnapshotState.count, 1) - XCTAssertEqual( - String(describing: inlineSnapshotState.keys.first!.path) - .hasSuffix("InlineSnapshotTestingTests.swift"), - true - ) - } + XCTAssertEqual(inlineSnapshotState.count, 1) + XCTAssertEqual( + String(describing: inlineSnapshotState.keys.first!.path) + .hasSuffix("InlineSnapshotTestingTests.swift"), + true + ) + } #endif }