11import Foundation
22
33#if canImport(SwiftSyntax509)
4- import SnapshotTesting
4+ @ _spi ( Internals ) import SnapshotTesting
55 import SwiftParser
66 import SwiftSyntax
77 import SwiftSyntaxBuilder
@@ -35,7 +35,7 @@ import Foundation
3535 of value: @autoclosure ( ) throws -> Value ? ,
3636 as snapshotting: Snapshotting < Value , String > ,
3737 message: @autoclosure ( ) -> String = " " ,
38- record isRecording: Bool = isRecording ,
38+ record isRecording: Bool ? = nil ,
3939 timeout: TimeInterval = 5 ,
4040 syntaxDescriptor: InlineSnapshotSyntaxDescriptor = InlineSnapshotSyntaxDescriptor ( ) ,
4141 matches expected: ( ( ) -> String ) ? = nil ,
@@ -44,95 +44,116 @@ import Foundation
4444 line: UInt = #line,
4545 column: UInt = #column
4646 ) {
47- let _: Void = installTestObserver
48- do {
49- var actual : String ?
50- let expectation = XCTestExpectation ( )
51- if let value = try value ( ) {
52- snapshotting. snapshot ( value) . run {
53- actual = $0
54- expectation. fulfill ( )
47+ let record =
48+ ( isRecording == true ? . all : isRecording == false ? . missing : nil )
49+ ?? SnapshotTestingConfiguration . current? . record
50+ ?? _record
51+ withSnapshotTesting ( record: record) {
52+ let _: Void = installTestObserver
53+ do {
54+ var actual : String ?
55+ let expectation = XCTestExpectation ( )
56+ if let value = try value ( ) {
57+ snapshotting. snapshot ( value) . run {
58+ actual = $0
59+ expectation. fulfill ( )
60+ }
61+ switch XCTWaiter . wait ( for: [ expectation] , timeout: timeout) {
62+ case . completed:
63+ break
64+ case . timedOut:
65+ recordIssue (
66+ """
67+ Exceeded timeout of \( timeout) seconds waiting for snapshot.
68+
69+ This can happen when an asynchronously loaded value (like a network response) has not \
70+ loaded. If a timeout is unavoidable, consider setting the " timeout " parameter of
71+ " assertInlineSnapshot " to a higher value.
72+ """ ,
73+ file: file,
74+ line: line
75+ )
76+ return
77+ case . incorrectOrder, . interrupted, . invertedFulfillment:
78+ recordIssue ( " Couldn't snapshot value " , file: file, line: line)
79+ return
80+ @unknown default :
81+ recordIssue ( " Couldn't snapshot value " , file: file, line: line)
82+ return
83+ }
5584 }
56- switch XCTWaiter . wait ( for: [ expectation] , timeout: timeout) {
57- case . completed:
58- break
59- case . timedOut:
60- XCTFail (
85+ let expected = expected ? ( )
86+ guard
87+ record != . all,
88+ record != . missing || expected != nil
89+ else {
90+ // NB: Write snapshot state before calling `XCTFail` in case `continueAfterFailure = false`
91+ inlineSnapshotState [ File ( path: file) , default: [ ] ] . append (
92+ InlineSnapshot (
93+ expected: expected,
94+ actual: actual,
95+ wasRecording: record == . all,
96+ syntaxDescriptor: syntaxDescriptor,
97+ function: " \( function) " ,
98+ line: line,
99+ column: column
100+ )
101+ )
102+
103+ var failure : String
104+ if syntaxDescriptor. trailingClosureLabel
105+ == InlineSnapshotSyntaxDescriptor . defaultTrailingClosureLabel
106+ {
107+ failure = " Automatically recorded a new snapshot. "
108+ } else {
109+ failure = """
110+ Automatically recorded a new snapshot for " \( syntaxDescriptor. trailingClosureLabel) " .
111+ """
112+ }
113+ if let difference = snapshotting. diffing. diff ( expected ?? " " , actual ?? " " ) ? . 0 {
114+ failure += " Difference: … \n \n \( difference. indenting ( by: 2 ) ) "
115+ }
116+ recordIssue (
61117 """
62- Exceeded timeout of \( timeout ) seconds waiting for snapshot.
118+ \( failure )
63119
64- This can happen when an asynchronously loaded value (like a network response) has not \
65- loaded. If a timeout is unavoidable, consider setting the " timeout " parameter of
66- " assertInlineSnapshot " to a higher value.
120+ Re-run " \( function) " to assert against the newly-recorded snapshot.
67121 """ ,
68122 file: file,
69123 line: line
70124 )
71125 return
72- case . incorrectOrder, . interrupted, . invertedFulfillment:
73- XCTFail ( " Couldn't snapshot value " , file: file, line: line)
74- return
75- @unknown default :
76- XCTFail ( " Couldn't snapshot value " , file: file, line: line)
77- return
78126 }
79- }
80- let expected = expected ? ( )
81- guard !isRecording, let expected
82- else {
83- // NB: Write snapshot state before calling `XCTFail` in case `continueAfterFailure = false`
84- inlineSnapshotState [ File ( path: file) , default: [ ] ] . append (
85- InlineSnapshot (
86- expected: expected,
87- actual: actual,
88- wasRecording: isRecording,
89- syntaxDescriptor: syntaxDescriptor,
90- function: " \( function) " ,
91- line: line,
92- column: column
93- )
94- )
95127
96- var failure : String
97- if syntaxDescriptor. trailingClosureLabel
98- == InlineSnapshotSyntaxDescriptor . defaultTrailingClosureLabel
99- {
100- failure = " Automatically recorded a new snapshot. "
101- } else {
102- failure = """
103- Automatically recorded a new snapshot for " \( syntaxDescriptor. trailingClosureLabel) " .
128+ guard let expected
129+ else {
130+ recordIssue (
104131 """
132+ No expected value to assert against.
133+ """ ,
134+ file: file,
135+ line: line
136+ )
137+ return
105138 }
106- if let difference = snapshotting. diffing. diff ( expected ?? " " , actual ?? " " ) ? . 0 {
107- failure += " Difference: … \n \n \( difference. indenting ( by: 2 ) ) "
108- }
109- XCTFail (
139+ guard
140+ let difference = snapshotting. diffing. diff ( expected, actual ?? " " ) ? . 0
141+ else { return }
142+
143+ let message = message ( )
144+ syntaxDescriptor. fail (
110145 """
111- \( failure )
146+ \( message . isEmpty ? " Snapshot did not match. Difference: … " : message )
112147
113- Re-run " \( function ) " to assert against the newly-recorded snapshot.
148+ \( difference . indenting ( by : 2 ) )
114149 """ ,
115150 file: file,
116- line: line
151+ line: line,
152+ column: column
117153 )
118- return
154+ } catch {
155+ recordIssue ( " Threw error: \( error) " , file: file, line: line)
119156 }
120- guard let difference = snapshotting. diffing. diff ( expected, actual ?? " " ) ? . 0
121- else { return }
122-
123- let message = message ( )
124- syntaxDescriptor. fail (
125- """
126- \( message. isEmpty ? " Snapshot did not match. Difference: … " : message)
127-
128- \( difference. indenting ( by: 2 ) )
129- """ ,
130- file: file,
131- line: line,
132- column: column
133- )
134- } catch {
135- XCTFail ( " Threw error: \( error) " , file: file, line: line)
136157 }
137158 }
138159#else
@@ -197,6 +218,8 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable {
197218 /// Initializes an inline snapshot syntax descriptor.
198219 ///
199220 /// - Parameters:
221+ /// - deprecatedTrailingClosureLabels: An array of deprecated labels to consider for the inline
222+ /// snapshot.
200223 /// - trailingClosureLabel: The label of the trailing closure that returns the inline snapshot.
201224 /// - trailingClosureOffset: The offset of the trailing closure that returns the inline
202225 /// snapshot, relative to the first trailing closure.
@@ -242,7 +265,7 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable {
242265 visitor. walk ( testSource. sourceFile)
243266 trailingClosureLine = visitor. trailingClosureLine
244267 }
245- XCTFail (
268+ recordIssue (
246269 message ( ) ,
247270 file: file,
248271 line: trailingClosureLine. map ( UInt . init) ?? line
@@ -386,7 +409,7 @@ public struct InlineSnapshotSyntaxDescriptor: Hashable {
386409 ) {
387410 self . file = file
388411 self . line = snapshots. first? . line
389- self . wasRecording = snapshots. first? . wasRecording ?? isRecording
412+ self . wasRecording = snapshots. first? . wasRecording ?? false
390413 self . indent = String (
391414 sourceLocationConverter. sourceLines
392415 . first { $0. first? . isWhitespace == true && $0. contains { !$0. isWhitespace } } ?
0 commit comments