ComponentKitTests/CKAnimationTests.mm (539 lines of code) (raw):
/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#import <XCTest/XCTest.h>
#import <array>
#import <ComponentKit/CKCasting.h>
#import <ComponentKit/CKAnimation.h>
#import <ComponentKit/ComponentUtilities.h>
using namespace CK;
using namespace CK::Animation;
template <size_t N>
static auto checkKeyPathsForAnimations(XCTestCase *self,
const std::array<CAPropertyAnimation *, N> &animations,
const std::array<const char *, N> &expectedKeyPaths)
{
for (auto i = 0; i < N; ++i) {
XCTAssertEqualObjects(animations[i].keyPath, @(expectedKeyPaths[i]));
}
}
@interface CKAnimationTests_KeyPaths : XCTestCase
@end
@implementation CKAnimationTests_KeyPaths
- (void)testInitialAnimationsKeyPaths
{
auto const animations = std::array<CAPropertyAnimation *, 4>{
objCForceCast<CAPropertyAnimation>(alphaFrom(0).toCA()),
objCForceCast<CAPropertyAnimation>(translationYFrom(0).toCA()),
objCForceCast<CAPropertyAnimation>(backgroundColorFrom(UIColor.blackColor).toCA()),
objCForceCast<CAPropertyAnimation>(borderColorFrom(UIColor.blackColor).toCA()),
};
auto const expectedKeyPaths = std::array<const char *, 4>{
"opacity",
"transform.translation.y",
"backgroundColor",
"borderColor"
};
checkKeyPathsForAnimations(self, animations, expectedKeyPaths);
}
- (void)testFinalAnimationsKeyPaths
{
auto const animations = std::array<CAPropertyAnimation *, 4>{
objCForceCast<CAPropertyAnimation>(alphaTo(0).toCA()),
objCForceCast<CAPropertyAnimation>(translationYTo(0).toCA()),
objCForceCast<CAPropertyAnimation>(backgroundColorTo(UIColor.blackColor).toCA()),
objCForceCast<CAPropertyAnimation>(borderColorTo(UIColor.blackColor).toCA()),
};
auto const expectedKeyPaths = std::array<const char *, 4>{
"opacity",
"transform.translation.y",
"backgroundColor",
"borderColor"
};
checkKeyPathsForAnimations(self, animations, expectedKeyPaths);
}
- (void)testChangeAnimationsKeyPaths
{
auto const animations = std::array<CAPropertyAnimation *, 4>{
objCForceCast<CAPropertyAnimation>(alpha().toCA()),
objCForceCast<CAPropertyAnimation>(backgroundColor().toCA()),
objCForceCast<CAPropertyAnimation>(borderColor().toCA()),
objCForceCast<CAPropertyAnimation>(position().toCA()),
};
auto const expectedKeyPaths = std::array<const char *, 4>{
"opacity",
"backgroundColor",
"borderColor",
"position"
};
checkKeyPathsForAnimations(self, animations, expectedKeyPaths);
}
@end
@interface CKAnimationTests_Initial: XCTestCase
@end
@implementation CKAnimationTests_Initial
- (void)testSettingScalarFromValue
{
auto a = objCForceCast<CABasicAnimation>(alphaFrom(0).toCA());
XCTAssertEqualObjects(a.fromValue, @(0));
}
- (void)testSettingUIColorFromValueForInitialAnimation
{
auto a = objCForceCast<CABasicAnimation>(backgroundColorFrom(UIColor.blueColor).toCA());
XCTAssertEqualObjects(a.fromValue, (id)UIColor.blueColor.CGColor);
}
- (void)test_WhenDurationIsNotSet_ItIsZero
{
XCTAssertEqual(alphaFrom(0).toCA().duration, 0);
XCTAssertEqual(backgroundColorFrom(UIColor.blackColor).toCA().duration, 0);
}
- (void)testSettingDuration
{
XCTAssertEqual(alphaFrom(0).withDuration(0.25).toCA().duration, 0.25);
XCTAssertEqual(backgroundColorFrom(UIColor.blackColor).withDuration(0.25).toCA().duration, 0.25);
}
- (void)testSettingDelay
{
XCTAssertEqual(alphaFrom(0).withDelay(0.25).toCA().beginTime, 0.25);
XCTAssertEqual(backgroundColorFrom(UIColor.blackColor).withDelay(0.25).toCA().beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(alphaFrom(0).toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
XCTAssertEqualObjects(backgroundColorFrom(UIColor.blackColor).toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(alphaFrom(0).easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(backgroundColorFrom(UIColor.blackColor).easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(alphaFrom(0).easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
XCTAssertEqualObjects(backgroundColorFrom(UIColor.blackColor).easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)testSettingTimingFunctionWithDuration
{
auto a1 = alphaFrom(0).easeIn(0.25).toCA();
XCTAssertEqual(a1.duration, 0.25);
XCTAssertEqualObjects(a1.timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
auto a2 = backgroundColorFrom(UIColor.blackColor).easeIn(0.25).toCA();
XCTAssertEqual(a2.duration, 0.25);
XCTAssertEqualObjects(a2.timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
}
- (void)testAlwaysUsesBackwardsFillMode
{
XCTAssertEqualObjects(alphaFrom(0).toCA().fillMode, kCAFillModeBackwards);
XCTAssertEqualObjects(backgroundColorFrom(UIColor.blackColor).toCA().fillMode, kCAFillModeBackwards);
}
@end
@interface CKAnimationTests_Final: XCTestCase
@end
@implementation CKAnimationTests_Final
- (void)testSettingScalarToValueForFinalAnimation
{
auto a = objCForceCast<CABasicAnimation>(alphaTo(0).toCA());
XCTAssertEqualObjects(a.toValue, @(0));
}
- (void)testSettingUIColorToValueForFinalAnimation
{
auto a = objCForceCast<CABasicAnimation>(backgroundColorTo(UIColor.blueColor).toCA());
XCTAssertEqualObjects(a.toValue, (id)UIColor.blueColor.CGColor);
}
- (void)test_WhenDurationIsNotSet_ItIsZero
{
XCTAssertEqual(alphaTo(0).toCA().duration, 0);
XCTAssertEqual(backgroundColorTo(UIColor.blackColor).toCA().duration, 0);
}
- (void)testSettingDuration
{
XCTAssertEqual(alphaTo(0).withDuration(0.25).toCA().duration, 0.25);
XCTAssertEqual(backgroundColorTo(UIColor.blackColor).withDuration(0.25).toCA().duration, 0.25);
}
- (void)testSettingDelay
{
XCTAssertEqual(alphaTo(0).withDelay(0.25).toCA().beginTime, 0.25);
XCTAssertEqual(backgroundColorTo(UIColor.blackColor).withDelay(0.25).toCA().beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(alphaTo(0).toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
XCTAssertEqualObjects(backgroundColorTo(UIColor.blackColor).toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(alphaTo(0).easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(backgroundColorTo(UIColor.blackColor).easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(alphaTo(0).easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
XCTAssertEqualObjects(backgroundColorTo(UIColor.blackColor).easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)testSettingTimingFunctionWithDuration
{
auto a1 = alphaTo(0).easeIn(0.25).toCA();
XCTAssertEqual(a1.duration, 0.25);
XCTAssertEqualObjects(a1.timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
auto a2 = backgroundColorTo(UIColor.blackColor).easeIn(0.25).toCA();
XCTAssertEqual(a2.duration, 0.25);
XCTAssertEqualObjects(a2.timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
}
- (void)testAlwaysUsesForwardsFillMode
{
XCTAssertEqualObjects(alphaTo(0).toCA().fillMode, kCAFillModeForwards);
XCTAssertEqualObjects(backgroundColorTo(UIColor.blackColor).toCA().fillMode, kCAFillModeForwards);
}
- (void)testIsNotRemovedOnCompletion
{
XCTAssertFalse(alphaTo(0).toCA().removedOnCompletion);
}
@end
@interface CKAnimationTests_Change: XCTestCase
@end
@implementation CKAnimationTests_Change
- (void)test_WhenDurationIsNotSet_ItIsZero
{
auto a = alpha().toCA();
XCTAssertEqual(a.duration, 0);
}
- (void)testSettingDuration
{
auto a = alpha().withDuration(0.25).toCA();
XCTAssertEqual(a.duration, 0.25);
}
- (void)testSettingDelay
{
auto a = alpha().withDelay(0.25).toCA();
XCTAssertEqual(a.beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(alpha().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(alpha().easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(alpha().easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)testSettingTimingFunctionWithDuration
{
auto a = alpha().easeIn(0.25).toCA();
XCTAssertEqual(a.duration, 0.25);
XCTAssertEqualObjects(a.timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
}
- (void)test_WhenDelayIsNotSet_UsesDefaultFillMode
{
XCTAssertEqualObjects(alpha().toCA().fillMode, kCAFillModeRemoved);
}
- (void)test_WhenDelayIsSet_UsesBackwardsFillMode
{
XCTAssertEqualObjects(alpha().withDelay(0.25).toCA().fillMode, kCAFillModeBackwards);
}
@end
@interface CKAnimationTests_Parallel : XCTestCase
@end
@implementation CKAnimationTests_Parallel
- (void)testComposingAnimations
{
auto group = objCForceCast<CAAnimationGroup>(parallel(alphaFrom(0), translationYFrom(0)).toCA());
XCTAssertEqual(group.animations.count, 2);
auto a1 = objCForceCast<CAPropertyAnimation>(group.animations[0]);
XCTAssertEqualObjects(a1.keyPath, @"opacity");
auto a2 = objCForceCast<CAPropertyAnimation>(group.animations[1]);
XCTAssertEqualObjects(a2.keyPath, @"transform.translation.y");
}
- (void)test_WhenDurationIsNotSet_ItIsZero
{
auto a = parallel(alphaFrom(0), translationYFrom(0)).toCA();
XCTAssertEqual(a.duration, 0);
}
- (void)testSettingDuration
{
auto a = parallel(alphaFrom(0), translationYFrom(0)).withDuration(0.25).toCA();
XCTAssertEqual(a.duration, 0.25);
}
- (void)testSettingDelay
{
auto a = parallel(alphaFrom(0), translationYFrom(0)).withDelay(0.25).toCA();
XCTAssertEqual(a.beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(parallel(alphaFrom(0), translationYFrom(0)).toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(parallel(alphaFrom(0), translationYFrom(0)).easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(parallel(alphaFrom(0), translationYFrom(0)).easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)testSettingCustomTimingFunction
{
auto const expectedFunc = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
auto const c = TimingCurve::fromCA(expectedFunc);
auto const func = parallel(alphaFrom(0), translationYFrom(0)).timingCurve(c).toCA().timingFunction;
XCTAssertEqualObjects(func, expectedFunc);
}
- (void)testSettingCustomTimingFunctionUsingControlPoints
{
auto const expectedPoint1 = TimingCurve::ControlPoint{0.14, 1.0};
auto const expectedPoint2 = TimingCurve::ControlPoint{0.34, 1.0};
auto const f = parallel(alphaFrom(0), translationYFrom(0))
.timingCurveWithControlPoints(expectedPoint1, expectedPoint2)
.toCA()
.timingFunction;
TimingCurve::ControlPoint point1, point2;
[f getControlPointAtIndex:1 values:point1.data()];
[f getControlPointAtIndex:2 values:point2.data()];
XCTAssert(point1 == expectedPoint1);
XCTAssert(point2 == expectedPoint2);
}
- (void)testSettingTimingFunctionWithDuration
{
auto a = parallel(alphaFrom(0), translationYFrom(0)).easeIn(0.25).toCA();
XCTAssertEqual(a.duration, 0.25);
XCTAssertEqualObjects(a.timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
}
- (void)test_WhenComposingInitialAnimations_UsesBackwardsFillMode
{
auto a = parallel(alphaFrom(0), translationYFrom(0)).toCA();
XCTAssertEqualObjects(a.fillMode, kCAFillModeBackwards);
}
- (void)test_WhenComposingChangeAnimations_UsesBackwardsFillMode
{
auto a = parallel(alpha(), position()).toCA();
XCTAssertEqualObjects(a.fillMode, kCAFillModeBackwards);
}
- (void)test_WhenComposingFinalAnimations_UsesForwardsFillMode
{
auto a = parallel(alphaTo(0), translationYTo(0)).toCA();
XCTAssertEqualObjects(a.fillMode, kCAFillModeForwards);
}
- (void)test_WhenComposingFinalAnimations_NotRemovedOnCompletion
{
auto a = parallel(alphaTo(0), translationYTo(0)).toCA();
XCTAssertFalse(a.removedOnCompletion);
}
- (void)test_WhenDurationCannotBeSetExternally_DurationIsMaxDurationOfComposedAnimations
{
auto a = parallel(alpha().withDuration(0.5), sequence(position().withDuration(0.3), backgroundColor())).toCA();
auto const expected = 0.3 + 0.25; // Explicit for position + implicit for background color > 0.5 for alpha
XCTAssertEqual(a.duration, expected);
}
@end
@interface CKAnimationTests_Sequence : XCTestCase
@end
@implementation CKAnimationTests_Sequence
- (void)testComposingAnimations
{
auto group = objCForceCast<CAAnimationGroup>(sequence(alphaFrom(0), translationYFrom(0)).toCA());
XCTAssertEqual(group.animations.count, 2);
auto a1 = objCForceCast<CAPropertyAnimation>(group.animations[0]);
XCTAssertEqualObjects(a1.keyPath, @"opacity");
auto a2 = objCForceCast<CAPropertyAnimation>(group.animations[1]);
XCTAssertEqualObjects(a2.keyPath, @"transform.translation.y");
}
- (void)testSecondAnimationStartsAfterFirst
{
auto group = objCForceCast<CAAnimationGroup>(sequence(alphaFrom(0), translationYFrom(0)).toCA());
XCTAssertEqual(group.animations.count, 2);
auto a1 = objCForceCast<CAPropertyAnimation>(group.animations[0]);
XCTAssertEqual(a1.beginTime, 0);
auto a2 = objCForceCast<CAPropertyAnimation>(group.animations[1]);
XCTAssertEqual(a2.beginTime, 0.25);
}
- (void)test_DurationIsEqualToSumOfComposedAnimationDurations
{
XCTAssertEqual(sequence(alphaFrom(0), translationYFrom(0)).toCA().duration, 0.5);
XCTAssertEqual(sequence(alphaFrom(0).withDuration(0.5), translationYFrom(0)).toCA().duration, 0.75);
XCTAssertEqual(sequence(alphaFrom(0), translationYFrom(0).withDuration(0.5)).toCA().duration, 0.75);
}
- (void)testSettingDelay
{
auto a = sequence(alphaFrom(0), translationYFrom(0)).withDelay(0.25).toCA();
XCTAssertEqual(a.beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(sequence(alphaFrom(0), translationYFrom(0)).toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(sequence(alphaFrom(0), translationYFrom(0)).easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(sequence(alphaFrom(0), translationYFrom(0)).easeOut().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)testSettingCustomTimingFunction
{
auto const expectedFunc = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
auto const c = TimingCurve::fromCA(expectedFunc);
auto const func = sequence(alphaFrom(0), translationYFrom(0)).timingCurve(c).toCA().timingFunction;
XCTAssertEqualObjects(func, expectedFunc);
}
- (void)testSettingCustomTimingFunctionUsingControlPoints
{
auto const expectedPoint1 = TimingCurve::ControlPoint{0.14, 1.0};
auto const expectedPoint2 = TimingCurve::ControlPoint{0.34, 1.0};
auto const f = sequence(alphaFrom(0), translationYFrom(0))
.timingCurveWithControlPoints(expectedPoint1, expectedPoint2)
.toCA()
.timingFunction;
TimingCurve::ControlPoint point1, point2;
[f getControlPointAtIndex:1 values:point1.data()];
[f getControlPointAtIndex:2 values:point2.data()];
XCTAssert(point1 == expectedPoint1);
XCTAssert(point2 == expectedPoint2);
}
- (void)test_WhenComposingInitialAnimations_UsesBackwardsFillMode
{
auto a = sequence(alphaFrom(0), translationYFrom(0)).toCA();
XCTAssertEqualObjects(a.fillMode, kCAFillModeBackwards);
}
@end
@interface CKAnimationTests_SpringChange : XCTestCase
@end
@implementation CKAnimationTests_SpringChange
- (void)testSpringBuilderBuildsSpringAnimation
{
XCTAssertEqualObjects(alpha().usingSpring().withDelay(0.25).toCA().class, [CASpringAnimation class]);
}
- (void)testChangeAnimationsKeyPaths
{
auto const animations = std::array<CAPropertyAnimation *, 4>{
objCForceCast<CAPropertyAnimation>(alpha().usingSpring().toCA()),
objCForceCast<CAPropertyAnimation>(backgroundColor().usingSpring().toCA()),
objCForceCast<CAPropertyAnimation>(borderColor().usingSpring().toCA()),
objCForceCast<CAPropertyAnimation>(position().usingSpring().toCA()),
};
auto const expectedKeyPaths = std::array<const char *, 4>{
"opacity",
"backgroundColor",
"borderColor",
"position"
};
checkKeyPathsForAnimations(self, animations, expectedKeyPaths);
}
- (void)testSettingDelay
{
XCTAssertEqual(alpha().usingSpring().withDelay(0.25).toCA().beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(alpha().usingSpring().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(alpha().easeIn().usingSpring().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(alpha().easeOut().usingSpring().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)test_WhenDelayIsNotSet_UsesDefaultFillMode
{
XCTAssertEqualObjects(alpha().usingSpring().toCA().fillMode, kCAFillModeRemoved);
}
- (void)test_WhenDelayIsSet_UsesBackwardsFillMode
{
XCTAssertEqualObjects(alpha().usingSpring().withDelay(0.25).toCA().fillMode, kCAFillModeBackwards);
}
- (void)testDurationIsEqualToSettlingDuration
{
auto const a = objCForceCast<CASpringAnimation>(alpha().usingSpring().toCA());
XCTAssertEqual(a.duration, a.settlingDuration);
}
- (void)testSettingDamping
{
auto const a = objCForceCast<CASpringAnimation>(alpha().usingSpring().withDamping(20).toCA());
XCTAssertEqual(a.damping, 20);
}
- (void)testSettingInitialVelocity
{
auto const a = objCForceCast<CASpringAnimation>(alpha().usingSpring().withInitialVelocity(1).toCA());
XCTAssertEqual(a.initialVelocity, 1);
}
- (void)testSettingMass
{
auto const a = objCForceCast<CASpringAnimation>(alpha().usingSpring().withMass(2).toCA());
XCTAssertEqual(a.mass, 2);
}
- (void)testSettingStiffness
{
auto const a = objCForceCast<CASpringAnimation>(alpha().usingSpring().withStiffness(200).toCA());
XCTAssertEqual(a.stiffness, 200);
}
- (void)testDurationIsSetAfterSettingSpringParams
{
auto spring = alpha().usingSpring();
auto const defaultSpringCA = objCForceCast<CASpringAnimation>(spring.toCA());
spring.withDamping(20);
auto const customSpringCA = objCForceCast<CASpringAnimation>(spring.toCA());
XCTAssertNotEqual(customSpringCA.duration, defaultSpringCA.duration);
}
@end
@interface CKAnimationTests_SpringInitial : XCTestCase
@end
@implementation CKAnimationTests_SpringInitial
- (void)testSpringBuilderBuildsSpringAnimation
{
XCTAssertEqualObjects(alphaFrom(0).usingSpring().withDelay(0.25).toCA().class, [CASpringAnimation class]);
}
- (void)testInitialAnimationKeyPaths
{
auto const animations = std::array<CAPropertyAnimation *, 4>{
objCForceCast<CAPropertyAnimation>(alphaFrom(0).usingSpring().toCA()),
objCForceCast<CAPropertyAnimation>(translationYFrom(0).usingSpring().toCA()),
objCForceCast<CAPropertyAnimation>(backgroundColorFrom(UIColor.blackColor).usingSpring().toCA()),
objCForceCast<CAPropertyAnimation>(borderColorFrom(UIColor.blackColor).usingSpring().toCA()),
};
auto const expectedKeyPaths = std::array<const char *, 4>{
"opacity",
"transform.translation.y",
"backgroundColor",
"borderColor"
};
checkKeyPathsForAnimations(self, animations, expectedKeyPaths);
}
- (void)testSettingFromValue
{
auto a = objCForceCast<CABasicAnimation>(alphaFrom(0).usingSpring().toCA());
XCTAssertEqualObjects(a.fromValue, @(0));
}
- (void)testSettingDelay
{
XCTAssertEqual(alphaFrom(0).withDelay(0.25).usingSpring().toCA().beginTime, 0.25);
}
- (void)test_WhenTimingFunctionIsNotSet_UsesLinear
{
XCTAssertEqualObjects(alphaFrom(0).usingSpring().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]);
}
- (void)testSettingTimingFunction
{
XCTAssertEqualObjects(alphaFrom(0).usingSpring().easeIn().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]);
XCTAssertEqualObjects(alphaFrom(0).easeOut().usingSpring().toCA().timingFunction, [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]);
}
- (void)testAlwaysUsesBackwardsFillMode
{
XCTAssertEqualObjects(alphaFrom(0).usingSpring().toCA().fillMode, kCAFillModeBackwards);
}
- (void)testDurationIsEqualToSettlingDuration
{
auto const a = objCForceCast<CASpringAnimation>(alphaFrom(0).usingSpring().toCA());
XCTAssertEqual(a.duration, a.settlingDuration);
}
- (void)testSettingDamping
{
auto const a = objCForceCast<CASpringAnimation>(alphaFrom(0).usingSpring().withDamping(20).toCA());
XCTAssertEqual(a.damping, 20);
}
- (void)testSettingInitialVelocity
{
auto const a = objCForceCast<CASpringAnimation>(alphaFrom(0).usingSpring().withInitialVelocity(1).toCA());
XCTAssertEqual(a.initialVelocity, 1);
}
- (void)testSettingMass
{
auto const a = objCForceCast<CASpringAnimation>(alphaFrom(0).usingSpring().withMass(2).toCA());
XCTAssertEqual(a.mass, 2);
}
- (void)testSettingStiffness
{
auto const a = objCForceCast<CASpringAnimation>(alpha().usingSpring().withStiffness(200).toCA());
XCTAssertEqual(a.stiffness, 200);
}
- (void)testDurationIsSetAfterSettingSpringParams
{
auto spring = alphaFrom(0).usingSpring();
auto const defaultSpringCA = objCForceCast<CASpringAnimation>(spring.toCA());
spring.withDamping(20);
auto const customSpringCA = objCForceCast<CASpringAnimation>(spring.toCA());
XCTAssertNotEqual(customSpringCA.duration, defaultSpringCA.duration);
}
@end