Index: Source/core/animation/ElementAnimationTest.cpp |
diff --git a/Source/core/animation/ElementAnimationTest.cpp b/Source/core/animation/ElementAnimationTest.cpp |
index 1530c38fb700191dc041e05acc26c9f8d0d8b535..5d46be82baf250b9a9348731dce911ebb05b8a7d 100644 |
--- a/Source/core/animation/ElementAnimationTest.cpp |
+++ b/Source/core/animation/ElementAnimationTest.cpp |
@@ -37,6 +37,7 @@ |
#include "core/animation/AnimationClock.h" |
#include "core/animation/DocumentTimeline.h" |
#include "core/animation/KeyframeEffectModel.h" |
+#include "core/animation/Timing.h" |
#include "core/dom/Document.h" |
#include "core/dom/Element.h" |
@@ -51,11 +52,21 @@ v8::Handle<v8::Value> stringToV8Value(String string) |
return v8::Handle<v8::Value>::Cast(v8String(v8::Isolate::GetCurrent(), string)); |
} |
-void setV8ObjectProperty(v8::Handle<v8::Object> object, String name, String value) |
+v8::Handle<v8::Value> doubleToV8Value(double number) |
+{ |
+ return v8::Handle<v8::Value>::Cast(v8::Number::New(v8::Isolate::GetCurrent(), number)); |
+} |
+ |
+void setV8ObjectPropertyAsString(v8::Handle<v8::Object> object, String name, String value) |
{ |
object->Set(stringToV8Value(name), stringToV8Value(value)); |
} |
+void setV8ObjectPropertyAsNumber(v8::Handle<v8::Object> object, String name, double value) |
+{ |
+ object->Set(stringToV8Value(name), doubleToV8Value(value)); |
+} |
+ |
} // namespace |
class AnimationElementAnimationTest : public ::testing::Test { |
@@ -72,14 +83,40 @@ protected: |
RefPtr<Document> document; |
RefPtr<Element> element; |
+ void startAnimation(Element* element, Vector<Dictionary> keyframesDictionaryVector, Dictionary timingInput) |
+ { |
+ ElementAnimation::startAnimation(element, keyframesDictionaryVector, timingInput); |
+ } |
+ |
+ void startAnimation(Element* element, Vector<Dictionary> keyframesDictionaryVector, double timingInput) |
+ { |
+ ElementAnimation::startAnimation(element, keyframesDictionaryVector, timingInput); |
+ } |
+ |
void startAnimation(Element* element, Vector<Dictionary> keyframesDictionaryVector) |
{ |
ElementAnimation::startAnimation(element, keyframesDictionaryVector); |
} |
- void startAnimationWithSpecifiedDuration(Element* element, Vector<Dictionary> keyframesDictionaryVector, double duration) |
+ void populateTiming(Timing& timing, Dictionary timingInputDictionary) |
{ |
- ElementAnimation::startAnimation(element, keyframesDictionaryVector, duration); |
+ ElementAnimation::populateTiming(timing, timingInputDictionary); |
+ } |
+ |
+ void applyTimingInputNumber(Timing& timing, v8::Isolate* isolate, String timingProperty, double timingPropertyValue) |
+ { |
+ v8::Handle<v8::Object> timingInput = v8::Object::New(isolate); |
+ setV8ObjectPropertyAsNumber(timingInput, timingProperty, timingPropertyValue); |
+ Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate); |
+ populateTiming(timing, timingInputDictionary); |
+ } |
+ |
+ void applyTimingInputString(Timing& timing, v8::Isolate* isolate, String timingProperty, String timingPropertyValue) |
+ { |
+ v8::Handle<v8::Object> timingInput = v8::Object::New(isolate); |
+ setV8ObjectPropertyAsString(timingInput, timingProperty, timingPropertyValue); |
+ Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate); |
+ populateTiming(timing, timingInputDictionary); |
} |
}; |
@@ -94,10 +131,10 @@ TEST_F(AnimationElementAnimationTest, CanStartAnAnimation) |
v8::Handle<v8::Object> keyframe1 = v8::Object::New(isolate); |
v8::Handle<v8::Object> keyframe2 = v8::Object::New(isolate); |
- setV8ObjectProperty(keyframe1, "width", "100px"); |
- setV8ObjectProperty(keyframe1, "offset", "0"); |
- setV8ObjectProperty(keyframe2, "width", "0px"); |
- setV8ObjectProperty(keyframe2, "offset", "1"); |
+ setV8ObjectPropertyAsString(keyframe1, "width", "100px"); |
+ setV8ObjectPropertyAsString(keyframe1, "offset", "0"); |
+ setV8ObjectPropertyAsString(keyframe2, "width", "0px"); |
+ setV8ObjectPropertyAsString(keyframe2, "offset", "1"); |
jsKeyframes.append(Dictionary(keyframe1, isolate)); |
jsKeyframes.append(Dictionary(keyframe2, isolate)); |
@@ -110,7 +147,7 @@ TEST_F(AnimationElementAnimationTest, CanStartAnAnimation) |
ASSERT_TRUE(jsKeyframes[1].get("width", value2)); |
ASSERT_EQ("0px", value2); |
- startAnimationWithSpecifiedDuration(element.get(), jsKeyframes, 0); |
+ startAnimation(element.get(), jsKeyframes, 0); |
Player* player = document->timeline()->players().at(0).get(); |
@@ -157,9 +194,9 @@ TEST_F(AnimationElementAnimationTest, CanSetDuration) |
v8::Context::Scope contextScope(context); |
Vector<Dictionary, 0> jsKeyframes; |
- double duration = 2; |
- startAnimationWithSpecifiedDuration(element.get(), jsKeyframes, duration); |
+ double duration = 2; |
+ startAnimation(element.get(), jsKeyframes, duration); |
Player* player = document->timeline()->players().at(0).get(); |
@@ -180,11 +217,7 @@ TEST_F(AnimationElementAnimationTest, CanOmitSpecifiedDuration) |
Player* player = document->timeline()->players().at(0).get(); |
- // FIXME: This is correct for the moment, as using c++ default arguments means |
- // there is no way to tell whether a duration has been specified by the user. |
- // Once we implment timing object arguments we should be able to tell, and this |
- // check should be changed to EXPECT_FALSE. |
- EXPECT_TRUE(player->source()->specified().hasIterationDuration); |
+ EXPECT_FALSE(player->source()->specified().hasIterationDuration); |
EXPECT_EQ(0, player->source()->specified().iterationDuration); |
} |
@@ -196,9 +229,8 @@ TEST_F(AnimationElementAnimationTest, ClipNegativeDurationToZero) |
v8::Context::Scope contextScope(context); |
Vector<Dictionary, 0> jsKeyframes; |
- double duration = -2; |
- startAnimationWithSpecifiedDuration(element.get(), jsKeyframes, duration); |
+ startAnimation(element.get(), jsKeyframes, -2); |
Player* player = document->timeline()->players().at(0).get(); |
@@ -206,4 +238,312 @@ TEST_F(AnimationElementAnimationTest, ClipNegativeDurationToZero) |
EXPECT_EQ(0, player->source()->specified().iterationDuration); |
} |
+TEST_F(AnimationElementAnimationTest, TimingInputStartDelay) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ EXPECT_EQ(0, timing.startDelay); |
+ |
+ applyTimingInputNumber(timing, isolate, "delay", 1.1); |
+ EXPECT_EQ(1.1, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputNumber(timing, isolate, "delay", -1); |
+ EXPECT_EQ(-1, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputString(timing, isolate, "delay", "1"); |
+ EXPECT_EQ(1, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputString(timing, isolate, "delay", "1s"); |
+ EXPECT_EQ(0, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputString(timing, isolate, "delay", "Infinity"); |
+ EXPECT_EQ(0, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputString(timing, isolate, "delay", "-Infinity"); |
+ EXPECT_EQ(0, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputString(timing, isolate, "delay", "NaN"); |
+ EXPECT_EQ(0, timing.startDelay); |
+ timing.startDelay = 0; |
+ |
+ applyTimingInputString(timing, isolate, "delay", "rubbish"); |
+ EXPECT_EQ(0, timing.startDelay); |
+ timing.startDelay = 0; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputFillMode) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ Timing::FillMode defaultFillMode = Timing::FillModeForwards; |
+ EXPECT_EQ(defaultFillMode, timing.fillMode); |
+ |
+ applyTimingInputString(timing, isolate, "fill", "forwards"); |
+ EXPECT_EQ(Timing::FillModeForwards, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+ |
+ applyTimingInputString(timing, isolate, "fill", "none"); |
+ EXPECT_EQ(Timing::FillModeNone, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+ |
+ applyTimingInputString(timing, isolate, "fill", "backwards"); |
+ EXPECT_EQ(Timing::FillModeBackwards, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+ |
+ applyTimingInputString(timing, isolate, "fill", "both"); |
+ EXPECT_EQ(Timing::FillModeBoth, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+ |
+ applyTimingInputString(timing, isolate, "fill", "everything!"); |
+ EXPECT_EQ(defaultFillMode, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+ |
+ applyTimingInputString(timing, isolate, "fill", "backwardsandforwards"); |
+ EXPECT_EQ(defaultFillMode, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+ |
+ applyTimingInputNumber(timing, isolate, "fill", 2); |
+ EXPECT_EQ(defaultFillMode, timing.fillMode); |
+ timing.fillMode = defaultFillMode; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputIterationStart) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ EXPECT_EQ(0, timing.iterationStart); |
+ |
+ applyTimingInputNumber(timing, isolate, "iterationStart", 1.1); |
+ EXPECT_EQ(1.1, timing.iterationStart); |
+ timing.iterationStart = 0; |
+ |
+ applyTimingInputNumber(timing, isolate, "iterationStart", -1); |
+ EXPECT_EQ(0, timing.iterationStart); |
+ timing.iterationStart = 0; |
+ |
+ applyTimingInputString(timing, isolate, "iterationStart", "Infinity"); |
+ EXPECT_EQ(0, timing.iterationStart); |
+ timing.iterationStart = 0; |
+ |
+ applyTimingInputString(timing, isolate, "iterationStart", "-Infinity"); |
+ EXPECT_EQ(0, timing.iterationStart); |
+ timing.iterationStart = 0; |
+ |
+ applyTimingInputString(timing, isolate, "iterationStart", "NaN"); |
+ EXPECT_EQ(0, timing.iterationStart); |
+ timing.iterationStart = 0; |
+ |
+ applyTimingInputString(timing, isolate, "iterationStart", "rubbish"); |
+ EXPECT_EQ(0, timing.iterationStart); |
+ timing.iterationStart = 0; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputIterationCount) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ EXPECT_EQ(1, timing.iterationCount); |
+ |
+ applyTimingInputNumber(timing, isolate, "iterations", 2.1); |
+ EXPECT_EQ(2.1, timing.iterationCount); |
+ timing.iterationCount = 1; |
+ |
+ applyTimingInputNumber(timing, isolate, "iterations", -1); |
+ EXPECT_EQ(0, timing.iterationCount); |
+ timing.iterationCount = 1; |
+ |
+ applyTimingInputString(timing, isolate, "iterations", "Infinity"); |
+ EXPECT_TRUE(isinf(timing.iterationCount) && (timing.iterationCount > 0)); |
+ timing.iterationCount = 1; |
+ |
+ applyTimingInputString(timing, isolate, "iterations", "-Infinity"); |
+ EXPECT_EQ(0, timing.iterationCount); |
+ timing.iterationCount = 1; |
+ |
+ applyTimingInputString(timing, isolate, "iterations", "NaN"); |
+ EXPECT_EQ(1, timing.iterationCount); |
+ timing.iterationCount = 1; |
+ |
+ applyTimingInputString(timing, isolate, "iterations", "rubbish"); |
+ EXPECT_EQ(1, timing.iterationCount); |
+ timing.iterationCount = 1; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputIterationDuration) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ EXPECT_EQ(0, timing.iterationDuration); |
+ EXPECT_FALSE(timing.hasIterationDuration); |
+ |
+ applyTimingInputNumber(timing, isolate, "duration", 1.1); |
+ EXPECT_EQ(1.1, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputNumber(timing, isolate, "duration", -1); |
+ EXPECT_EQ(0, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputString(timing, isolate, "duration", "1"); |
+ EXPECT_EQ(1, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputString(timing, isolate, "duration", "Infinity"); |
+ EXPECT_TRUE(isinf(timing.iterationDuration) && (timing.iterationDuration > 0)); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputString(timing, isolate, "duration", "-Infinity"); |
+ EXPECT_EQ(0, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputString(timing, isolate, "duration", "NaN"); |
+ EXPECT_EQ(0, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputString(timing, isolate, "duration", "auto"); |
+ EXPECT_EQ(0, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+ |
+ applyTimingInputString(timing, isolate, "duration", "rubbish"); |
+ EXPECT_EQ(0, timing.iterationDuration); |
+ EXPECT_TRUE(timing.hasIterationDuration); |
+ timing.hasIterationDuration = false; |
+ timing.iterationDuration = 0; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputPlaybackRate) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ EXPECT_EQ(1, timing.playbackRate); |
+ |
+ applyTimingInputNumber(timing, isolate, "playbackRate", 2.1); |
+ EXPECT_EQ(2.1, timing.playbackRate); |
+ timing.playbackRate = 1; |
+ |
+ applyTimingInputNumber(timing, isolate, "playbackRate", -1); |
+ EXPECT_EQ(-1, timing.playbackRate); |
+ timing.playbackRate = 1; |
+ |
+ applyTimingInputString(timing, isolate, "playbackRate", "Infinity"); |
+ EXPECT_EQ(1, timing.playbackRate); |
+ timing.playbackRate = 1; |
+ |
+ applyTimingInputString(timing, isolate, "playbackRate", "-Infinity"); |
+ EXPECT_EQ(1, timing.playbackRate); |
+ timing.playbackRate = 1; |
+ |
+ applyTimingInputString(timing, isolate, "playbackRate", "NaN"); |
+ EXPECT_EQ(1, timing.playbackRate); |
+ timing.playbackRate = 1; |
+ |
+ applyTimingInputString(timing, isolate, "playbackRate", "rubbish"); |
+ EXPECT_EQ(1, timing.playbackRate); |
+ timing.playbackRate = 1; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputDirection) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing timing; |
+ Timing::PlaybackDirection defaultPlaybackDirection = Timing::PlaybackDirectionNormal; |
+ EXPECT_EQ(defaultPlaybackDirection, timing.direction); |
+ |
+ applyTimingInputString(timing, isolate, "direction", "normal"); |
+ EXPECT_EQ(Timing::PlaybackDirectionNormal, timing.direction); |
+ timing.direction = defaultPlaybackDirection; |
+ |
+ applyTimingInputString(timing, isolate, "direction", "reverse"); |
+ EXPECT_EQ(Timing::PlaybackDirectionReverse, timing.direction); |
+ timing.direction = defaultPlaybackDirection; |
+ |
+ applyTimingInputString(timing, isolate, "direction", "alternate"); |
+ EXPECT_EQ(Timing::PlaybackDirectionAlternate, timing.direction); |
+ timing.direction = defaultPlaybackDirection; |
+ |
+ applyTimingInputString(timing, isolate, "direction", "alternate-reverse"); |
+ EXPECT_EQ(Timing::PlaybackDirectionAlternateReverse, timing.direction); |
+ timing.direction = defaultPlaybackDirection; |
+ |
+ applyTimingInputString(timing, isolate, "direction", "rubbish"); |
+ EXPECT_EQ(defaultPlaybackDirection, timing.direction); |
+ timing.direction = defaultPlaybackDirection; |
+ |
+ applyTimingInputNumber(timing, isolate, "direction", 2); |
+ EXPECT_EQ(defaultPlaybackDirection, timing.direction); |
+ timing.direction = defaultPlaybackDirection; |
+} |
+ |
+TEST_F(AnimationElementAnimationTest, TimingInputEmpty) |
+{ |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope scope(isolate); |
+ v8::Local<v8::Context> context = v8::Context::New(isolate); |
+ v8::Context::Scope contextScope(context); |
+ |
+ Timing updatedTiming; |
+ Timing controlTiming; |
+ |
+ v8::Handle<v8::Object> timingInput = v8::Object::New(isolate); |
+ Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate); |
+ populateTiming(updatedTiming, timingInputDictionary); |
+ |
+ EXPECT_EQ(controlTiming.startDelay, updatedTiming.startDelay); |
+ EXPECT_EQ(controlTiming.fillMode, updatedTiming.fillMode); |
+ EXPECT_EQ(controlTiming.iterationStart, updatedTiming.iterationStart); |
+ EXPECT_EQ(controlTiming.iterationCount, updatedTiming.iterationCount); |
+ EXPECT_EQ(controlTiming.iterationDuration, updatedTiming.iterationDuration); |
+ EXPECT_EQ(controlTiming.hasIterationDuration, updatedTiming.hasIterationDuration); |
+ EXPECT_EQ(controlTiming.playbackRate, updatedTiming.playbackRate); |
+ EXPECT_EQ(controlTiming.direction, updatedTiming.direction); |
+} |
+ |
} // namespace WebCore |