Repository: airbnb/lottie-ios
File: Tests/SnapshotTests.swift (Swift)

Code before:
  private let progressPercentagesToSnapshot = [0, 0.25, 0.5, 0.75, 1.0]

  /// Captures snapshots of `sampleAnimationURLs` and compares them to the snapshot images stored on disk
  private func compareSampleSnapshots(
    configuration: LottieConfiguration,
    testName: String = #function)
    async throws
  {
    guard try SnapshotTests.enabled else { return }

    #if os(iOS)
    for sampleAnimationName in Samples.sampleAnimationNames {
      for percent in progressPercentagesToSnapshot {
        guard
          let animationView = await SnapshotConfiguration.makeAnimationView(
            for: sampleAnimationName,
            configuration: configuration)
        else { continue }

        animationView.currentProgress = CGFloat(percent)

        assertSnapshot(
          matching: animationView,
          as: .imageOfPresentationLayer(
            precision: SnapshotConfiguration.forSample(named: sampleAnimationName).precision),
          named: "\(sampleAnimationName) (\(Int(percent * 100))%)",
          testName: testName)
      }
    }
    #endif
  }

}

// MARK: Animation + snapshotSize

extension LottieAnimation {
  /// The size that this animation should be snapshot at
  var snapshotSize: CGSize {
    let maxDimension: CGFloat = 500

    // If this is a landscape aspect ratio, we clamp the width
    if width > height {
      let newWidth = min(CGFloat(width), maxDimension)
      let newHeight = newWidth * (CGFloat(height) / CGFloat(width))
      return CGSize(width: newWidth, height: newHeight)
    }

    // otherwise, this is either a square or portrait aspect ratio,
    // in which case we clamp the height
    else {

Review comment (bug):
I was getting diff failures locally on master, probably because I'm using a different Xcode version than CI. I enabled `perceptualPrecision` (a new-ish feature in the snapshotting library) which should prevent that sort of issue from now on.

Code after:
  private let progressPercentagesToSnapshot = [0, 0.25, 0.5, 0.75, 1.0]

  /// Captures snapshots of `sampleAnimationURLs` and compares them to the snapshot images stored on disk
  private func compareSampleSnapshots(
    configuration: LottieConfiguration,
    testName: String = #function)
    async throws
  {
    guard try SnapshotTests.enabled else { return }

    #if os(iOS)
    for sampleAnimationName in Samples.sampleAnimationNames {
      for percent in progressPercentagesToSnapshot {
        guard
          let animationView = await SnapshotConfiguration.makeAnimationView(
            for: sampleAnimationName,
            configuration: configuration)
        else { continue }

        animationView.currentProgress = CGFloat(percent)

        assertSnapshot(
          matching: animationView,
          as: .imageOfPresentationLayer(
            precision: SnapshotConfiguration.forSample(named: sampleAnimationName).precision,
            perceptualPrecision: 0.985),
          named: "\(sampleAnimationName) (\(Int(percent * 100))%)",
          testName: testName)
      }
    }
    #endif
  }

}

// MARK: Animation + snapshotSize

extension LottieAnimation {
  /// The size that this animation should be snapshot at
  var snapshotSize: CGSize {
    let maxDimension: CGFloat = 500

    // If this is a landscape aspect ratio, we clamp the width
    if width > height {
      let newWidth = min(CGFloat(width), maxDimension)
      let newHeight = newWidth * (CGFloat(height) / CGFloat(width))
      return CGSize(width: newWidth, height: newHeight)
    }

    // otherwise, this is either a square or portrait aspect ratio,
    // in which case we clamp the height