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

Code before:
    let tests: [(fromFrame: AnimationFrameTime?, toFrame: AnimationFrameTime)] = [
      (fromFrame: nil, toFrame: 10),
      (fromFrame: 8, toFrame: 14),
      (fromFrame: 14, toFrame: 0),
    ]

    let engineOptions: [(label: String, engine: RenderingEngineOption)] = [
      ("mainThread", .mainThread),
      ("coreAnimation", .coreAnimation),
      ("automatic", .automatic),
    ]

    let animation = LottieAnimation.named(
      "Issues/issue_1877",
      bundle: .lottie,
      subdirectory: Samples.directoryName)

    XCTAssertNotNil(animation)

    let window = UIWindow()

    for (test, values) in tests.enumerated() {
      for engine in engineOptions {
        let animationView = LottieAnimationView(
          animation: animation,
          configuration: .init(renderingEngine: engine.engine))

        window.addSubview(animationView)
        defer {
          animationView.removeFromSuperview()
        }

        let animationPlayingExpectation = XCTestExpectation(
          description: "Animation playing case \(test) on engine: \(engine.label)")

        let animationCompleteExpectation = XCTestExpectation(
          description: "Finished playing case \(test) on engine: \(engine.label)")

        animationView.play(fromFrame: values.fromFrame, toFrame: values.toFrame, loopMode: .playOnce) { finished in
          XCTAssertTrue(
            finished,
            "Failed case \(test) on engine: \(engine.label)")

          XCTAssertEqual(
            animationView.currentFrame,
            values.toFrame,
            accuracy: 0.01,
            "Failed case \(test) on engine: \(engine.label)")

          XCTAssertFalse(
            animationView.isAnimationPlaying,

Review comment (bug):
Updated this existing test to include an additional case. This case fails without the change to `LottieAnimationView`.

Code after:
      XCTAssert(Thread.isMainThread)
      expectation.fulfill()
    }

    wait(for: [expectation], timeout: 1.0)
  }

  func testPlayFromFrameToFrame() {
    let tests: [(fromFrame: AnimationFrameTime?, toFrame: AnimationFrameTime)] = [
      (fromFrame: nil, toFrame: 10),
      (fromFrame: 8, toFrame: 14),
      (fromFrame: 14, toFrame: 0),
    ]

    let engineOptions: [(label: String, engine: RenderingEngineOption)] = [
      ("mainThread", .mainThread),
      ("coreAnimation", .coreAnimation),
      ("automatic", .automatic),
    ]

    let animationSupportedByCoreAnimationRenderingEngine = LottieAnimation.named(
      "Issues/issue_1877",
      bundle: .lottie,
      subdirectory: Samples.directoryName)

    let animationUnsupportedByCoreAnimationRenderingEngine = LottieAnimation.named(
      "TypeFace/G",
      bundle: .lottie,
      subdirectory: Samples.directoryName)

    let animations = [
      animationSupportedByCoreAnimationRenderingEngine,
      animationUnsupportedByCoreAnimationRenderingEngine,
    ]

    for animation in animations {
      XCTAssertNotNil(animation)
      let window = UIWindow()

      for (test, values) in tests.enumerated() {
        for engine in engineOptions {
          let animationView = LottieAnimationView(
            animation: animation,
            configuration: .init(renderingEngine: engine.engine))

          window.addSubview(animationView)
          defer {
            animationView.removeFromSuperview()
          }

          let animationPlayingExpectation = XCTestExpectation(