// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/animation/keyframe_effect.h"

#include <memory>

#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/unrestricted_double_or_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_effect_timing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "v8/include/v8.h"

namespace blink {

#define EXPECT_TIMEDELTA(expected, observed)                          \
  EXPECT_NEAR(expected.InMillisecondsF(), observed.InMillisecondsF(), \
              Animation::kTimeToleranceMs)

using animation_test_helpers::SetV8ObjectPropertyAsNumber;
using animation_test_helpers::SetV8ObjectPropertyAsString;

class KeyframeEffectTest : public PageTestBase {
 protected:
  void SetUp() override {
    PageTestBase::SetUp(IntSize());
    element = GetDocument().CreateElementForBinding("foo");
    GetDocument().documentElement()->AppendChild(element.Get());
  }

  KeyframeEffectModelBase* CreateEmptyEffectModel() {
    return MakeGarbageCollected<StringKeyframeEffectModel>(
        StringKeyframeVector());
  }

  // Returns a two-frame effect updated styles.
  KeyframeEffect* GetTwoFrameEffect(const CSSPropertyID& property,
                                    const String& value_a,
                                    const String& value_b) {
    StringKeyframeVector keyframes(2);
    keyframes[0] = MakeGarbageCollected<StringKeyframe>();
    keyframes[0]->SetOffset(0.0);
    keyframes[0]->SetCSSPropertyValue(
        property, value_a, SecureContextMode::kInsecureContext, nullptr);
    keyframes[1] = MakeGarbageCollected<StringKeyframe>();
    keyframes[1]->SetOffset(1.0);
    keyframes[1]->SetCSSPropertyValue(
        property, value_b, SecureContextMode::kInsecureContext, nullptr);
    auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
    Timing timing;
    auto* effect = MakeGarbageCollected<KeyframeEffect>(element, model, timing);
    // Ensure GetCompositorKeyframeValue is updated which would normally happen
    // when applying the animation styles.
    UpdateAllLifecyclePhasesForTest();
    model->SnapshotAllCompositorKeyframesIfNecessary(
        *element, *element->GetComputedStyle(), nullptr);

    return effect;
  }

  Persistent<Element> element;
};

class AnimationKeyframeEffectV8Test : public KeyframeEffectTest {
 protected:
  static KeyframeEffect* CreateAnimationFromTiming(
      ScriptState* script_state,
      Element* element,
      const ScriptValue& keyframe_object,
      double timing_input) {
    NonThrowableExceptionState exception_state;
    return KeyframeEffect::Create(
        script_state, element, keyframe_object,
        UnrestrictedDoubleOrKeyframeEffectOptions::FromUnrestrictedDouble(
            timing_input),
        exception_state);
  }
  static KeyframeEffect* CreateAnimationFromOption(
      ScriptState* script_state,
      Element* element,
      const ScriptValue& keyframe_object,
      const KeyframeEffectOptions* timing_input) {
    NonThrowableExceptionState exception_state;
    return KeyframeEffect::Create(
        script_state, element, keyframe_object,
        UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
            const_cast<KeyframeEffectOptions*>(timing_input)),
        exception_state);
  }
  static KeyframeEffect* CreateAnimation(ScriptState* script_state,
                                         Element* element,
                                         const ScriptValue& keyframe_object) {
    NonThrowableExceptionState exception_state;
    return KeyframeEffect::Create(script_state, element, keyframe_object,
                                  exception_state);
  }
};

