Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / animation / ElementAnimationTest.cpp
1 /*
2  * Copyright (c) 2013, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "core/animation/ElementAnimation.h"
33
34 #include "bindings/v8/Dictionary.h"
35 #include "core/animation/AnimatableLength.h"
36 #include "core/animation/Animation.h"
37 #include "core/animation/AnimationClock.h"
38 #include "core/animation/DocumentTimeline.h"
39 #include "core/animation/KeyframeEffectModel.h"
40 #include "core/animation/Timing.h"
41 #include "core/dom/Document.h"
42 #include "core/dom/Element.h"
43
44 #include <gtest/gtest.h>
45
46 namespace WebCore {
47
48 namespace {
49
50 v8::Handle<v8::Value> stringToV8Value(String string)
51 {
52     return v8::Handle<v8::Value>::Cast(v8String(v8::Isolate::GetCurrent(), string));
53 }
54
55 v8::Handle<v8::Value> doubleToV8Value(double number)
56 {
57     return v8::Handle<v8::Value>::Cast(v8::Number::New(v8::Isolate::GetCurrent(), number));
58 }
59
60 void setV8ObjectPropertyAsString(v8::Handle<v8::Object> object, String name, String value)
61 {
62     object->Set(stringToV8Value(name), stringToV8Value(value));
63 }
64
65 void setV8ObjectPropertyAsNumber(v8::Handle<v8::Object> object, String name, double value)
66 {
67     object->Set(stringToV8Value(name), doubleToV8Value(value));
68 }
69
70 } // namespace
71
72 class AnimationElementAnimationTest : public ::testing::Test {
73 protected:
74     virtual void SetUp()
75     {
76         document = Document::create();
77         document->animationClock().resetTimeForTesting();
78         element = document->createElement("foo", ASSERT_NO_EXCEPTION);
79         document->timeline()->setZeroTime(0);
80         ASSERT_EQ(0, document->timeline()->currentTime());
81     }
82
83     RefPtr<Document> document;
84     RefPtr<Element> element;
85
86     Animation* startAnimation(Element* element, Vector<Dictionary> keyframesDictionaryVector, Dictionary timingInput)
87     {
88         return ElementAnimation::startAnimation(element, keyframesDictionaryVector, timingInput);
89     }
90
91     Animation* startAnimation(Element* element, Vector<Dictionary> keyframesDictionaryVector, double timingInput)
92     {
93         return ElementAnimation::startAnimation(element, keyframesDictionaryVector, timingInput);
94     }
95
96     Animation* startAnimation(Element* element, Vector<Dictionary> keyframesDictionaryVector)
97     {
98         return ElementAnimation::startAnimation(element, keyframesDictionaryVector);
99     }
100
101     void populateTiming(Timing& timing, Dictionary timingInputDictionary)
102     {
103         ElementAnimation::populateTiming(timing, timingInputDictionary);
104     }
105
106     void applyTimingInputNumber(Timing& timing, v8::Isolate* isolate, String timingProperty, double timingPropertyValue)
107     {
108         v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
109         setV8ObjectPropertyAsNumber(timingInput, timingProperty, timingPropertyValue);
110         Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
111         populateTiming(timing, timingInputDictionary);
112     }
113
114     void applyTimingInputString(Timing& timing, v8::Isolate* isolate, String timingProperty, String timingPropertyValue)
115     {
116         v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
117         setV8ObjectPropertyAsString(timingInput, timingProperty, timingPropertyValue);
118         Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
119         populateTiming(timing, timingInputDictionary);
120     }
121 };
122
123 TEST_F(AnimationElementAnimationTest, CanStartAnAnimation)
124 {
125     v8::Isolate* isolate = v8::Isolate::GetCurrent();
126     v8::HandleScope scope(isolate);
127     v8::Local<v8::Context> context = v8::Context::New(isolate);
128     v8::Context::Scope contextScope(context);
129
130     Vector<Dictionary> jsKeyframes;
131     v8::Handle<v8::Object> keyframe1 = v8::Object::New(isolate);
132     v8::Handle<v8::Object> keyframe2 = v8::Object::New(isolate);
133
134     setV8ObjectPropertyAsString(keyframe1, "width", "100px");
135     setV8ObjectPropertyAsString(keyframe1, "offset", "0");
136     setV8ObjectPropertyAsString(keyframe2, "width", "0px");
137     setV8ObjectPropertyAsString(keyframe2, "offset", "1");
138
139     jsKeyframes.append(Dictionary(keyframe1, isolate));
140     jsKeyframes.append(Dictionary(keyframe2, isolate));
141
142     String value1;
143     ASSERT_TRUE(jsKeyframes[0].get("width", value1));
144     ASSERT_EQ("100px", value1);
145
146     String value2;
147     ASSERT_TRUE(jsKeyframes[1].get("width", value2));
148     ASSERT_EQ("0px", value2);
149
150     Animation* animation = startAnimation(element.get(), jsKeyframes, 0);
151
152     Player* player = document->timeline()->players().at(0).get();
153     EXPECT_EQ(animation, player->source());
154
155     Element* target = animation->target();
156     EXPECT_EQ(*element.get(), *target);
157
158     const KeyframeEffectModel::KeyframeVector keyframes =
159         toKeyframeEffectModel(animation->effect())->getFrames();
160
161     EXPECT_EQ(0, keyframes[0]->offset());
162     EXPECT_EQ(1, keyframes[1]->offset());
163
164     const AnimatableValue* keyframe1Width = keyframes[0]->propertyValue(CSSPropertyWidth);
165     const AnimatableValue* keyframe2Width = keyframes[1]->propertyValue(CSSPropertyWidth);
166     ASSERT(keyframe1Width);
167     ASSERT(keyframe2Width);
168
169     EXPECT_TRUE(keyframe1Width->isLength());
170     EXPECT_TRUE(keyframe2Width->isLength());
171
172     EXPECT_EQ("100px", toAnimatableLength(keyframe1Width)->toCSSValue()->cssText());
173     EXPECT_EQ("0px", toAnimatableLength(keyframe2Width)->toCSSValue()->cssText());
174 }
175
176 TEST_F(AnimationElementAnimationTest, ParseCamelCasePropertyNames)
177 {
178     EXPECT_EQ(CSSPropertyInvalid, ElementAnimation::camelCaseCSSPropertyNameToID(String("line-height")));
179     EXPECT_EQ(CSSPropertyLineHeight, ElementAnimation::camelCaseCSSPropertyNameToID(String("lineHeight")));
180     EXPECT_EQ(CSSPropertyBorderTopWidth, ElementAnimation::camelCaseCSSPropertyNameToID(String("borderTopWidth")));
181     EXPECT_EQ(CSSPropertyWidth, ElementAnimation::camelCaseCSSPropertyNameToID(String("width")));
182     EXPECT_EQ(CSSPropertyInvalid, ElementAnimation::camelCaseCSSPropertyNameToID(String("Width")));
183     EXPECT_EQ(CSSPropertyInvalid, ElementAnimation::camelCaseCSSPropertyNameToID(String("-webkit-transform")));
184     EXPECT_EQ(CSSPropertyInvalid, ElementAnimation::camelCaseCSSPropertyNameToID(String("webkitTransform")));
185     EXPECT_EQ(CSSPropertyInvalid, ElementAnimation::camelCaseCSSPropertyNameToID(String("cssFloat")));
186 }
187
188 TEST_F(AnimationElementAnimationTest, CanSetDuration)
189 {
190     v8::Isolate* isolate = v8::Isolate::GetCurrent();
191     v8::HandleScope scope(isolate);
192     v8::Local<v8::Context> context = v8::Context::New(isolate);
193     v8::Context::Scope contextScope(context);
194
195     Vector<Dictionary, 0> jsKeyframes;
196     double duration = 2;
197
198     Animation* animation = startAnimation(element.get(), jsKeyframes, duration);
199
200     Player* player = document->timeline()->players().at(0).get();
201
202     EXPECT_EQ(animation, player->source());
203     EXPECT_TRUE(player->source()->specified().hasIterationDuration);
204     EXPECT_EQ(duration, player->source()->specified().iterationDuration);
205 }
206
207 TEST_F(AnimationElementAnimationTest, CanOmitSpecifiedDuration)
208 {
209     v8::Isolate* isolate = v8::Isolate::GetCurrent();
210     v8::HandleScope scope(isolate);
211     v8::Local<v8::Context> context = v8::Context::New(isolate);
212     v8::Context::Scope contextScope(context);
213
214     Vector<Dictionary, 0> jsKeyframes;
215
216     Animation* animation = startAnimation(element.get(), jsKeyframes);
217
218     Player* player = document->timeline()->players().at(0).get();
219     EXPECT_EQ(animation, player->source());
220
221     EXPECT_FALSE(player->source()->specified().hasIterationDuration);
222     EXPECT_EQ(0, player->source()->specified().iterationDuration);
223 }
224
225 TEST_F(AnimationElementAnimationTest, ClipNegativeDurationToZero)
226 {
227     v8::Isolate* isolate = v8::Isolate::GetCurrent();
228     v8::HandleScope scope(isolate);
229     v8::Local<v8::Context> context = v8::Context::New(isolate);
230     v8::Context::Scope contextScope(context);
231
232     Vector<Dictionary, 0> jsKeyframes;
233
234     Animation* animation = startAnimation(element.get(), jsKeyframes, -2);
235
236     Player* player = document->timeline()->players().at(0).get();
237     EXPECT_EQ(animation, player->source());
238
239     EXPECT_TRUE(player->source()->specified().hasIterationDuration);
240     EXPECT_EQ(0, player->source()->specified().iterationDuration);
241 }
242
243 TEST_F(AnimationElementAnimationTest, TimingInputStartDelay)
244 {
245     v8::Isolate* isolate = v8::Isolate::GetCurrent();
246     v8::HandleScope scope(isolate);
247     v8::Local<v8::Context> context = v8::Context::New(isolate);
248     v8::Context::Scope contextScope(context);
249
250     Timing timing;
251     EXPECT_EQ(0, timing.startDelay);
252
253     applyTimingInputNumber(timing, isolate, "delay", 1.1);
254     EXPECT_EQ(1.1, timing.startDelay);
255     timing.startDelay = 0;
256
257     applyTimingInputNumber(timing, isolate, "delay", -1);
258     EXPECT_EQ(-1, timing.startDelay);
259     timing.startDelay = 0;
260
261     applyTimingInputString(timing, isolate, "delay", "1");
262     EXPECT_EQ(1, timing.startDelay);
263     timing.startDelay = 0;
264
265     applyTimingInputString(timing, isolate, "delay", "1s");
266     EXPECT_EQ(0, timing.startDelay);
267     timing.startDelay = 0;
268
269     applyTimingInputString(timing, isolate, "delay", "Infinity");
270     EXPECT_EQ(0, timing.startDelay);
271     timing.startDelay = 0;
272
273     applyTimingInputString(timing, isolate, "delay", "-Infinity");
274     EXPECT_EQ(0, timing.startDelay);
275     timing.startDelay = 0;
276
277     applyTimingInputString(timing, isolate, "delay", "NaN");
278     EXPECT_EQ(0, timing.startDelay);
279     timing.startDelay = 0;
280
281     applyTimingInputString(timing, isolate, "delay", "rubbish");
282     EXPECT_EQ(0, timing.startDelay);
283     timing.startDelay = 0;
284 }
285
286 TEST_F(AnimationElementAnimationTest, TimingInputFillMode)
287 {
288     v8::Isolate* isolate = v8::Isolate::GetCurrent();
289     v8::HandleScope scope(isolate);
290     v8::Local<v8::Context> context = v8::Context::New(isolate);
291     v8::Context::Scope contextScope(context);
292
293     Timing timing;
294     Timing::FillMode defaultFillMode = Timing::FillModeForwards;
295     EXPECT_EQ(defaultFillMode, timing.fillMode);
296
297     applyTimingInputString(timing, isolate, "fill", "forwards");
298     EXPECT_EQ(Timing::FillModeForwards, timing.fillMode);
299     timing.fillMode = defaultFillMode;
300
301     applyTimingInputString(timing, isolate, "fill", "none");
302     EXPECT_EQ(Timing::FillModeNone, timing.fillMode);
303     timing.fillMode = defaultFillMode;
304
305     applyTimingInputString(timing, isolate, "fill", "backwards");
306     EXPECT_EQ(Timing::FillModeBackwards, timing.fillMode);
307     timing.fillMode = defaultFillMode;
308
309     applyTimingInputString(timing, isolate, "fill", "both");
310     EXPECT_EQ(Timing::FillModeBoth, timing.fillMode);
311     timing.fillMode = defaultFillMode;
312
313     applyTimingInputString(timing, isolate, "fill", "everything!");
314     EXPECT_EQ(defaultFillMode, timing.fillMode);
315     timing.fillMode = defaultFillMode;
316
317     applyTimingInputString(timing, isolate, "fill", "backwardsandforwards");
318     EXPECT_EQ(defaultFillMode, timing.fillMode);
319     timing.fillMode = defaultFillMode;
320
321     applyTimingInputNumber(timing, isolate, "fill", 2);
322     EXPECT_EQ(defaultFillMode, timing.fillMode);
323     timing.fillMode = defaultFillMode;
324 }
325
326 TEST_F(AnimationElementAnimationTest, TimingInputIterationStart)
327 {
328     v8::Isolate* isolate = v8::Isolate::GetCurrent();
329     v8::HandleScope scope(isolate);
330     v8::Local<v8::Context> context = v8::Context::New(isolate);
331     v8::Context::Scope contextScope(context);
332
333     Timing timing;
334     EXPECT_EQ(0, timing.iterationStart);
335
336     applyTimingInputNumber(timing, isolate, "iterationStart", 1.1);
337     EXPECT_EQ(1.1, timing.iterationStart);
338     timing.iterationStart = 0;
339
340     applyTimingInputNumber(timing, isolate, "iterationStart", -1);
341     EXPECT_EQ(0, timing.iterationStart);
342     timing.iterationStart = 0;
343
344     applyTimingInputString(timing, isolate, "iterationStart", "Infinity");
345     EXPECT_EQ(0, timing.iterationStart);
346     timing.iterationStart = 0;
347
348     applyTimingInputString(timing, isolate, "iterationStart", "-Infinity");
349     EXPECT_EQ(0, timing.iterationStart);
350     timing.iterationStart = 0;
351
352     applyTimingInputString(timing, isolate, "iterationStart", "NaN");
353     EXPECT_EQ(0, timing.iterationStart);
354     timing.iterationStart = 0;
355
356     applyTimingInputString(timing, isolate, "iterationStart", "rubbish");
357     EXPECT_EQ(0, timing.iterationStart);
358     timing.iterationStart = 0;
359 }
360
361 TEST_F(AnimationElementAnimationTest, TimingInputIterationCount)
362 {
363     v8::Isolate* isolate = v8::Isolate::GetCurrent();
364     v8::HandleScope scope(isolate);
365     v8::Local<v8::Context> context = v8::Context::New(isolate);
366     v8::Context::Scope contextScope(context);
367
368     Timing timing;
369     EXPECT_EQ(1, timing.iterationCount);
370
371     applyTimingInputNumber(timing, isolate, "iterations", 2.1);
372     EXPECT_EQ(2.1, timing.iterationCount);
373     timing.iterationCount = 1;
374
375     applyTimingInputNumber(timing, isolate, "iterations", -1);
376     EXPECT_EQ(0, timing.iterationCount);
377     timing.iterationCount = 1;
378
379     applyTimingInputString(timing, isolate, "iterations", "Infinity");
380     EXPECT_TRUE(std::isinf(timing.iterationCount) && (timing.iterationCount > 0));
381     timing.iterationCount = 1;
382
383     applyTimingInputString(timing, isolate, "iterations", "-Infinity");
384     EXPECT_EQ(0, timing.iterationCount);
385     timing.iterationCount = 1;
386
387     applyTimingInputString(timing, isolate, "iterations", "NaN");
388     EXPECT_EQ(1, timing.iterationCount);
389     timing.iterationCount = 1;
390
391     applyTimingInputString(timing, isolate, "iterations", "rubbish");
392     EXPECT_EQ(1, timing.iterationCount);
393     timing.iterationCount = 1;
394 }
395
396 TEST_F(AnimationElementAnimationTest, TimingInputIterationDuration)
397 {
398     v8::Isolate* isolate = v8::Isolate::GetCurrent();
399     v8::HandleScope scope(isolate);
400     v8::Local<v8::Context> context = v8::Context::New(isolate);
401     v8::Context::Scope contextScope(context);
402
403     Timing timing;
404     EXPECT_EQ(0, timing.iterationDuration);
405     EXPECT_FALSE(timing.hasIterationDuration);
406
407     applyTimingInputNumber(timing, isolate, "duration", 1.1);
408     EXPECT_EQ(1.1, timing.iterationDuration);
409     EXPECT_TRUE(timing.hasIterationDuration);
410     timing.hasIterationDuration = false;
411     timing.iterationDuration = 0;
412
413     applyTimingInputNumber(timing, isolate, "duration", -1);
414     EXPECT_EQ(0, timing.iterationDuration);
415     EXPECT_FALSE(timing.hasIterationDuration);
416     timing.hasIterationDuration = false;
417     timing.iterationDuration = 0;
418
419     applyTimingInputString(timing, isolate, "duration", "1");
420     EXPECT_EQ(1, timing.iterationDuration);
421     EXPECT_TRUE(timing.hasIterationDuration);
422     timing.hasIterationDuration = false;
423     timing.iterationDuration = 0;
424
425     applyTimingInputString(timing, isolate, "duration", "Infinity");
426     EXPECT_TRUE(std::isinf(timing.iterationDuration) && (timing.iterationDuration > 0));
427     EXPECT_TRUE(timing.hasIterationDuration);
428     timing.hasIterationDuration = false;
429     timing.iterationDuration = 0;
430
431     applyTimingInputString(timing, isolate, "duration", "-Infinity");
432     EXPECT_EQ(0, timing.iterationDuration);
433     EXPECT_FALSE(timing.hasIterationDuration);
434     timing.hasIterationDuration = false;
435     timing.iterationDuration = 0;
436
437     applyTimingInputString(timing, isolate, "duration", "NaN");
438     EXPECT_EQ(0, timing.iterationDuration);
439     EXPECT_FALSE(timing.hasIterationDuration);
440     timing.hasIterationDuration = false;
441     timing.iterationDuration = 0;
442
443     applyTimingInputString(timing, isolate, "duration", "auto");
444     EXPECT_EQ(0, timing.iterationDuration);
445     EXPECT_FALSE(timing.hasIterationDuration);
446     timing.hasIterationDuration = false;
447     timing.iterationDuration = 0;
448
449     applyTimingInputString(timing, isolate, "duration", "rubbish");
450     EXPECT_EQ(0, timing.iterationDuration);
451     EXPECT_FALSE(timing.hasIterationDuration);
452     timing.hasIterationDuration = false;
453     timing.iterationDuration = 0;
454 }
455
456 TEST_F(AnimationElementAnimationTest, TimingInputPlaybackRate)
457 {
458     v8::Isolate* isolate = v8::Isolate::GetCurrent();
459     v8::HandleScope scope(isolate);
460     v8::Local<v8::Context> context = v8::Context::New(isolate);
461     v8::Context::Scope contextScope(context);
462
463     Timing timing;
464     EXPECT_EQ(1, timing.playbackRate);
465
466     applyTimingInputNumber(timing, isolate, "playbackRate", 2.1);
467     EXPECT_EQ(2.1, timing.playbackRate);
468     timing.playbackRate = 1;
469
470     applyTimingInputNumber(timing, isolate, "playbackRate", -1);
471     EXPECT_EQ(-1, timing.playbackRate);
472     timing.playbackRate = 1;
473
474     applyTimingInputString(timing, isolate, "playbackRate", "Infinity");
475     EXPECT_EQ(1, timing.playbackRate);
476     timing.playbackRate = 1;
477
478     applyTimingInputString(timing, isolate, "playbackRate", "-Infinity");
479     EXPECT_EQ(1, timing.playbackRate);
480     timing.playbackRate = 1;
481
482     applyTimingInputString(timing, isolate, "playbackRate", "NaN");
483     EXPECT_EQ(1, timing.playbackRate);
484     timing.playbackRate = 1;
485
486     applyTimingInputString(timing, isolate, "playbackRate", "rubbish");
487     EXPECT_EQ(1, timing.playbackRate);
488     timing.playbackRate = 1;
489 }
490
491 TEST_F(AnimationElementAnimationTest, TimingInputDirection)
492 {
493     v8::Isolate* isolate = v8::Isolate::GetCurrent();
494     v8::HandleScope scope(isolate);
495     v8::Local<v8::Context> context = v8::Context::New(isolate);
496     v8::Context::Scope contextScope(context);
497
498     Timing timing;
499     Timing::PlaybackDirection defaultPlaybackDirection = Timing::PlaybackDirectionNormal;
500     EXPECT_EQ(defaultPlaybackDirection, timing.direction);
501
502     applyTimingInputString(timing, isolate, "direction", "normal");
503     EXPECT_EQ(Timing::PlaybackDirectionNormal, timing.direction);
504     timing.direction = defaultPlaybackDirection;
505
506     applyTimingInputString(timing, isolate, "direction", "reverse");
507     EXPECT_EQ(Timing::PlaybackDirectionReverse, timing.direction);
508     timing.direction = defaultPlaybackDirection;
509
510     applyTimingInputString(timing, isolate, "direction", "alternate");
511     EXPECT_EQ(Timing::PlaybackDirectionAlternate, timing.direction);
512     timing.direction = defaultPlaybackDirection;
513
514     applyTimingInputString(timing, isolate, "direction", "alternate-reverse");
515     EXPECT_EQ(Timing::PlaybackDirectionAlternateReverse, timing.direction);
516     timing.direction = defaultPlaybackDirection;
517
518     applyTimingInputString(timing, isolate, "direction", "rubbish");
519     EXPECT_EQ(defaultPlaybackDirection, timing.direction);
520     timing.direction = defaultPlaybackDirection;
521
522     applyTimingInputNumber(timing, isolate, "direction", 2);
523     EXPECT_EQ(defaultPlaybackDirection, timing.direction);
524     timing.direction = defaultPlaybackDirection;
525 }
526
527 TEST_F(AnimationElementAnimationTest, TimingInputEmpty)
528 {
529     v8::Isolate* isolate = v8::Isolate::GetCurrent();
530     v8::HandleScope scope(isolate);
531     v8::Local<v8::Context> context = v8::Context::New(isolate);
532     v8::Context::Scope contextScope(context);
533
534     Timing updatedTiming;
535     Timing controlTiming;
536
537     v8::Handle<v8::Object> timingInput = v8::Object::New(isolate);
538     Dictionary timingInputDictionary = Dictionary(v8::Handle<v8::Value>::Cast(timingInput), isolate);
539     populateTiming(updatedTiming, timingInputDictionary);
540
541     EXPECT_EQ(controlTiming.startDelay, updatedTiming.startDelay);
542     EXPECT_EQ(controlTiming.fillMode, updatedTiming.fillMode);
543     EXPECT_EQ(controlTiming.iterationStart, updatedTiming.iterationStart);
544     EXPECT_EQ(controlTiming.iterationCount, updatedTiming.iterationCount);
545     EXPECT_EQ(controlTiming.iterationDuration, updatedTiming.iterationDuration);
546     EXPECT_EQ(controlTiming.hasIterationDuration, updatedTiming.hasIterationDuration);
547     EXPECT_EQ(controlTiming.playbackRate, updatedTiming.playbackRate);
548     EXPECT_EQ(controlTiming.direction, updatedTiming.direction);
549 }
550
551 } // namespace WebCore