TEST_F(AnimationEffectInputTest, SortedOffsets) { Vector<Dictionary> jsKeyframes; v8::Local<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe2 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(m_isolate, keyframe1, "width", "100px"); setV8ObjectPropertyAsString(m_isolate, keyframe1, "offset", "0"); setV8ObjectPropertyAsString(m_isolate, keyframe2, "width", "0px"); setV8ObjectPropertyAsString(m_isolate, keyframe2, "offset", "1"); jsKeyframes.append(Dictionary(keyframe1, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe2, m_isolate, exceptionState)); EffectModel* animationEffect = EffectInput::convert(element.get(), jsKeyframes, exceptionState); EXPECT_FALSE(exceptionState.hadException()); const KeyframeEffectModelBase& keyframeEffect = *toKeyframeEffectModelBase(animationEffect); EXPECT_EQ(1.0, keyframeEffect.getFrames()[1]->offset()); }
TEST_F(AnimationAnimationV8Test, MissingOffsetZeroAndOneRaisesException) { Vector<Dictionary> jsKeyframes; v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(keyframe1, "width", "100px"); setV8ObjectPropertyAsString(keyframe1, "offset", "0.1"); setV8ObjectPropertyAsString(keyframe2, "width", "0px"); setV8ObjectPropertyAsString(keyframe2, "offset", "0.2"); jsKeyframes.append(Dictionary(keyframe1, m_isolate)); jsKeyframes.append(Dictionary(keyframe2, m_isolate)); RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, 0, exceptionState); EXPECT_TRUE(exceptionState.hadException()); EXPECT_EQ(NotSupportedError, exceptionState.code()); }
Timing applyTimingInputString(v8::Isolate* isolate, String timingProperty, String timingPropertyValue, bool& timingConversionSuccess) { v8::Local<v8::Object> timingInput = v8::Object::New(isolate); setV8ObjectPropertyAsString(isolate, timingInput, timingProperty, timingPropertyValue); KeyframeEffectOptions timingInputDictionary; TrackExceptionState exceptionState; V8KeyframeEffectOptions::toImpl(isolate, timingInput, timingInputDictionary, exceptionState); Timing result; timingConversionSuccess = TimingInput::convert(timingInputDictionary, result, nullptr, exceptionState) && !exceptionState.hadException(); return result; }
TEST_F(AnimationAnimationV8Test, MismatchedKeyframePropertyRaisesException) { Vector<Dictionary> jsKeyframes; v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(keyframe1, "width", "100px"); setV8ObjectPropertyAsString(keyframe1, "offset", "0"); // Height property appears only in keyframe2 setV8ObjectPropertyAsString(keyframe2, "height", "100px"); setV8ObjectPropertyAsString(keyframe2, "width", "0px"); setV8ObjectPropertyAsString(keyframe2, "offset", "1"); jsKeyframes.append(Dictionary(keyframe1, m_isolate)); jsKeyframes.append(Dictionary(keyframe2, m_isolate)); createAnimation(element.get(), jsKeyframes, 0, exceptionState); EXPECT_TRUE(exceptionState.hadException()); EXPECT_EQ(NotSupportedError, exceptionState.code()); }
TEST_F(AnimationEffectInputTest, Invalid) { // Not loosely sorted by offset, and there exists a keyframe with null offset. Vector<Dictionary> jsKeyframes; v8::Local<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe2 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe3 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(m_isolate, keyframe1, "width", "0px"); setV8ObjectPropertyAsString(m_isolate, keyframe1, "offset", "1"); setV8ObjectPropertyAsString(m_isolate, keyframe2, "width", "200px"); setV8ObjectPropertyAsString(m_isolate, keyframe3, "width", "100px"); setV8ObjectPropertyAsString(m_isolate, keyframe3, "offset", "0"); jsKeyframes.append(Dictionary(keyframe1, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe2, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe3, m_isolate, exceptionState)); EffectInput::convert(element.get(), jsKeyframes, exceptionState); EXPECT_TRUE(exceptionState.hadException()); EXPECT_EQ(InvalidModificationError, exceptionState.code()); }
TEST_F(AnimationEffectInputTest, LooslySorted) { Vector<Dictionary> jsKeyframes; v8::Local<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe2 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe3 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(m_isolate, keyframe1, "width", "100px"); setV8ObjectPropertyAsString(m_isolate, keyframe1, "offset", "0"); setV8ObjectPropertyAsString(m_isolate, keyframe2, "width", "200px"); setV8ObjectPropertyAsString(m_isolate, keyframe3, "width", "0px"); setV8ObjectPropertyAsString(m_isolate, keyframe3, "offset", "1"); jsKeyframes.append(Dictionary(keyframe1, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe2, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe3, m_isolate, exceptionState)); EffectModel* animationEffect = EffectInput::convert(element.get(), EffectModelOrDictionarySequenceOrDictionary::fromDictionarySequence(jsKeyframes), nullptr, exceptionState); EXPECT_FALSE(exceptionState.hadException()); const KeyframeEffectModelBase& keyframeEffect = *toKeyframeEffectModelBase(animationEffect); EXPECT_EQ(1, keyframeEffect.getFrames()[2]->offset()); }
TEST(AnimationEffectInputTest, UnsortedOffsets) { V8TestingScope scope; Vector<Dictionary> jsKeyframes; v8::Local<v8::Object> keyframe1 = v8::Object::New(scope.isolate()); v8::Local<v8::Object> keyframe2 = v8::Object::New(scope.isolate()); setV8ObjectPropertyAsString(scope.isolate(), keyframe1, "width", "0px"); setV8ObjectPropertyAsString(scope.isolate(), keyframe1, "offset", "1"); setV8ObjectPropertyAsString(scope.isolate(), keyframe2, "width", "100px"); setV8ObjectPropertyAsString(scope.isolate(), keyframe2, "offset", "0"); jsKeyframes.push_back( Dictionary(scope.isolate(), keyframe1, scope.getExceptionState())); jsKeyframes.push_back( Dictionary(scope.isolate(), keyframe2, scope.getExceptionState())); Element* element = appendElement(scope.document()); EffectInput::convert( element, DictionarySequenceOrDictionary::fromDictionarySequence(jsKeyframes), nullptr, scope.getExceptionState()); EXPECT_TRUE(scope.getExceptionState().hadException()); EXPECT_EQ(V8TypeError, scope.getExceptionState().code()); }
TEST_F(AnimationAnimationTest, CanCreateAnAnimation) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope contextScope(context); Vector<Dictionary> jsKeyframes; v8::Handle<v8::Object> keyframe1 = v8::Object::New(isolate); v8::Handle<v8::Object> keyframe2 = v8::Object::New(isolate); setV8ObjectPropertyAsString(keyframe1, "width", "100px"); setV8ObjectPropertyAsString(keyframe1, "offset", "0"); setV8ObjectPropertyAsString(keyframe1, "easing", "ease-in-out"); setV8ObjectPropertyAsString(keyframe2, "width", "0px"); setV8ObjectPropertyAsString(keyframe2, "offset", "1"); setV8ObjectPropertyAsString(keyframe2, "easing", "cubic-bezier(1, 1, 0.3, 0.3)"); jsKeyframes.append(Dictionary(keyframe1, isolate)); jsKeyframes.append(Dictionary(keyframe2, isolate)); String value1; ASSERT_TRUE(jsKeyframes[0].get("width", value1)); ASSERT_EQ("100px", value1); String value2; ASSERT_TRUE(jsKeyframes[1].get("width", value2)); ASSERT_EQ("0px", value2); RefPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, 0); Element* target = animation->target(); EXPECT_EQ(*element.get(), *target); const KeyframeEffectModel::KeyframeVector keyframes = toKeyframeEffectModel(animation->effect())->getFrames(); EXPECT_EQ(0, keyframes[0]->offset()); EXPECT_EQ(1, keyframes[1]->offset()); const AnimatableValue* keyframe1Width = keyframes[0]->propertyValue(CSSPropertyWidth); const AnimatableValue* keyframe2Width = keyframes[1]->propertyValue(CSSPropertyWidth); ASSERT(keyframe1Width); ASSERT(keyframe2Width); EXPECT_TRUE(keyframe1Width->isLength()); EXPECT_TRUE(keyframe2Width->isLength()); EXPECT_EQ("100px", toAnimatableLength(keyframe1Width)->toCSSValue()->cssText()); EXPECT_EQ("0px", toAnimatableLength(keyframe2Width)->toCSSValue()->cssText()); EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut)), *keyframes[0]->easing()); EXPECT_EQ(*(CubicBezierTimingFunction::create(1, 1, 0.3, 0.3).get()), *keyframes[1]->easing()); }
TEST_F(AnimationAnimationV8Test, CanCreateAnAnimation) { Vector<Dictionary> jsKeyframes; v8::Handle<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Handle<v8::Object> keyframe2 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(keyframe1, "width", "100px"); setV8ObjectPropertyAsString(keyframe1, "offset", "0"); setV8ObjectPropertyAsString(keyframe1, "easing", "ease-in-out"); setV8ObjectPropertyAsString(keyframe2, "width", "0px"); setV8ObjectPropertyAsString(keyframe2, "offset", "1"); setV8ObjectPropertyAsString(keyframe2, "easing", "cubic-bezier(1, 1, 0.3, 0.3)"); jsKeyframes.append(Dictionary(keyframe1, m_isolate)); jsKeyframes.append(Dictionary(keyframe2, m_isolate)); String value1; ASSERT_TRUE(jsKeyframes[0].get("width", value1)); ASSERT_EQ("100px", value1); String value2; ASSERT_TRUE(jsKeyframes[1].get("width", value2)); ASSERT_EQ("0px", value2); RefPtrWillBeRawPtr<Animation> animation = createAnimation(element.get(), jsKeyframes, 0, exceptionState); Element* target = animation->target(); EXPECT_EQ(*element.get(), *target); const KeyframeVector keyframes = toKeyframeEffectModelBase(animation->effect())->getFrames(); EXPECT_EQ(0, keyframes[0]->offset()); EXPECT_EQ(1, keyframes[1]->offset()); const CSSValue* keyframe1Width = toStringKeyframe(keyframes[0].get())->propertyValue(CSSPropertyWidth); const CSSValue* keyframe2Width = toStringKeyframe(keyframes[1].get())->propertyValue(CSSPropertyWidth); ASSERT(keyframe1Width); ASSERT(keyframe2Width); EXPECT_EQ("100px", keyframe1Width->cssText()); EXPECT_EQ("0px", keyframe2Width->cssText()); EXPECT_EQ(*(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut)), *keyframes[0]->easing()); EXPECT_EQ(*(CubicBezierTimingFunction::create(1, 1, 0.3, 0.3).get()), *keyframes[1]->easing()); }
TEST_F(AnimationEffectInputTest, OutOfOrderWithNullOffsets) { Vector<Dictionary> jsKeyframes; v8::Local<v8::Object> keyframe1 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe2 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe3 = v8::Object::New(m_isolate); v8::Local<v8::Object> keyframe4 = v8::Object::New(m_isolate); setV8ObjectPropertyAsString(m_isolate, keyframe1, "height", "100px"); setV8ObjectPropertyAsString(m_isolate, keyframe1, "offset", "0.5"); setV8ObjectPropertyAsString(m_isolate, keyframe2, "height", "150px"); setV8ObjectPropertyAsString(m_isolate, keyframe3, "height", "200px"); setV8ObjectPropertyAsString(m_isolate, keyframe3, "offset", "0"); setV8ObjectPropertyAsString(m_isolate, keyframe4, "height", "300px"); setV8ObjectPropertyAsString(m_isolate, keyframe4, "offset", "1"); jsKeyframes.append(Dictionary(keyframe1, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe2, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe3, m_isolate, exceptionState)); jsKeyframes.append(Dictionary(keyframe4, m_isolate, exceptionState)); EffectInput::convert(element.get(), jsKeyframes, exceptionState); EXPECT_TRUE(exceptionState.hadException()); }