TEST_F(AnimationKeyframeEffectV8Test, CanCreateAnAnimation) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  NonThrowableExceptionState exception_state;

  HeapVector<ScriptValue> blink_keyframes = {
      V8ObjectBuilder(script_state)
          .AddString("width", "100px")
          .AddString("offset", "0")
          .AddString("easing", "ease-in-out")
          .GetScriptValue(),
      V8ObjectBuilder(script_state)
          .AddString("width", "0px")
          .AddString("offset", "1")
          .AddString("easing", "cubic-bezier(1, 1, 0.3, 0.3)")
          .GetScriptValue()};

  ScriptValue js_keyframes(
      scope.GetIsolate(),
      ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));

  KeyframeEffect* animation =
      CreateAnimationFromTiming(script_state, element.Get(), js_keyframes, 0);

  Element* target = animation->target();
  EXPECT_EQ(*element.Get(), *target);

  const KeyframeVector keyframes = animation->Model()->GetFrames();

  EXPECT_EQ(0, keyframes[0]->CheckedOffset());
  EXPECT_EQ(1, keyframes[1]->CheckedOffset());

  const CSSValue& keyframe1_width =
      To<StringKeyframe>(*keyframes[0])
          .CssPropertyValue(PropertyHandle(GetCSSPropertyWidth()));
  const CSSValue& keyframe2_width =
      To<StringKeyframe>(*keyframes[1])
          .CssPropertyValue(PropertyHandle(GetCSSPropertyWidth()));

  EXPECT_EQ("100px", keyframe1_width.CssText());
  EXPECT_EQ("0px", keyframe2_width.CssText());

  EXPECT_EQ(*(CubicBezierTimingFunction::Preset(
                CubicBezierTimingFunction::EaseType::EASE_IN_OUT)),
            keyframes[0]->Easing());
  EXPECT_EQ(*(CubicBezierTimingFunction::Create(1, 1, 0.3, 0.3).get()),
            keyframes[1]->Easing());
}

TEST_F(AnimationKeyframeEffectV8Test, SetAndRetrieveEffectComposite) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  NonThrowableExceptionState exception_state;

  v8::Local<v8::Object> effect_options = v8::Object::New(scope.GetIsolate());
  SetV8ObjectPropertyAsString(scope.GetIsolate(), effect_options, "composite",
                              "add");
  KeyframeEffectOptions* effect_options_dictionary =
      NativeValueTraits<KeyframeEffectOptions>::NativeValue(
          scope.GetIsolate(), effect_options, exception_state);
  EXPECT_FALSE(exception_state.HadException());

  ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
  KeyframeEffect* effect = CreateAnimationFromOption(
      script_state, element.Get(), js_keyframes, effect_options_dictionary);
  EXPECT_EQ("add", effect->composite());

  effect->setComposite("replace");
  EXPECT_EQ("replace", effect->composite());

  effect->setComposite("accumulate");
  EXPECT_EQ("accumulate", effect->composite());
}

TEST_F(AnimationKeyframeEffectV8Test, KeyframeCompositeOverridesEffect) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  NonThrowableExceptionState exception_state;

  v8::Local<v8::Object> effect_options = v8::Object::New(scope.GetIsolate());
  SetV8ObjectPropertyAsString(scope.GetIsolate(), effect_options, "composite",
                              "add");
  KeyframeEffectOptions* effect_options_dictionary =
      NativeValueTraits<KeyframeEffectOptions>::NativeValue(
          scope.GetIsolate(), effect_options, exception_state);
  EXPECT_FALSE(exception_state.HadException());

  HeapVector<ScriptValue> blink_keyframes = {
      V8ObjectBuilder(script_state)
          .AddString("width", "100px")
          .AddString("composite", "replace")
          .GetScriptValue(),
      V8ObjectBuilder(script_state).AddString("width", "0px").GetScriptValue()};

  ScriptValue js_keyframes(
      scope.GetIsolate(),
      ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));

  KeyframeEffect* effect = CreateAnimationFromOption(
      script_state, element.Get(), js_keyframes, effect_options_dictionary);
  EXPECT_EQ("add", effect->composite());

  PropertyHandle property(GetCSSPropertyWidth());
  const PropertySpecificKeyframeVector& keyframes =
      *effect->Model()->GetPropertySpecificKeyframes(property);

  EXPECT_EQ(EffectModel::kCompositeReplace, keyframes[0]->Composite());
  EXPECT_EQ(EffectModel::kCompositeAdd, keyframes[1]->Composite());
}

TEST_F(AnimationKeyframeEffectV8Test, CanSetDuration) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
  double duration = 2000;

  KeyframeEffect* animation = CreateAnimationFromTiming(
      script_state, element.Get(), js_keyframes, duration);

  EXPECT_TIMEDELTA(AnimationTimeDelta::FromMillisecondsD(duration),
                   animation->SpecifiedTiming().iteration_duration.value());
}

TEST_F(AnimationKeyframeEffectV8Test, CanOmitSpecifiedDuration) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
  KeyframeEffect* animation =
      CreateAnimation(script_state, element.Get(), js_keyframes);
  EXPECT_FALSE(animation->SpecifiedTiming().iteration_duration);
}

