blob: 9a53c8679eb67309c0dfc9a39c1a7378084f8e73 [file] [log] [blame]
// Copyright (c) 2012 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 "ui/gfx/animation/slide_animation.h"
#include <memory>
#include "base/macros.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/animation/animation_test_api.h"
#include "ui/gfx/animation/test_animation_delegate.h"
namespace gfx {
////////////////////////////////////////////////////////////////////////////////
// SlideAnimationTest
class SlideAnimationTest : public testing::Test {
public:
void RunAnimationFor(base::TimeDelta duration) {
base::TimeTicks now = base::TimeTicks::Now();
animation_api_->SetStartTime(now);
animation_api_->Step(now + duration);
}
std::unique_ptr<AnimationTestApi> animation_api_;
std::unique_ptr<SlideAnimation> slide_animation_;
protected:
SlideAnimationTest()
: task_environment_(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {
slide_animation_ = std::make_unique<SlideAnimation>(nullptr);
animation_api_ = std::make_unique<AnimationTestApi>(slide_animation_.get());
}
private:
base::test::SingleThreadTaskEnvironment task_environment_;
};
// Tests animation construction.
TEST_F(SlideAnimationTest, InitialState) {
// By default, slide animations are 60 Hz, so the timer interval should be
// 1/60th of a second.
EXPECT_EQ(1000 / 60, slide_animation_->timer_interval().InMilliseconds());
// Duration defaults to 120 ms.
EXPECT_EQ(120, slide_animation_->GetSlideDuration().InMilliseconds());
// Slide is neither showing nor closing.
EXPECT_FALSE(slide_animation_->IsShowing());
EXPECT_FALSE(slide_animation_->IsClosing());
// Starts at 0.
EXPECT_EQ(0.0, slide_animation_->GetCurrentValue());
}
TEST_F(SlideAnimationTest, Basics) {
// Use linear tweening to make the math easier below.
slide_animation_->SetTweenType(Tween::LINEAR);
// Duration can be set after construction.
slide_animation_->SetSlideDuration(base::Milliseconds(100));
EXPECT_EQ(100, slide_animation_->GetSlideDuration().InMilliseconds());
// Show toggles the appropriate state.
slide_animation_->Show();
EXPECT_TRUE(slide_animation_->IsShowing());
EXPECT_FALSE(slide_animation_->IsClosing());
// Simulate running the animation.
RunAnimationFor(base::Milliseconds(50));
EXPECT_EQ(0.5, slide_animation_->GetCurrentValue());
// We can start hiding mid-way through the animation.
slide_animation_->Hide();
EXPECT_FALSE(slide_animation_->IsShowing());
EXPECT_TRUE(slide_animation_->IsClosing());
// Reset stops the animation.
slide_animation_->Reset();
EXPECT_EQ(0.0, slide_animation_->GetCurrentValue());
EXPECT_FALSE(slide_animation_->IsShowing());
EXPECT_FALSE(slide_animation_->IsClosing());
}
// Tests that delegate is not notified when animation is running and is deleted.
// (Such a scenario would cause problems for BoundsAnimator).
TEST_F(SlideAnimationTest, DontNotifyOnDelete) {
TestAnimationDelegate delegate;
std::unique_ptr<SlideAnimation> animation(new SlideAnimation(&delegate));
// Start the animation.
animation->Show();
// Delete the animation.
animation.reset();
// Make sure the delegate wasn't notified.
EXPECT_FALSE(delegate.finished());
EXPECT_FALSE(delegate.canceled());
}
// Tests that animations which are started partway and have a dampening factor
// of 1 progress linearly.
TEST_F(SlideAnimationTest,
AnimationWithPartialProgressAndDefaultDampeningFactor) {
slide_animation_->SetTweenType(Tween::LINEAR);
slide_animation_->SetSlideDuration(base::Milliseconds(100));
slide_animation_->Show();
EXPECT_EQ(slide_animation_->GetCurrentValue(), 0.0);
// Advance the animation to halfway done.
RunAnimationFor(base::Milliseconds(50));
EXPECT_EQ(0.5, slide_animation_->GetCurrentValue());
// Reverse the animation and run it for half of the remaining duration.
slide_animation_->Hide();
RunAnimationFor(base::Milliseconds(25));
EXPECT_EQ(0.25, slide_animation_->GetCurrentValue());
// Reverse the animation again and run it for half of the remaining duration.
slide_animation_->Show();
RunAnimationFor(base::Milliseconds(37.5));
EXPECT_EQ(0.625, slide_animation_->GetCurrentValue());
}
// Tests that animations which are started partway and have a dampening factor
// of >1 progress sub-leanearly.
TEST_F(SlideAnimationTest,
AnimationWithPartialProgressAndNonDefaultDampeningFactor) {
slide_animation_->SetTweenType(Tween::LINEAR);
slide_animation_->SetDampeningValue(2.0);
slide_animation_->SetSlideDuration(base::Milliseconds(100));
slide_animation_->Show();
// Advance the animation to halfway done.
RunAnimationFor(base::Milliseconds(50));
EXPECT_EQ(0.5, slide_animation_->GetCurrentValue());
// Reverse the animation and run it for the same duration, it should be
// sub-linear with dampening.
slide_animation_->Hide();
RunAnimationFor(base::Milliseconds(50));
EXPECT_GT(slide_animation_->GetCurrentValue(), 0);
}
// Tests that a mostly complete dampened animation takes a sub-linear
// amount of time to complete.
TEST_F(SlideAnimationTest, DampenedAnimationMostlyComplete) {
slide_animation_->SetTweenType(Tween::LINEAR);
slide_animation_->SetDampeningValue(2.0);
slide_animation_->SetSlideDuration(base::Milliseconds(100));
slide_animation_->Show();
// Advance the animation to 1/10th of the way done.
RunAnimationFor(base::Milliseconds(10));
EXPECT_EQ(0.1, slide_animation_->GetCurrentValue());
// Reverse the animation and run it for 1/10th of the duration, it should not
// be complete.
slide_animation_->Hide();
RunAnimationFor(base::Milliseconds(10));
EXPECT_GT(slide_animation_->GetCurrentValue(), 0);
// Finish the animation and set up the test for a mostly complete show
// animation.
RunAnimationFor(base::Milliseconds(100));
EXPECT_EQ(0, slide_animation_->GetCurrentValue());
slide_animation_->Show();
// Advance the animation to 9/10th of the way done.
RunAnimationFor(base::Milliseconds(90));
EXPECT_EQ(0.9, slide_animation_->GetCurrentValue());
// Hide and then Show the animation to force the duration to be recalculated,
// then show for 1/10th of the duration and test that the animation is not
// complete.
slide_animation_->Hide();
slide_animation_->Show();
RunAnimationFor(base::Milliseconds(10));
EXPECT_LT(slide_animation_->GetCurrentValue(), 1);
RunAnimationFor(base::Milliseconds(40));
EXPECT_EQ(1, slide_animation_->GetCurrentValue());
}
// Tests that a mostly incomplete dampened animation takes a sub-linear amount
// of time to complete.
TEST_F(SlideAnimationTest, DampenedAnimationMostlyIncomplete) {
slide_animation_->SetTweenType(Tween::LINEAR);
slide_animation_->SetDampeningValue(2.0);
slide_animation_->SetSlideDuration(base::Milliseconds(100));
slide_animation_->Show();
// Advance the animation to 1/10th of the way done.
RunAnimationFor(base::Milliseconds(10));
EXPECT_EQ(0.1, slide_animation_->GetCurrentValue());
// Hide and then Show the animation to force the duration to be recalculated,
// then show for 9/10th of the duration and test that the animation is not
// complete.
slide_animation_->Hide();
slide_animation_->Show();
RunAnimationFor(base::Milliseconds(90));
EXPECT_LT(slide_animation_->GetCurrentValue(), 1);
// Finish the animation and set up the test for a mostly incomplete hide
// animation.
RunAnimationFor(base::Milliseconds(100));
EXPECT_EQ(1, slide_animation_->GetCurrentValue());
slide_animation_->Hide();
RunAnimationFor(base::Milliseconds(10));
EXPECT_EQ(0.9, slide_animation_->GetCurrentValue());
// Show and then hide the animation to recompute the duration, then run the
// animation for 9/10ths of the duration and test that the animation is not
// complete.
slide_animation_->Show();
slide_animation_->Hide();
RunAnimationFor(base::Milliseconds(90));
EXPECT_GT(slide_animation_->GetCurrentValue(), 0);
RunAnimationFor(base::Milliseconds(100));
EXPECT_EQ(0, slide_animation_->GetCurrentValue());
}
TEST_F(SlideAnimationTest, HideFromHalfway) {
auto container = base::MakeRefCounted<AnimationContainer>();
AnimationContainerTestApi test_api(container.get());
slide_animation_->SetContainer(container.get());
slide_animation_->SetTweenType(Tween::LINEAR);
slide_animation_->SetSlideDuration(base::Milliseconds(100));
slide_animation_->Reset(0.5);
EXPECT_FALSE(slide_animation_->is_animating());
EXPECT_EQ(0.5, slide_animation_->GetCurrentValue());
slide_animation_->Hide();
ASSERT_TRUE(slide_animation_->is_animating());
test_api.IncrementTime(base::Milliseconds(100));
EXPECT_EQ(0.0, slide_animation_->GetCurrentValue());
}
} // namespace gfx