Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1163)

Side by Side Diff: sky/engine/core/animation/AnimationTest.cpp

Issue 922893002: Merge the Sky Engine changes from the SkyDart branch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "sky/engine/config.h"
6 #include "sky/engine/core/animation/Animation.h"
7
8 #include <gtest/gtest.h>
9
10 #include "core/testing/DummyPageHolder.h"
11 #include "sky/engine/bindings/core/v8/Dictionary.h"
12 #include "sky/engine/bindings/core/v8/Nullable.h"
13 #include "sky/engine/core/animation/AnimationClock.h"
14 #include "sky/engine/core/animation/AnimationHelpers.h"
15 #include "sky/engine/core/animation/AnimationNodeTiming.h"
16 #include "sky/engine/core/animation/AnimationTestHelper.h"
17 #include "sky/engine/core/animation/AnimationTimeline.h"
18 #include "sky/engine/core/animation/KeyframeEffectModel.h"
19 #include "sky/engine/core/animation/Timing.h"
20 #include "sky/engine/core/dom/Document.h"
21 #include "v8/include/v8.h"
22
23 namespace blink {
24
25 class AnimationAnimationTest : public ::testing::Test {
26 protected:
27 AnimationAnimationTest()
28 : pageHolder(DummyPageHolder::create())
29 , document(pageHolder->document())
30 , element(document.createElement("foo", ASSERT_NO_EXCEPTION))
31 {
32 document.animationClock().resetTimeForTesting();
33 EXPECT_EQ(0, document.timeline().currentTime());
34 }
35
36 OwnPtr<DummyPageHolder> pageHolder;
37 Document& document;
38 RefPtr<Element> element;
39 TrackExceptionState exceptionState;
40 };
41
42 class AnimationAnimationV8Test : public AnimationAnimationTest {
43 protected:
44 AnimationAnimationV8Test()
45 : m_isolate(v8::Isolate::GetCurrent())
46 , m_scope(m_isolate)
47 {
48 }
49
50 template<typename T>
51 static PassRefPtr<Animation> createAnimation(Element* element, Vector<Dictio nary> keyframeDictionaryVector, T timingInput, ExceptionState& exceptionState)
52 {
53 return Animation::create(element, EffectInput::convert(element, keyframe DictionaryVector, exceptionState), timingInput);
54 }
55 static PassRefPtr<Animation> createAnimation(Element* element, Vector<Dictio nary> keyframeDictionaryVector, ExceptionState& exceptionState)
56 {
57 return Animation::create(element, EffectInput::convert(element, keyframe DictionaryVector, exceptionState));
58 }
59
60 v8::Isolate* m_isolate;
61
62 private:
63 V8TestingScope m_scope;
64 };
65
66 TEST_F(AnimationAnimationV8Test, CanCreateAnAnimation)
67 {
68 Vector<Dictionary> jsKeyframes;
69 v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate);
70 v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate);
71
72 setV8ObjectPropertyAsString(keyframe1, "width", "100px");
73 setV8ObjectPropertyAsString(keyframe1, "offset", "0");
74 setV8ObjectPropertyAsString(keyframe1, "easing", "ease-in-out");
75 setV8ObjectPropertyAsString(keyframe2, "width", "0px");
76 setV8ObjectPropertyAsString(keyframe2, "offset", "1");
77 setV8ObjectPropertyAsString(keyframe2, "easing", "cubic-bezier(1, 1, 0.3, 0. 3)");
78
79 jsKeyframes.append(Dictionary(keyframe1, m_isolate));
80 jsKeyframes.append(Dictionary(keyframe2, m_isolate));
81
82 String value1;
83 ASSERT_TRUE(DictionaryHelper::get(jsKeyframes[0], "width", value1));
84 ASSERT_EQ("100px", value1);
85
86 String value2;
87 ASSERT_TRUE(DictionaryHelper::get(jsKeyframes[1], "width", value2));
88 ASSERT_EQ("0px", value2);
89
90 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, 0, exceptionState);
91
92 Element* target = animation->target();
93 EXPECT_EQ(*element.get(), *target);
94
95 const KeyframeVector keyframes = toKeyframeEffectModelBase(animation->effect ())->getFrames();
96
97 EXPECT_EQ(0, keyframes[0]->offset());
98 EXPECT_EQ(1, keyframes[1]->offset());
99
100 const CSSValue* keyframe1Width = toStringKeyframe(keyframes[0].get())->prope rtyValue(CSSPropertyWidth);
101 const CSSValue* keyframe2Width = toStringKeyframe(keyframes[1].get())->prope rtyValue(CSSPropertyWidth);
102 ASSERT(keyframe1Width);
103 ASSERT(keyframe2Width);
104
105 EXPECT_EQ("100px", keyframe1Width->cssText());
106 EXPECT_EQ("0px", keyframe2Width->cssText());
107
108 EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Eas eInOut)), keyframes[0]->easing());
109 EXPECT_EQ(*(CubicBezierTimingFunction::create(1, 1, 0.3, 0.3).get()), keyfra mes[1]->easing());
110 }
111
112 TEST_F(AnimationAnimationV8Test, CanSetDuration)
113 {
114 Vector<Dictionary, 0> jsKeyframes;
115 double duration = 2000;
116
117 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, du ration, exceptionState);
118
119 EXPECT_EQ(duration / 1000, animation->specifiedTiming().iterationDuration);
120 }
121
122 TEST_F(AnimationAnimationV8Test, CanOmitSpecifiedDuration)
123 {
124 Vector<Dictionary, 0> jsKeyframes;
125 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, ex ceptionState);
126 EXPECT_TRUE(std::isnan(animation->specifiedTiming().iterationDuration));
127 }
128
129 TEST_F(AnimationAnimationV8Test, NegativeDurationIsAuto)
130 {
131 Vector<Dictionary, 0> jsKeyframes;
132 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, -2 , exceptionState);
133 EXPECT_TRUE(std::isnan(animation->specifiedTiming().iterationDuration));
134 }
135
136 TEST_F(AnimationAnimationV8Test, MismatchedKeyframePropertyRaisesException)
137 {
138 Vector<Dictionary> jsKeyframes;
139 v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate);
140 v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate);
141
142 setV8ObjectPropertyAsString(keyframe1, "width", "100px");
143 setV8ObjectPropertyAsString(keyframe1, "offset", "0");
144
145 // Height property appears only in keyframe2
146 setV8ObjectPropertyAsString(keyframe2, "height", "100px");
147 setV8ObjectPropertyAsString(keyframe2, "width", "0px");
148 setV8ObjectPropertyAsString(keyframe2, "offset", "1");
149
150 jsKeyframes.append(Dictionary(keyframe1, m_isolate));
151 jsKeyframes.append(Dictionary(keyframe2, m_isolate));
152
153 createAnimation(element.get(), jsKeyframes, 0, exceptionState);
154
155 EXPECT_TRUE(exceptionState.hadException());
156 EXPECT_EQ(NotSupportedError, exceptionState.code());
157 }
158
159 TEST_F(AnimationAnimationV8Test, MissingOffsetZeroRaisesException)
160 {
161 Vector<Dictionary> jsKeyframes;
162 v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate);
163 v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate);
164
165 setV8ObjectPropertyAsString(keyframe1, "width", "100px");
166 setV8ObjectPropertyAsString(keyframe1, "offset", "0.1");
167 setV8ObjectPropertyAsString(keyframe2, "width", "0px");
168 setV8ObjectPropertyAsString(keyframe2, "offset", "1");
169
170 jsKeyframes.append(Dictionary(keyframe1, m_isolate));
171 jsKeyframes.append(Dictionary(keyframe2, m_isolate));
172
173 createAnimation(element.get(), jsKeyframes, 0, exceptionState);
174
175 EXPECT_TRUE(exceptionState.hadException());
176 EXPECT_EQ(NotSupportedError, exceptionState.code());
177 }
178
179 TEST_F(AnimationAnimationV8Test, MissingOffsetOneRaisesException)
180 {
181 Vector<Dictionary> jsKeyframes;
182 v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate);
183 v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate);
184
185 setV8ObjectPropertyAsString(keyframe1, "width", "100px");
186 setV8ObjectPropertyAsString(keyframe1, "offset", "0");
187 setV8ObjectPropertyAsString(keyframe2, "width", "0px");
188 setV8ObjectPropertyAsString(keyframe2, "offset", "0.1");
189
190 jsKeyframes.append(Dictionary(keyframe1, m_isolate));
191 jsKeyframes.append(Dictionary(keyframe2, m_isolate));
192
193 createAnimation(element.get(), jsKeyframes, 0, exceptionState);
194
195 EXPECT_TRUE(exceptionState.hadException());
196 EXPECT_EQ(NotSupportedError, exceptionState.code());
197 }
198
199 TEST_F(AnimationAnimationV8Test, MissingOffsetZeroAndOneRaisesException)
200 {
201 Vector<Dictionary> jsKeyframes;
202 v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate);
203 v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate);
204
205 setV8ObjectPropertyAsString(keyframe1, "width", "100px");
206 setV8ObjectPropertyAsString(keyframe1, "offset", "0.1");
207 setV8ObjectPropertyAsString(keyframe2, "width", "0px");
208 setV8ObjectPropertyAsString(keyframe2, "offset", "0.2");
209
210 jsKeyframes.append(Dictionary(keyframe1, m_isolate));
211 jsKeyframes.append(Dictionary(keyframe2, m_isolate));
212
213 createAnimation(element.get(), jsKeyframes, 0, exceptionState);
214
215 EXPECT_TRUE(exceptionState.hadException());
216 EXPECT_EQ(NotSupportedError, exceptionState.code());
217 }
218
219 TEST_F(AnimationAnimationV8Test, SpecifiedGetters)
220 {
221 Vector<Dictionary, 0> jsKeyframes;
222
223 v8::Handle<v8::Object> timingInput = v8::Object::New(m_isolate);
224 setV8ObjectPropertyAsNumber(timingInput, "delay", 2);
225 setV8ObjectPropertyAsNumber(timingInput, "endDelay", 0.5);
226 setV8ObjectPropertyAsString(timingInput, "fill", "backwards");
227 setV8ObjectPropertyAsNumber(timingInput, "iterationStart", 2);
228 setV8ObjectPropertyAsNumber(timingInput, "iterations", 10);
229 setV8ObjectPropertyAsNumber(timingInput, "playbackRate", 2);
230 setV8ObjectPropertyAsString(timingInput, "direction", "reverse");
231 setV8ObjectPropertyAsString(timingInput, "easing", "step-start");
232 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(ti mingInput), m_isolate);
233
234 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, ti mingInputDictionary, exceptionState);
235
236 RefPtr<AnimationNodeTiming> specified = animation->timing();
237 EXPECT_EQ(2, specified->delay());
238 EXPECT_EQ(0.5, specified->endDelay());
239 EXPECT_EQ("backwards", specified->fill());
240 EXPECT_EQ(2, specified->iterationStart());
241 EXPECT_EQ(10, specified->iterations());
242 EXPECT_EQ(2, specified->playbackRate());
243 EXPECT_EQ("reverse", specified->direction());
244 EXPECT_EQ("step-start", specified->easing());
245 }
246
247 TEST_F(AnimationAnimationV8Test, SpecifiedDurationGetter)
248 {
249 Vector<Dictionary, 0> jsKeyframes;
250
251 v8::Handle<v8::Object> timingInputWithDuration = v8::Object::New(m_isolate);
252 setV8ObjectPropertyAsNumber(timingInputWithDuration, "duration", 2.5);
253 Dictionary timingInputDictionaryWithDuration = Dictionary(v8::Handle<v8::Val ue>::Cast(timingInputWithDuration), m_isolate);
254
255 RefPtr<Animation> animationWithDuration = createAnimation(element.get(), jsK eyframes, timingInputDictionaryWithDuration, exceptionState);
256
257 RefPtr<AnimationNodeTiming> specifiedWithDuration = animationWithDuration->t iming();
258 Nullable<double> numberDuration;
259 String stringDuration;
260 specifiedWithDuration->getDuration("duration", numberDuration, stringDuratio n);
261 EXPECT_FALSE(numberDuration.isNull());
262 EXPECT_EQ(2.5, numberDuration.get());
263 EXPECT_TRUE(stringDuration.isNull());
264
265
266 v8::Handle<v8::Object> timingInputNoDuration = v8::Object::New(m_isolate);
267 Dictionary timingInputDictionaryNoDuration = Dictionary(v8::Handle<v8::Value >::Cast(timingInputNoDuration), m_isolate);
268
269 RefPtr<Animation> animationNoDuration = createAnimation(element.get(), jsKey frames, timingInputDictionaryNoDuration, exceptionState);
270
271 RefPtr<AnimationNodeTiming> specifiedNoDuration = animationNoDuration->timin g();
272 Nullable<double> numberDuration2;
273 String stringDuration2;
274 specifiedNoDuration->getDuration("duration", numberDuration2, stringDuration 2);
275 EXPECT_TRUE(numberDuration2.isNull());
276 EXPECT_FALSE(stringDuration2.isNull());
277 EXPECT_EQ("auto", stringDuration2);
278 }
279
280 TEST_F(AnimationAnimationV8Test, SpecifiedSetters)
281 {
282 Vector<Dictionary, 0> jsKeyframes;
283 v8::Handle<v8::Object> timingInput = v8::Object::New(m_isolate);
284 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(ti mingInput), m_isolate);
285 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, ti mingInputDictionary, exceptionState);
286
287 RefPtr<AnimationNodeTiming> specified = animation->timing();
288
289 EXPECT_EQ(0, specified->delay());
290 specified->setDelay(2);
291 EXPECT_EQ(2, specified->delay());
292
293 EXPECT_EQ(0, specified->endDelay());
294 specified->setEndDelay(0.5);
295 EXPECT_EQ(0.5, specified->endDelay());
296
297 EXPECT_EQ("auto", specified->fill());
298 specified->setFill("backwards");
299 EXPECT_EQ("backwards", specified->fill());
300
301 EXPECT_EQ(0, specified->iterationStart());
302 specified->setIterationStart(2);
303 EXPECT_EQ(2, specified->iterationStart());
304
305 EXPECT_EQ(1, specified->iterations());
306 specified->setIterations(10);
307 EXPECT_EQ(10, specified->iterations());
308
309 EXPECT_EQ(1, specified->playbackRate());
310 specified->setPlaybackRate(2);
311 EXPECT_EQ(2, specified->playbackRate());
312
313 EXPECT_EQ("normal", specified->direction());
314 specified->setDirection("reverse");
315 EXPECT_EQ("reverse", specified->direction());
316
317 EXPECT_EQ("linear", specified->easing());
318 specified->setEasing("step-start");
319 EXPECT_EQ("step-start", specified->easing());
320 }
321
322 TEST_F(AnimationAnimationV8Test, SetSpecifiedDuration)
323 {
324 Vector<Dictionary, 0> jsKeyframes;
325 v8::Handle<v8::Object> timingInput = v8::Object::New(m_isolate);
326 Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(ti mingInput), m_isolate);
327 RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, ti mingInputDictionary, exceptionState);
328
329 RefPtr<AnimationNodeTiming> specified = animation->timing();
330
331 Nullable<double> numberDuration;
332 String stringDuration;
333 specified->getDuration("duration", numberDuration, stringDuration);
334 EXPECT_TRUE(numberDuration.isNull());
335 EXPECT_FALSE(stringDuration.isNull());
336 EXPECT_EQ("auto", stringDuration);
337
338 specified->setDuration("duration", 2.5);
339 Nullable<double> numberDuration2;
340 String stringDuration2;
341 specified->getDuration("duration", numberDuration2, stringDuration2);
342 EXPECT_FALSE(numberDuration2.isNull());
343 EXPECT_EQ(2.5, numberDuration2.get());
344 EXPECT_TRUE(stringDuration2.isNull());
345 }
346
347 TEST_F(AnimationAnimationTest, TimeToEffectChange)
348 {
349 Timing timing;
350 timing.iterationDuration = 100;
351 timing.startDelay = 100;
352 timing.endDelay = 100;
353 timing.fillMode = Timing::FillModeNone;
354 RefPtr<Animation> animation = Animation::create(0, nullptr, timing);
355 RefPtr<AnimationPlayer> player = document.timeline().play(animation.get());
356 double inf = std::numeric_limits<double>::infinity();
357
358 EXPECT_EQ(100, animation->timeToForwardsEffectChange());
359 EXPECT_EQ(inf, animation->timeToReverseEffectChange());
360
361 player->setCurrentTimeInternal(100);
362 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
363 EXPECT_EQ(0, animation->timeToReverseEffectChange());
364
365 player->setCurrentTimeInternal(199);
366 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
367 EXPECT_EQ(0, animation->timeToReverseEffectChange());
368
369 player->setCurrentTimeInternal(200);
370 // End-exclusive.
371 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
372 EXPECT_EQ(0, animation->timeToReverseEffectChange());
373
374 player->setCurrentTimeInternal(300);
375 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
376 EXPECT_EQ(100, animation->timeToReverseEffectChange());
377 }
378
379 TEST_F(AnimationAnimationTest, TimeToEffectChangeWithPlaybackRate)
380 {
381 Timing timing;
382 timing.iterationDuration = 100;
383 timing.startDelay = 100;
384 timing.endDelay = 100;
385 timing.playbackRate = 2;
386 timing.fillMode = Timing::FillModeNone;
387 RefPtr<Animation> animation = Animation::create(0, nullptr, timing);
388 RefPtr<AnimationPlayer> player = document.timeline().play(animation.get());
389 double inf = std::numeric_limits<double>::infinity();
390
391 EXPECT_EQ(100, animation->timeToForwardsEffectChange());
392 EXPECT_EQ(inf, animation->timeToReverseEffectChange());
393
394 player->setCurrentTimeInternal(100);
395 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
396 EXPECT_EQ(0, animation->timeToReverseEffectChange());
397
398 player->setCurrentTimeInternal(149);
399 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
400 EXPECT_EQ(0, animation->timeToReverseEffectChange());
401
402 player->setCurrentTimeInternal(150);
403 // End-exclusive.
404 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
405 EXPECT_EQ(0, animation->timeToReverseEffectChange());
406
407 player->setCurrentTimeInternal(200);
408 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
409 EXPECT_EQ(50, animation->timeToReverseEffectChange());
410 }
411
412 TEST_F(AnimationAnimationTest, TimeToEffectChangeWithNegativePlaybackRate)
413 {
414 Timing timing;
415 timing.iterationDuration = 100;
416 timing.startDelay = 100;
417 timing.endDelay = 100;
418 timing.playbackRate = -2;
419 timing.fillMode = Timing::FillModeNone;
420 RefPtr<Animation> animation = Animation::create(0, nullptr, timing);
421 RefPtr<AnimationPlayer> player = document.timeline().play(animation.get());
422 double inf = std::numeric_limits<double>::infinity();
423
424 EXPECT_EQ(100, animation->timeToForwardsEffectChange());
425 EXPECT_EQ(inf, animation->timeToReverseEffectChange());
426
427 player->setCurrentTimeInternal(100);
428 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
429 EXPECT_EQ(0, animation->timeToReverseEffectChange());
430
431 player->setCurrentTimeInternal(149);
432 EXPECT_EQ(0, animation->timeToForwardsEffectChange());
433 EXPECT_EQ(0, animation->timeToReverseEffectChange());
434
435 player->setCurrentTimeInternal(150);
436 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
437 EXPECT_EQ(0, animation->timeToReverseEffectChange());
438
439 player->setCurrentTimeInternal(200);
440 EXPECT_EQ(inf, animation->timeToForwardsEffectChange());
441 EXPECT_EQ(50, animation->timeToReverseEffectChange());
442 }
443
444 TEST_F(AnimationAnimationTest, ElementDestructorClearsAnimationTarget)
445 {
446 // This test expects incorrect behaviour should be removed once Element
447 // and Animation are moved to Oilpan. See crbug.com/362404 for context.
448 Timing timing;
449 timing.iterationDuration = 5;
450 RefPtr<Animation> animation = Animation::create(element.get(), nullptr, timi ng);
451 EXPECT_EQ(element.get(), animation->target());
452 document.timeline().play(animation.get());
453 pageHolder.clear();
454 element.clear();
455 #if !ENABLE(OILPAN)
456 EXPECT_EQ(0, animation->target());
457 #endif
458 }
459
460 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/core/animation/AnimationPlayerTest.cpp ('k') | sky/engine/core/animation/AnimationTestHelper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698