TEST_F(AnimationKeyframeEffectV8Test, SpecifiedGetters) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());

  v8::Local<v8::Object> timing_input = v8::Object::New(scope.GetIsolate());
  SetV8ObjectPropertyAsNumber(scope.GetIsolate(), timing_input, "delay", 2);
  SetV8ObjectPropertyAsNumber(scope.GetIsolate(), timing_input, "endDelay",
                              0.5);
  SetV8ObjectPropertyAsString(scope.GetIsolate(), timing_input, "fill",
                              "backwards");
  SetV8ObjectPropertyAsNumber(scope.GetIsolate(), timing_input,
                              "iterationStart", 2);
  SetV8ObjectPropertyAsNumber(scope.GetIsolate(), timing_input, "iterations",
                              10);
  SetV8ObjectPropertyAsString(scope.GetIsolate(), timing_input, "direction",
                              "reverse");
  SetV8ObjectPropertyAsString(scope.GetIsolate(), timing_input, "easing",
                              "ease-in-out");
  DummyExceptionStateForTesting exception_state;
  KeyframeEffectOptions* timing_input_dictionary =
      NativeValueTraits<KeyframeEffectOptions>::NativeValue(
          scope.GetIsolate(), timing_input, exception_state);
  EXPECT_FALSE(exception_state.HadException());

  KeyframeEffect* animation = CreateAnimationFromOption(
      script_state, element.Get(), js_keyframes, timing_input_dictionary);

  EffectTiming* timing = animation->getTiming();
  EXPECT_EQ(2, timing->delay());
  EXPECT_EQ(0.5, timing->endDelay());
  EXPECT_EQ("backwards", timing->fill());
  EXPECT_EQ(2, timing->iterationStart());
  EXPECT_EQ(10, timing->iterations());
  EXPECT_EQ("reverse", timing->direction());
  EXPECT_EQ("ease-in-out", timing->easing());
}

TEST_F(AnimationKeyframeEffectV8Test, SpecifiedDurationGetter) {
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());

  v8::Local<v8::Object> timing_input_with_duration =
      v8::Object::New(scope.GetIsolate());
  SetV8ObjectPropertyAsNumber(scope.GetIsolate(), timing_input_with_duration,
                              "duration", 2.5);
  DummyExceptionStateForTesting exception_state;
  KeyframeEffectOptions* timing_input_dictionary_with_duration =
      NativeValueTraits<KeyframeEffectOptions>::NativeValue(
          scope.GetIsolate(), timing_input_with_duration, exception_state);
  EXPECT_FALSE(exception_state.HadException());

  KeyframeEffect* animation_with_duration =
      CreateAnimationFromOption(script_state, element.Get(), js_keyframes,
                                timing_input_dictionary_with_duration);

  EffectTiming* specified_with_duration = animation_with_duration->getTiming();
  UnrestrictedDoubleOrString duration = specified_with_duration->duration();
  EXPECT_TRUE(duration.IsUnrestrictedDouble());
  EXPECT_EQ(2.5, duration.GetAsUnrestrictedDouble());
  EXPECT_FALSE(duration.IsString());

  v8::Local<v8::Object> timing_input_no_duration =
      v8::Object::New(scope.GetIsolate());
  KeyframeEffectOptions* timing_input_dictionary_no_duration =
      NativeValueTraits<KeyframeEffectOptions>::NativeValue(
          scope.GetIsolate(), timing_input_no_duration, exception_state);
  EXPECT_FALSE(exception_state.HadException());

  KeyframeEffect* animation_no_duration =
      CreateAnimationFromOption(script_state, element.Get(), js_keyframes,
                                timing_input_dictionary_no_duration);

  EffectTiming* specified_no_duration = animation_no_duration->getTiming();
  UnrestrictedDoubleOrString duration2 = specified_no_duration->duration();
  EXPECT_FALSE(duration2.IsUnrestrictedDouble());
  EXPECT_TRUE(duration2.IsString());
  EXPECT_EQ("auto", duration2.GetAsString());
}

