1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/animation/Animation.h"
8 #include "bindings/v8/Dictionary.h"
9 #include "core/animation/AnimatableLength.h"
10 #include "core/animation/AnimationClock.h"
11 #include "core/animation/AnimationHelpers.h"
12 #include "core/animation/DocumentTimeline.h"
13 #include "core/animation/KeyframeEffectModel.h"
14 #include "core/animation/TimedItemTiming.h"
15 #include "platform/animation/TimingFunctionTestHelper.h"
17 #include <gtest/gtest.h>
23 v8::Handle<v8::Value> stringToV8Value(String string)
25 return v8::Handle<v8::Value>::Cast(v8String(v8::Isolate::GetCurrent(), string));
28 v8::Handle<v8::Value> doubleToV8Value(double number)
30 return v8::Handle<v8::Value>::Cast(v8::Number::New(v8::Isolate::GetCurrent(), number));
33 void setV8ObjectPropertyAsString(v8::Handle<v8::Object> object, String name, String value)
35 object->Set(stringToV8Value(name), stringToV8Value(value));
38 void setV8ObjectPropertyAsNumber(v8::Handle<v8::Object> object, String name, double value)
40 object->Set(stringToV8Value(name), doubleToV8Value(value));
45 class AnimationAnimationTest : public ::testing::Test {
49 document = Document::create();
50 document->animationClock().resetTimeForTesting();
51 element = document->createElement("foo", ASSERT_NO_EXCEPTION);
52 document->timeline()->setZeroTime(0);
53 ASSERT_EQ(0, document->timeline()->currentTime());
56 RefPtr<Document> document;
57 RefPtr<Element> element;
59 PassRefPtr<Animation> createAnimation(Element* element, Vector<Dictionary> keyframeDictionaryVector, Dictionary timingInput)
61 return Animation::createUnsafe(element, keyframeDictionaryVector, timingInput);
64 PassRefPtr<Animation> createAnimation(Element* element, Vector<Dictionary> keyframeDictionaryVector, double timingInput)
66 return Animation::createUnsafe(element, keyframeDictionaryVector, timingInput);
69 PassRefPtr<Animation> createAnimation(Element* element, Vector<Dictionary> keyframeDictionaryVector)
71 return Animation::createUnsafe(element, keyframeDictionaryVector);
74 void populateTiming(Timing& timing, Dictionary timingInputDictionary)
76 Animation::populateTiming(timing, timingInputDictionary);
79 void applyTimingInputNumber(Timing& timing, v8::Isolate* isolate, String timingProperty, double timingPropertyValue)
81 v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
82 setV8ObjectPropertyAsNumber(timingInput, timingProperty, timingPropertyValue);
83 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
84 populateTiming(timing, timingInputDictionary);
87 void applyTimingInputString(Timing& timing, v8::Isolate* isolate, String timingProperty, String timingPropertyValue)
89 v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
90 setV8ObjectPropertyAsString(timingInput, timingProperty, timingPropertyValue);
91 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
92 populateTiming(timing, timingInputDictionary);
96 TEST_F(AnimationAnimationTest, CanCreateAnAnimation)
98 v8::Isolate* isolate = v8::Isolate::GetCurrent();
99 v8::HandleScope scope(isolate);
100 v8::Local<v8::Context> context = v8::Context::New(isolate);
101 v8::Context::Scope contextScope(context);
103 Vector<Dictionary> jsKeyframes;
104 v8::Handle<v8::Object> keyframe1 = v8::Object::New(isolate);
105 v8::Handle<v8::Object> keyframe2 = v8::Object::New(isolate);
107 setV8ObjectPropertyAsString(keyframe1, "width", "100px");
108 setV8ObjectPropertyAsString(keyframe1, "offset", "0");
109 setV8ObjectPropertyAsString(keyframe1, "easing", "ease-in-out");
110 setV8ObjectPropertyAsString(keyframe2, "width", "0px");
111 setV8ObjectPropertyAsString(keyframe2, "offset", "1");
112 setV8ObjectPropertyAsString(keyframe2, "easing", "cubic-bezier(1, 1, 0.3, 0.3)");
114 jsKeyframes.append(Dictionary(keyframe1, isolate));
115 jsKeyframes.append(Dictionary(keyframe2, isolate));
118 ASSERT_TRUE(jsKeyframes[0].get("width", value1));
119 ASSERT_EQ("100px", value1);
122 ASSERT_TRUE(jsKeyframes[1].get("width", value2));
123 ASSERT_EQ("0px", value2);
125 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, 0);
127 Element* target = animation->target();
128 EXPECT_EQ(*element.get(), *target);
130 const KeyframeEffectModel::KeyframeVector keyframes =
131 toKeyframeEffectModel(animation->effect())->getFrames();
133 EXPECT_EQ(0, keyframes[0]->offset());
134 EXPECT_EQ(1, keyframes[1]->offset());
136 const AnimatableValue* keyframe1Width = keyframes[0]->propertyValue(CSSPropertyWidth);
137 const AnimatableValue* keyframe2Width = keyframes[1]->propertyValue(CSSPropertyWidth);
138 ASSERT(keyframe1Width);
139 ASSERT(keyframe2Width);
141 EXPECT_TRUE(keyframe1Width->isLength());
142 EXPECT_TRUE(keyframe2Width->isLength());
144 EXPECT_EQ("100px", toAnimatableLength(keyframe1Width)->toCSSValue()->cssText());
145 EXPECT_EQ("0px", toAnimatableLength(keyframe2Width)->toCSSValue()->cssText());
147 EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut)), *keyframes[0]->easing());
148 EXPECT_EQ(*(CubicBezierTimingFunction::create(1, 1, 0.3, 0.3).get()), *keyframes[1]->easing());
151 TEST_F(AnimationAnimationTest, CanSetDuration)
153 v8::Isolate* isolate = v8::Isolate::GetCurrent();
154 v8::HandleScope scope(isolate);
155 v8::Local<v8::Context> context = v8::Context::New(isolate);
156 v8::Context::Scope contextScope(context);
158 Vector<Dictionary, 0> jsKeyframes;
161 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, duration);
163 EXPECT_EQ(duration, animation->specifiedTiming().iterationDuration);
166 TEST_F(AnimationAnimationTest, CanOmitSpecifiedDuration)
168 v8::Isolate* isolate = v8::Isolate::GetCurrent();
169 v8::HandleScope scope(isolate);
170 v8::Local<v8::Context> context = v8::Context::New(isolate);
171 v8::Context::Scope contextScope(context);
173 Vector<Dictionary, 0> jsKeyframes;
175 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes);
177 EXPECT_TRUE(std::isnan(animation->specifiedTiming().iterationDuration));
180 TEST_F(AnimationAnimationTest, ClipNegativeDurationToZero)
182 v8::Isolate* isolate = v8::Isolate::GetCurrent();
183 v8::HandleScope scope(isolate);
184 v8::Local<v8::Context> context = v8::Context::New(isolate);
185 v8::Context::Scope contextScope(context);
187 Vector<Dictionary, 0> jsKeyframes;
189 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, -2);
191 EXPECT_EQ(0, animation->specifiedTiming().iterationDuration);
194 TEST_F(AnimationAnimationTest, SpecifiedGetters)
196 v8::Isolate* isolate = v8::Isolate::GetCurrent();
197 v8::HandleScope scope(isolate);
198 v8::Local<v8::Context> context = v8::Context::New(isolate);
199 v8::Context::Scope contextScope(context);
201 Vector<Dictionary, 0> jsKeyframes;
203 v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
204 setV8ObjectPropertyAsNumber(timingInput, "delay", 2);
205 setV8ObjectPropertyAsNumber(timingInput, "endDelay", 0.5);
206 setV8ObjectPropertyAsString(timingInput, "fill", "backwards");
207 setV8ObjectPropertyAsNumber(timingInput, "iterationStart", 2);
208 setV8ObjectPropertyAsNumber(timingInput, "iterations", 10);
209 setV8ObjectPropertyAsNumber(timingInput, "playbackRate", 2);
210 setV8ObjectPropertyAsString(timingInput, "direction", "reverse");
211 setV8ObjectPropertyAsString(timingInput, "easing", "step-start");
212 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
214 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, timingInputDictionary);
216 RefPtr<TimedItemTiming> specified = animation->specified();
217 EXPECT_EQ(2, specified->delay());
218 EXPECT_EQ(0.5, specified->endDelay());
219 EXPECT_EQ("backwards", specified->fill());
220 EXPECT_EQ(2, specified->iterationStart());
221 EXPECT_EQ(10, specified->iterations());
222 EXPECT_EQ(2, specified->playbackRate());
223 EXPECT_EQ("reverse", specified->direction());
224 EXPECT_EQ("step-start", specified->easing());
227 TEST_F(AnimationAnimationTest, SpecifiedDurationGetter)
229 v8::Isolate* isolate = v8::Isolate::GetCurrent();
230 v8::HandleScope scope(isolate);
231 v8::Local<v8::Context> context = v8::Context::New(isolate);
232 v8::Context::Scope contextScope(context);
234 Vector<Dictionary, 0> jsKeyframes;
236 v8::Handle<v8::Object> timingInputWithDuration = v8::Object::New(isolate);
237 setV8ObjectPropertyAsNumber(timingInputWithDuration, "duration", 2.5);
238 Dictionary timingInputDictionaryWithDuration = Dictionary(v8::Handle<v8::Value>::Cast(timingInputWithDuration), isolate);
240 RefPtr<Animation> animationWithDuration = createAnimation(element.get(), jsKeyframes, timingInputDictionaryWithDuration);
242 RefPtr<TimedItemTiming> specifiedWithDuration = animationWithDuration->specified();
243 bool isNumber = false;
244 double numberDuration = std::numeric_limits<double>::quiet_NaN();
245 bool isString = false;
246 String stringDuration = "";
247 specifiedWithDuration->getDuration("duration", isNumber, numberDuration, isString, stringDuration);
248 EXPECT_TRUE(isNumber);
249 EXPECT_EQ(2.5, numberDuration);
250 EXPECT_FALSE(isString);
251 EXPECT_EQ("", stringDuration);
254 v8::Handle<v8::Object> timingInputNoDuration = v8::Object::New(isolate);
255 Dictionary timingInputDictionaryNoDuration = Dictionary(v8::Handle<v8::Value>::Cast(timingInputNoDuration), isolate);
257 RefPtr<Animation> animationNoDuration = createAnimation(element.get(), jsKeyframes, timingInputDictionaryNoDuration);
259 RefPtr<TimedItemTiming> specifiedNoDuration = animationNoDuration->specified();
261 numberDuration = std::numeric_limits<double>::quiet_NaN();
264 specifiedNoDuration->getDuration("duration", isNumber, numberDuration, isString, stringDuration);
265 EXPECT_FALSE(isNumber);
266 EXPECT_TRUE(std::isnan(numberDuration));
267 EXPECT_TRUE(isString);
268 EXPECT_EQ("auto", stringDuration);
271 TEST_F(AnimationAnimationTest, SpecifiedSetters)
273 v8::Isolate* isolate = v8::Isolate::GetCurrent();
274 v8::HandleScope scope(isolate);
275 v8::Local<v8::Context> context = v8::Context::New(isolate);
276 v8::Context::Scope contextScope(context);
278 Vector<Dictionary, 0> jsKeyframes;
279 v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
280 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
281 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, timingInputDictionary);
283 RefPtr<TimedItemTiming> specified = animation->specified();
285 EXPECT_EQ(0, specified->delay());
286 specified->setDelay(2);
287 EXPECT_EQ(2, specified->delay());
289 EXPECT_EQ(0, specified->endDelay());
290 specified->setEndDelay(0.5);
291 EXPECT_EQ(0.5, specified->endDelay());
293 EXPECT_EQ("auto", specified->fill());
294 specified->setFill("backwards");
295 EXPECT_EQ("backwards", specified->fill());
297 EXPECT_EQ(0, specified->iterationStart());
298 specified->setIterationStart(2);
299 EXPECT_EQ(2, specified->iterationStart());
301 EXPECT_EQ(1, specified->iterations());
302 specified->setIterations(10);
303 EXPECT_EQ(10, specified->iterations());
305 EXPECT_EQ(1, specified->playbackRate());
306 specified->setPlaybackRate(2);
307 EXPECT_EQ(2, specified->playbackRate());
309 EXPECT_EQ("normal", specified->direction());
310 specified->setDirection("reverse");
311 EXPECT_EQ("reverse", specified->direction());
313 EXPECT_EQ("linear", specified->easing());
314 specified->setEasing("step-start");
315 EXPECT_EQ("step-start", specified->easing());
318 TEST_F(AnimationAnimationTest, SetSpecifiedDuration)
320 v8::Isolate* isolate = v8::Isolate::GetCurrent();
321 v8::HandleScope scope(isolate);
322 v8::Local<v8::Context> context = v8::Context::New(isolate);
323 v8::Context::Scope contextScope(context);
325 Vector<Dictionary, 0> jsKeyframes;
326 v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
327 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
328 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, timingInputDictionary);
330 RefPtr<TimedItemTiming> specified = animation->specified();
332 bool isNumber = false;
333 double numberDuration = std::numeric_limits<double>::quiet_NaN();
334 bool isString = false;
335 String stringDuration = "";
336 specified->getDuration("duration", isNumber, numberDuration, isString, stringDuration);
337 EXPECT_FALSE(isNumber);
338 EXPECT_TRUE(std::isnan(numberDuration));
339 EXPECT_TRUE(isString);
340 EXPECT_EQ("auto", stringDuration);
342 specified->setDuration("duration", 2.5);
344 numberDuration = std::numeric_limits<double>::quiet_NaN();
347 specified->getDuration("duration", isNumber, numberDuration, isString, stringDuration);
348 EXPECT_TRUE(isNumber);
349 EXPECT_EQ(2.5, numberDuration);
350 EXPECT_FALSE(isString);
351 EXPECT_EQ("", stringDuration);
354 TEST_F(AnimationAnimationTest, TimingInputStartDelay)
356 v8::Isolate* isolate = v8::Isolate::GetCurrent();
357 v8::HandleScope scope(isolate);
358 v8::Local<v8::Context> context = v8::Context::New(isolate);
359 v8::Context::Scope contextScope(context);
362 EXPECT_EQ(0, timing.startDelay);
364 applyTimingInputNumber(timing, isolate, "delay", 1.1);
365 EXPECT_EQ(1.1, timing.startDelay);
366 timing.startDelay = 0;
368 applyTimingInputNumber(timing, isolate, "delay", -1);
369 EXPECT_EQ(-1, timing.startDelay);
370 timing.startDelay = 0;
372 applyTimingInputString(timing, isolate, "delay", "1");
373 EXPECT_EQ(1, timing.startDelay);
374 timing.startDelay = 0;
376 applyTimingInputString(timing, isolate, "delay", "1s");
377 EXPECT_EQ(0, timing.startDelay);
378 timing.startDelay = 0;
380 applyTimingInputString(timing, isolate, "delay", "Infinity");
381 EXPECT_EQ(0, timing.startDelay);
382 timing.startDelay = 0;
384 applyTimingInputString(timing, isolate, "delay", "-Infinity");
385 EXPECT_EQ(0, timing.startDelay);
386 timing.startDelay = 0;
388 applyTimingInputString(timing, isolate, "delay", "NaN");
389 EXPECT_EQ(0, timing.startDelay);
390 timing.startDelay = 0;
392 applyTimingInputString(timing, isolate, "delay", "rubbish");
393 EXPECT_EQ(0, timing.startDelay);
394 timing.startDelay = 0;
397 TEST_F(AnimationAnimationTest, TimingInputEndDelay)
399 v8::Isolate* isolate = v8::Isolate::GetCurrent();
400 v8::HandleScope scope(isolate);
401 v8::Local<v8::Context> context = v8::Context::New(isolate);
402 v8::Context::Scope contextScope(context);
405 applyTimingInputNumber(timing, isolate, "endDelay", 10);
406 EXPECT_EQ(10, timing.endDelay);
407 applyTimingInputNumber(timing, isolate, "endDelay", -2.5);
408 EXPECT_EQ(-2.5, timing.endDelay);
411 TEST_F(AnimationAnimationTest, TimingInputFillMode)
413 v8::Isolate* isolate = v8::Isolate::GetCurrent();
414 v8::HandleScope scope(isolate);
415 v8::Local<v8::Context> context = v8::Context::New(isolate);
416 v8::Context::Scope contextScope(context);
419 Timing::FillMode defaultFillMode = Timing::FillModeAuto;
420 EXPECT_EQ(defaultFillMode, timing.fillMode);
422 applyTimingInputString(timing, isolate, "fill", "auto");
423 EXPECT_EQ(Timing::FillModeAuto, timing.fillMode);
424 timing.fillMode = defaultFillMode;
426 applyTimingInputString(timing, isolate, "fill", "forwards");
427 EXPECT_EQ(Timing::FillModeForwards, timing.fillMode);
428 timing.fillMode = defaultFillMode;
430 applyTimingInputString(timing, isolate, "fill", "none");
431 EXPECT_EQ(Timing::FillModeNone, timing.fillMode);
432 timing.fillMode = defaultFillMode;
434 applyTimingInputString(timing, isolate, "fill", "backwards");
435 EXPECT_EQ(Timing::FillModeBackwards, timing.fillMode);
436 timing.fillMode = defaultFillMode;
438 applyTimingInputString(timing, isolate, "fill", "both");
439 EXPECT_EQ(Timing::FillModeBoth, timing.fillMode);
440 timing.fillMode = defaultFillMode;
442 applyTimingInputString(timing, isolate, "fill", "everything!");
443 EXPECT_EQ(defaultFillMode, timing.fillMode);
444 timing.fillMode = defaultFillMode;
446 applyTimingInputString(timing, isolate, "fill", "backwardsandforwards");
447 EXPECT_EQ(defaultFillMode, timing.fillMode);
448 timing.fillMode = defaultFillMode;
450 applyTimingInputNumber(timing, isolate, "fill", 2);
451 EXPECT_EQ(defaultFillMode, timing.fillMode);
452 timing.fillMode = defaultFillMode;
455 TEST_F(AnimationAnimationTest, TimingInputIterationStart)
457 v8::Isolate* isolate = v8::Isolate::GetCurrent();
458 v8::HandleScope scope(isolate);
459 v8::Local<v8::Context> context = v8::Context::New(isolate);
460 v8::Context::Scope contextScope(context);
463 EXPECT_EQ(0, timing.iterationStart);
465 applyTimingInputNumber(timing, isolate, "iterationStart", 1.1);
466 EXPECT_EQ(1.1, timing.iterationStart);
467 timing.iterationStart = 0;
469 applyTimingInputNumber(timing, isolate, "iterationStart", -1);
470 EXPECT_EQ(0, timing.iterationStart);
471 timing.iterationStart = 0;
473 applyTimingInputString(timing, isolate, "iterationStart", "Infinity");
474 EXPECT_EQ(0, timing.iterationStart);
475 timing.iterationStart = 0;
477 applyTimingInputString(timing, isolate, "iterationStart", "-Infinity");
478 EXPECT_EQ(0, timing.iterationStart);
479 timing.iterationStart = 0;
481 applyTimingInputString(timing, isolate, "iterationStart", "NaN");
482 EXPECT_EQ(0, timing.iterationStart);
483 timing.iterationStart = 0;
485 applyTimingInputString(timing, isolate, "iterationStart", "rubbish");
486 EXPECT_EQ(0, timing.iterationStart);
487 timing.iterationStart = 0;
490 TEST_F(AnimationAnimationTest, TimingInputIterationCount)
492 v8::Isolate* isolate = v8::Isolate::GetCurrent();
493 v8::HandleScope scope(isolate);
494 v8::Local<v8::Context> context = v8::Context::New(isolate);
495 v8::Context::Scope contextScope(context);
498 EXPECT_EQ(1, timing.iterationCount);
500 applyTimingInputNumber(timing, isolate, "iterations", 2.1);
501 EXPECT_EQ(2.1, timing.iterationCount);
502 timing.iterationCount = 1;
504 applyTimingInputNumber(timing, isolate, "iterations", -1);
505 EXPECT_EQ(0, timing.iterationCount);
506 timing.iterationCount = 1;
508 applyTimingInputString(timing, isolate, "iterations", "Infinity");
509 EXPECT_TRUE(std::isinf(timing.iterationCount) && (timing.iterationCount > 0));
510 timing.iterationCount = 1;
512 applyTimingInputString(timing, isolate, "iterations", "-Infinity");
513 EXPECT_EQ(0, timing.iterationCount);
514 timing.iterationCount = 1;
516 applyTimingInputString(timing, isolate, "iterations", "NaN");
517 EXPECT_EQ(1, timing.iterationCount);
518 timing.iterationCount = 1;
520 applyTimingInputString(timing, isolate, "iterations", "rubbish");
521 EXPECT_EQ(1, timing.iterationCount);
522 timing.iterationCount = 1;
525 TEST_F(AnimationAnimationTest, TimingInputIterationDuration)
527 v8::Isolate* isolate = v8::Isolate::GetCurrent();
528 v8::HandleScope scope(isolate);
529 v8::Local<v8::Context> context = v8::Context::New(isolate);
530 v8::Context::Scope contextScope(context);
533 EXPECT_TRUE(std::isnan(timing.iterationDuration));
535 applyTimingInputNumber(timing, isolate, "duration", 1.1);
536 EXPECT_EQ(1.1, timing.iterationDuration);
537 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
539 applyTimingInputNumber(timing, isolate, "duration", -1);
540 EXPECT_TRUE(std::isnan(timing.iterationDuration));
541 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
543 applyTimingInputString(timing, isolate, "duration", "1");
544 EXPECT_EQ(1, timing.iterationDuration);
545 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
547 applyTimingInputString(timing, isolate, "duration", "Infinity");
548 EXPECT_TRUE(std::isinf(timing.iterationDuration) && (timing.iterationDuration > 0));
549 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
551 applyTimingInputString(timing, isolate, "duration", "-Infinity");
552 EXPECT_TRUE(std::isnan(timing.iterationDuration));
553 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
555 applyTimingInputString(timing, isolate, "duration", "NaN");
556 EXPECT_TRUE(std::isnan(timing.iterationDuration));
557 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
559 applyTimingInputString(timing, isolate, "duration", "auto");
560 EXPECT_TRUE(std::isnan(timing.iterationDuration));
561 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
563 applyTimingInputString(timing, isolate, "duration", "rubbish");
564 EXPECT_TRUE(std::isnan(timing.iterationDuration));
565 timing.iterationDuration = std::numeric_limits<double>::quiet_NaN();
568 TEST_F(AnimationAnimationTest, TimingInputPlaybackRate)
570 v8::Isolate* isolate = v8::Isolate::GetCurrent();
571 v8::HandleScope scope(isolate);
572 v8::Local<v8::Context> context = v8::Context::New(isolate);
573 v8::Context::Scope contextScope(context);
576 EXPECT_EQ(1, timing.playbackRate);
578 applyTimingInputNumber(timing, isolate, "playbackRate", 2.1);
579 EXPECT_EQ(2.1, timing.playbackRate);
580 timing.playbackRate = 1;
582 applyTimingInputNumber(timing, isolate, "playbackRate", -1);
583 EXPECT_EQ(-1, timing.playbackRate);
584 timing.playbackRate = 1;
586 applyTimingInputString(timing, isolate, "playbackRate", "Infinity");
587 EXPECT_EQ(1, timing.playbackRate);
588 timing.playbackRate = 1;
590 applyTimingInputString(timing, isolate, "playbackRate", "-Infinity");
591 EXPECT_EQ(1, timing.playbackRate);
592 timing.playbackRate = 1;
594 applyTimingInputString(timing, isolate, "playbackRate", "NaN");
595 EXPECT_EQ(1, timing.playbackRate);
596 timing.playbackRate = 1;
598 applyTimingInputString(timing, isolate, "playbackRate", "rubbish");
599 EXPECT_EQ(1, timing.playbackRate);
600 timing.playbackRate = 1;
603 TEST_F(AnimationAnimationTest, TimingInputDirection)
605 v8::Isolate* isolate = v8::Isolate::GetCurrent();
606 v8::HandleScope scope(isolate);
607 v8::Local<v8::Context> context = v8::Context::New(isolate);
608 v8::Context::Scope contextScope(context);
611 Timing::PlaybackDirection defaultPlaybackDirection = Timing::PlaybackDirectionNormal;
612 EXPECT_EQ(defaultPlaybackDirection, timing.direction);
614 applyTimingInputString(timing, isolate, "direction", "normal");
615 EXPECT_EQ(Timing::PlaybackDirectionNormal, timing.direction);
616 timing.direction = defaultPlaybackDirection;
618 applyTimingInputString(timing, isolate, "direction", "reverse");
619 EXPECT_EQ(Timing::PlaybackDirectionReverse, timing.direction);
620 timing.direction = defaultPlaybackDirection;
622 applyTimingInputString(timing, isolate, "direction", "alternate");
623 EXPECT_EQ(Timing::PlaybackDirectionAlternate, timing.direction);
624 timing.direction = defaultPlaybackDirection;
626 applyTimingInputString(timing, isolate, "direction", "alternate-reverse");
627 EXPECT_EQ(Timing::PlaybackDirectionAlternateReverse, timing.direction);
628 timing.direction = defaultPlaybackDirection;
630 applyTimingInputString(timing, isolate, "direction", "rubbish");
631 EXPECT_EQ(defaultPlaybackDirection, timing.direction);
632 timing.direction = defaultPlaybackDirection;
634 applyTimingInputNumber(timing, isolate, "direction", 2);
635 EXPECT_EQ(defaultPlaybackDirection, timing.direction);
636 timing.direction = defaultPlaybackDirection;
639 TEST_F(AnimationAnimationTest, TimingInputTimingFunction)
641 v8::Isolate* isolate = v8::Isolate::GetCurrent();
642 v8::HandleScope scope(isolate);
643 v8::Local<v8::Context> context = v8::Context::New(isolate);
644 v8::Context::Scope contextScope(context);
647 const RefPtr<TimingFunction> defaultTimingFunction = LinearTimingFunction::create();
648 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
650 applyTimingInputString(timing, isolate, "easing", "ease");
651 EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease)), *timing.timingFunction.get());
652 timing.timingFunction = defaultTimingFunction;
654 applyTimingInputString(timing, isolate, "easing", "ease-in");
655 EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn)), *timing.timingFunction.get());
656 timing.timingFunction = defaultTimingFunction;
658 applyTimingInputString(timing, isolate, "easing", "ease-out");
659 EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut)), *timing.timingFunction.get());
660 timing.timingFunction = defaultTimingFunction;
662 applyTimingInputString(timing, isolate, "easing", "ease-in-out");
663 EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut)), *timing.timingFunction.get());
664 timing.timingFunction = defaultTimingFunction;
666 applyTimingInputString(timing, isolate, "easing", "linear");
667 EXPECT_EQ(*(LinearTimingFunction::create()), *timing.timingFunction.get());
668 timing.timingFunction = defaultTimingFunction;
670 applyTimingInputString(timing, isolate, "easing", "initial");
671 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
672 timing.timingFunction = defaultTimingFunction;
674 applyTimingInputString(timing, isolate, "easing", "step-start");
675 EXPECT_EQ(*(StepsTimingFunction::preset(StepsTimingFunction::Start)), *timing.timingFunction.get());
676 timing.timingFunction = defaultTimingFunction;
678 applyTimingInputString(timing, isolate, "easing", "step-end");
679 EXPECT_EQ(*(StepsTimingFunction::preset(StepsTimingFunction::End)), *timing.timingFunction.get());
680 timing.timingFunction = defaultTimingFunction;
682 applyTimingInputString(timing, isolate, "easing", "cubic-bezier(1, 1, 0.3, 0.3)");
683 EXPECT_EQ(*(CubicBezierTimingFunction::create(1, 1, 0.3, 0.3).get()), *timing.timingFunction.get());
684 timing.timingFunction = defaultTimingFunction;
686 applyTimingInputString(timing, isolate, "easing", "steps(3, start)");
687 EXPECT_EQ(*(StepsTimingFunction::create(3, true).get()), *timing.timingFunction.get());
688 timing.timingFunction = defaultTimingFunction;
690 applyTimingInputString(timing, isolate, "easing", "steps(5, end)");
691 EXPECT_EQ(*(StepsTimingFunction::create(5, false).get()), *timing.timingFunction.get());
692 timing.timingFunction = defaultTimingFunction;
694 applyTimingInputString(timing, isolate, "easing", "steps(5.6, end)");
695 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
696 timing.timingFunction = defaultTimingFunction;
698 // FIXME: Step-middle not yet implemented. Change this test when it is working.
699 applyTimingInputString(timing, isolate, "easing", "steps(5, middle)");
700 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
701 timing.timingFunction = defaultTimingFunction;
703 applyTimingInputString(timing, isolate, "easing", "cubic-bezier(2, 2, 0.3, 0.3)");
704 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
705 timing.timingFunction = defaultTimingFunction;
707 applyTimingInputString(timing, isolate, "easing", "rubbish");
708 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
709 timing.timingFunction = defaultTimingFunction;
711 applyTimingInputNumber(timing, isolate, "easing", 2);
712 EXPECT_EQ(*defaultTimingFunction.get(), *timing.timingFunction.get());
713 timing.timingFunction = defaultTimingFunction;
716 TEST_F(AnimationAnimationTest, TimingInputEmpty)
718 v8::Isolate* isolate = v8::Isolate::GetCurrent();
719 v8::HandleScope scope(isolate);
720 v8::Local<v8::Context> context = v8::Context::New(isolate);
721 v8::Context::Scope contextScope(context);
723 Timing updatedTiming;
724 Timing controlTiming;
726 v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
727 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
728 populateTiming(updatedTiming, timingInputDictionary);
730 EXPECT_EQ(controlTiming.startDelay, updatedTiming.startDelay);
731 EXPECT_EQ(controlTiming.fillMode, updatedTiming.fillMode);
732 EXPECT_EQ(controlTiming.iterationStart, updatedTiming.iterationStart);
733 EXPECT_EQ(controlTiming.iterationCount, updatedTiming.iterationCount);
734 EXPECT_TRUE(std::isnan(updatedTiming.iterationDuration));
735 EXPECT_EQ(controlTiming.playbackRate, updatedTiming.playbackRate);
736 EXPECT_EQ(controlTiming.direction, updatedTiming.direction);
737 EXPECT_EQ(*controlTiming.timingFunction.get(), *updatedTiming.timingFunction.get());
740 TEST_F(AnimationAnimationTest, TimeToEffectChange)
743 timing.iterationDuration = 100;
744 timing.startDelay = 100;
745 timing.endDelay = 100;
746 timing.fillMode = Timing::FillModeNone;
747 RefPtr<Animation> animation = Animation::create(0, 0, timing);
748 RefPtr<Player> player = document->timeline()->play(animation.get());
749 double inf = std::numeric_limits<double>::infinity();
751 EXPECT_EQ(100, animation->timeToForwardsEffectChange());
752 EXPECT_EQ(inf, animation->timeToReverseEffectChange());
754 player->setCurrentTime(100);
755 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
756 EXPECT_EQ(0, animation->timeToReverseEffectChange());
758 player->setCurrentTime(199);
759 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
760 EXPECT_EQ(0, animation->timeToReverseEffectChange());
762 player->setCurrentTime(200);
764 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
765 EXPECT_EQ(0, animation->timeToReverseEffectChange());
767 player->setCurrentTime(300);
768 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
769 EXPECT_EQ(100, animation->timeToReverseEffectChange());
772 TEST_F(AnimationAnimationTest, TimeToEffectChangeWithPlaybackRate)
775 timing.iterationDuration = 100;
776 timing.startDelay = 100;
777 timing.endDelay = 100;
778 timing.playbackRate = 2;
779 timing.fillMode = Timing::FillModeNone;
780 RefPtr<Animation> animation = Animation::create(0, 0, timing);
781 RefPtr<Player> player = document->timeline()->play(animation.get());
782 double inf = std::numeric_limits<double>::infinity();
784 EXPECT_EQ(100, animation->timeToForwardsEffectChange());
785 EXPECT_EQ(inf, animation->timeToReverseEffectChange());
787 player->setCurrentTime(100);
788 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
789 EXPECT_EQ(0, animation->timeToReverseEffectChange());
791 player->setCurrentTime(149);
792 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
793 EXPECT_EQ(0, animation->timeToReverseEffectChange());
795 player->setCurrentTime(150);
797 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
798 EXPECT_EQ(0, animation->timeToReverseEffectChange());
800 player->setCurrentTime(200);
801 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
802 EXPECT_EQ(50, animation->timeToReverseEffectChange());
805 TEST_F(AnimationAnimationTest, TimeToEffectChangeWithNegativePlaybackRate)
808 timing.iterationDuration = 100;
809 timing.startDelay = 100;
810 timing.endDelay = 100;
811 timing.playbackRate = -2;
812 timing.fillMode = Timing::FillModeNone;
813 RefPtr<Animation> animation = Animation::create(0, 0, timing);
814 RefPtr<Player> player = document->timeline()->play(animation.get());
815 double inf = std::numeric_limits<double>::infinity();
817 EXPECT_EQ(100, animation->timeToForwardsEffectChange());
818 EXPECT_EQ(inf, animation->timeToReverseEffectChange());
820 player->setCurrentTime(100);
821 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
822 EXPECT_EQ(0, animation->timeToReverseEffectChange());
824 player->setCurrentTime(149);
825 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
826 EXPECT_EQ(0, animation->timeToReverseEffectChange());
828 player->setCurrentTime(150);
829 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
830 EXPECT_EQ(0, animation->timeToReverseEffectChange());
832 player->setCurrentTime(200);
833 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
834 EXPECT_EQ(50, animation->timeToReverseEffectChange());
837 } // namespace WebCore