@@ -352,42 +352,69 @@ public func verifySnapshot<Value, Format>(
352
352
return " Couldn't snapshot value "
353
353
}
354
354
355
- func recordSnapshot( ) throws {
356
- try snapshotting. diffing. toData ( diffable) . write ( to: snapshotFileUrl)
355
+ func recordSnapshot( writeToDisk: Bool ) throws {
356
+ let snapshotData = snapshotting. diffing. toData ( diffable)
357
+
358
+ if writeToDisk {
359
+ try snapshotData. write ( to: snapshotFileUrl)
360
+ }
361
+
357
362
#if !os(Linux) && !os(Windows)
358
363
if !isSwiftTesting,
359
364
ProcessInfo . processInfo. environment. keys. contains ( " __XCODE_BUILT_PRODUCTS_DIR_PATHS " )
360
365
{
361
366
XCTContext . runActivity ( named: " Attached Recorded Snapshot " ) { activity in
362
- let attachment = XCTAttachment ( contentsOfFile: snapshotFileUrl)
363
- activity. add ( attachment)
367
+ if writeToDisk {
368
+ // Snapshot was written to disk. Create attachment from file
369
+ let attachment = XCTAttachment ( contentsOfFile: snapshotFileUrl)
370
+ activity. add ( attachment)
371
+ } else {
372
+ // Snapshot was not written to disk. Create attachment from data and path extension
373
+ let typeIdentifier = snapshotting. pathExtension. flatMap ( uniformTypeIdentifier ( fromExtension: ) )
374
+
375
+ let attachment = XCTAttachment (
376
+ uniformTypeIdentifier: typeIdentifier,
377
+ name: snapshotFileUrl. lastPathComponent,
378
+ payload: snapshotData
379
+ )
380
+
381
+ activity. add ( attachment)
382
+ }
364
383
}
365
384
}
366
385
#endif
367
386
}
368
387
369
- guard
370
- record != . all,
371
- ( record != . missing && record != . failed)
372
- || fileManager. fileExists ( atPath: snapshotFileUrl. path)
373
- else {
374
- try recordSnapshot ( )
388
+ if record == . all {
389
+ try recordSnapshot ( writeToDisk: true )
375
390
376
- return SnapshotTestingConfiguration . current? . record == . all
377
- ? """
391
+ return """
378
392
Record mode is on. Automatically recorded snapshot: …
379
393
380
394
open " \( snapshotFileUrl. absoluteString) "
381
395
382
396
Turn record mode off and re-run " \( testName) " to assert against the newly-recorded snapshot
383
397
"""
384
- : """
398
+ }
399
+
400
+ guard fileManager. fileExists ( atPath: snapshotFileUrl. path) else {
401
+ if record == . never {
402
+ try recordSnapshot ( writeToDisk: false )
403
+
404
+ return """
405
+ No reference was found on disk. New snapshot was not recorded because recording is disabled
406
+ """
407
+ } else {
408
+ try recordSnapshot ( writeToDisk: true )
409
+
410
+ return """
385
411
No reference was found on disk. Automatically recorded snapshot: …
386
412
387
413
open " \( snapshotFileUrl. absoluteString) "
388
414
389
415
Re-run " \( testName) " to assert against the newly-recorded snapshot.
390
416
"""
417
+ }
391
418
}
392
419
393
420
let data = try Data ( contentsOf: snapshotFileUrl)
@@ -444,7 +471,7 @@ public func verifySnapshot<Value, Format>(
444
471
}
445
472
446
473
if record == . failed {
447
- try recordSnapshot ( )
474
+ try recordSnapshot ( writeToDisk : true )
448
475
failureMessage += " A new snapshot was automatically recorded. "
449
476
}
450
477
@@ -473,6 +500,19 @@ func sanitizePathComponent(_ string: String) -> String {
473
500
. replacingOccurrences ( of: " ^-|-$ " , with: " " , options: . regularExpression)
474
501
}
475
502
503
+ #if !os(Linux) && !os(Windows)
504
+ func uniformTypeIdentifier( fromExtension pathExtension: String ) -> String ? {
505
+ // This can be much cleaner in macOS 11+ using UTType
506
+ let unmanagedString = UTTypeCreatePreferredIdentifierForTag (
507
+ kUTTagClassFilenameExtension as CFString ,
508
+ pathExtension as CFString ,
509
+ nil
510
+ )
511
+
512
+ return unmanagedString? . takeRetainedValue ( ) as String ?
513
+ }
514
+ #endif
515
+
476
516
// We need to clean counter between tests executions in order to support test-iterations.
477
517
private class CleanCounterBetweenTestCases : NSObject , XCTestObservation {
478
518
private static var registered = false
0 commit comments