TEST_F(AnimationKeyframeEffectV8Test, SetKeyframesAdditiveCompositeOperation) {
  // AnimationWorklet also needs to be disabled since it depends on
  // WebAnimationsAPI and prevents us from turning it off if enabled.
  ScopedAnimationWorkletForTest no_animation_worklet(false);
  ScopedWebAnimationsAPIForTest no_web_animations(false);
  V8TestingScope scope;
  ScriptState* script_state = scope.GetScriptState();
  ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
  v8::Local<v8::Object> timing_input = v8::Object::New(scope.GetIsolate());
  DummyExceptionStateForTesting exception_state;
  KeyframeEffectOptions* timing_input_dictionary =
      NativeValueTraits<KeyframeEffectOptions>::NativeValue(
          scope.GetIsolate(), timing_input, exception_state);
  ASSERT_FALSE(exception_state.HadException());

  // Since there are no CSS-targeting keyframes, we can create a KeyframeEffect
  // with composite = 'add'.
  timing_input_dictionary->setComposite("add");
  KeyframeEffect* effect = CreateAnimationFromOption(
      script_state, element.Get(), js_keyframes, timing_input_dictionary);
  EXPECT_EQ(effect->Model()->Composite(), EffectModel::kCompositeAdd);

  // But if we then setKeyframes with CSS-targeting keyframes, the composite
  // should fallback to 'replace'.
  HeapVector<ScriptValue> blink_keyframes = {
      V8ObjectBuilder(script_state).AddString("width", "10px").GetScriptValue(),
      V8ObjectBuilder(script_state).AddString("width", "0px").GetScriptValue()};
  ScriptValue new_js_keyframes(
      scope.GetIsolate(),
      ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
  effect->setKeyframes(script_state, new_js_keyframes, exception_state);
  ASSERT_FALSE(exception_state.HadException());
  EXPECT_EQ(effect->Model()->Composite(), EffectModel::kCompositeReplace);
}

TEST_F(KeyframeEffectTest, TimeToEffectChange) {
  Timing timing;
  timing.iteration_duration = AnimationTimeDelta::FromSecondsD(100);
  timing.start_delay = 100;
  timing.end_delay = 100;
  timing.fill_mode = Timing::FillMode::NONE;
  auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
      nullptr, CreateEmptyEffectModel(), timing);
  Animation* animation = GetDocument().Timeline().Play(keyframe_effect);

  // Beginning of the animation.
  EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
                   keyframe_effect->TimeToForwardsEffectChange());
  EXPECT_EQ(AnimationTimeDelta::Max(),
            keyframe_effect->TimeToReverseEffectChange());

  // End of the before phase.
  animation->setCurrentTime(CSSNumberish::FromDouble(100000));
  EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
                   keyframe_effect->TimeToForwardsEffectChange());
  EXPECT_TIMEDELTA(AnimationTimeDelta(),
                   keyframe_effect->TimeToReverseEffectChange());

  // Nearing the end of the active phase.
  animation->setCurrentTime(CSSNumberish::FromDouble(199000));
  EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(1),
                   keyframe_effect->TimeToForwardsEffectChange());
  EXPECT_TIMEDELTA(AnimationTimeDelta(),
                   keyframe_effect->TimeToReverseEffectChange());

  // End of the active phase.
  animation->setCurrentTime(CSSNumberish::FromDouble(200000));
  EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
                   keyframe_effect->TimeToForwardsEffectChange());
  EXPECT_TIMEDELTA(AnimationTimeDelta(),
                   keyframe_effect->TimeToReverseEffectChange());

  // End of the animation.
  animation->setCurrentTime(CSSNumberish::FromDouble(300000));
  EXPECT_EQ(AnimationTimeDelta::Max(),
            keyframe_effect->TimeToForwardsEffectChange());
  EXPECT_TIMEDELTA(AnimationTimeDelta::FromSecondsD(100),
                   keyframe_effect->TimeToReverseEffectChange());
}

TEST_F(KeyframeEffectTest, CheckCanStartAnimationOnCompositorNoKeyframes) {
  ASSERT_TRUE(element);

  const double animation_playback_rate = 1;
  Timing timing;

  // No keyframes results in an invalid animation.
  {
    auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
        element, CreateEmptyEffectModel(), timing);
    EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
                    nullptr, animation_playback_rate) &
                CompositorAnimations::kInvalidAnimationOrEffect);
  }

  // Keyframes but no properties results in an invalid animation.
  {
    StringKeyframeVector keyframes(2);
    keyframes[0] = MakeGarbageCollected<StringKeyframe>();
    keyframes[0]->SetOffset(0.0);
    keyframes[1] = MakeGarbageCollected<StringKeyframe>();
    keyframes[1]->SetOffset(1.0);
    auto* effect_model =
        MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);

    auto* keyframe_effect =
        MakeGarbageCollected<KeyframeEffect>(element, effect_model, timing);
    EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
                    nullptr, animation_playback_rate) &
                CompositorAnimations::kInvalidAnimationOrEffect);
  }
}

TEST_F(KeyframeEffectTest, CheckCanStartAnimationOnCompositorNoTarget) {
  const double animation_playback_rate = 1;
  Timing timing;

  // No target results in an invalid animation.
  StringKeyframeVector keyframes(2);
  keyframes[0] = MakeGarbageCollected<StringKeyframe>();
  keyframes[0]->SetOffset(0.0);
  keyframes[0]->SetCSSPropertyValue(CSSPropertyID::kLeft, "0px",
                                    SecureContextMode::kInsecureContext,
                                    nullptr);
  keyframes[1] = MakeGarbageCollected<StringKeyframe>();
  keyframes[1]->SetOffset(1.0);
  keyframes[1]->SetCSSPropertyValue(CSSPropertyID::kLeft, "10px",
                                    SecureContextMode::kInsecureContext,
                                    nullptr);
  auto* effect_model =
      MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);

  auto* keyframe_effect =
      MakeGarbageCollected<KeyframeEffect>(nullptr, effect_model, timing);
  EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
                  nullptr, animation_playback_rate) &
              CompositorAnimations::kInvalidAnimationOrEffect);
}

TEST_F(KeyframeEffectTest, CheckCanStartAnimationOnCompositorBadTarget) {
  const double animation_playback_rate = 1;
  Timing timing;

  StringKeyframeVector keyframes(2);
  keyframes[0] = MakeGarbageCollected<StringKeyframe>();
  keyframes[0]->SetOffset(0.0);
  keyframes[0]->SetCSSPropertyValue(CSSPropertyID::kLeft, "0px",
                                    SecureContextMode::kInsecureContext,
                                    nullptr);
  keyframes[1] = MakeGarbageCollected<StringKeyframe>();
  keyframes[1]->SetOffset(1.0);
  keyframes[1]->SetCSSPropertyValue(CSSPropertyID::kLeft, "10px",
                                    SecureContextMode::kInsecureContext,
                                    nullptr);
  auto* effect_model =
      MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
  auto* keyframe_effect =
      MakeGarbageCollected<KeyframeEffect>(element, effect_model, timing);

  // If the target has a CSS offset we can't composite it.
  element->SetInlineStyleProperty(CSSPropertyID::kOffsetPosition, "50px 50px");
  UpdateAllLifecyclePhasesForTest();

  ASSERT_TRUE(element->GetComputedStyle()->HasOffset());
  EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
                  nullptr, animation_playback_rate) &
              CompositorAnimations::kTargetHasCSSOffset);

  // If the target has multiple transform properties we can't composite it.
  element->SetInlineStyleProperty(CSSPropertyID::kRotate, "90deg");
  element->SetInlineStyleProperty(CSSPropertyID::kScale, "2 1");
  UpdateAllLifecyclePhasesForTest();

  EXPECT_TRUE(keyframe_effect->CheckCanStartAnimationOnCompositor(
                  nullptr, animation_playback_rate) &
              CompositorAnimations::kTargetHasMultipleTransformProperties);
}

TEST_F(KeyframeEffectTest, TranslationTransformsPreserveAxisAlignment) {
  auto* effect =
      GetTwoFrameEffect(CSSPropertyID::kTransform, "translate(10px, 10px)",
                        "translate(20px, 20px)");
  EXPECT_TRUE(effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
}

TEST_F(KeyframeEffectTest, ScaleTransformsPreserveAxisAlignment) {
  auto* effect =
      GetTwoFrameEffect(CSSPropertyID::kTransform, "scale(2)", "scale(3)");
  EXPECT_TRUE(effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
}

TEST_F(KeyframeEffectTest, RotationTransformsDoNotPreserveAxisAlignment) {
  auto* effect = GetTwoFrameEffect(CSSPropertyID::kTransform, "rotate(10deg)",
                                   "rotate(20deg)");

  EXPECT_FALSE(
      effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
}

TEST_F(KeyframeEffectTest, RotationsDoNotPreserveAxisAlignment) {
  auto* effect = GetTwoFrameEffect(CSSPropertyID::kRotate, "10deg", "20deg");
  EXPECT_FALSE(
      effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
}

}  // namespace blink
