blob: bc5e1787e2be1a63e448a0256adfb79efb4459e0 [file] [log] [blame]
// Copyright 2021 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/views/animation/widget_fade_animator.h"
#include <memory>
#include "base/test/bind.h"
#include "base/time/time.h"
#include "ui/gfx/animation/animation_test_api.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
namespace views {
namespace {
constexpr base::TimeDelta kFadeDuration =
base::TimeDelta::FromMilliseconds(1000);
constexpr base::TimeDelta kHalfFadeDuration = kFadeDuration / 2;
class TestWidgetFadeAnimator : public WidgetFadeAnimator {
public:
using WidgetFadeAnimator::WidgetFadeAnimator;
~TestWidgetFadeAnimator() override = default;
void AnimationContainerWasSet(gfx::AnimationContainer* container) override {
WidgetFadeAnimator::AnimationContainerWasSet(container);
container_test_api_.reset();
if (container) {
container_test_api_ =
std::make_unique<gfx::AnimationContainerTestApi>(container);
}
}
gfx::AnimationContainerTestApi* test_api() {
return container_test_api_.get();
}
private:
std::unique_ptr<gfx::AnimationContainerTestApi> container_test_api_;
};
} // namespace
class WidgetFadeAnimatorTest : public test::WidgetTest {
public:
void SetUp() override {
test::WidgetTest::SetUp();
widget_ = CreateTestWidget(Widget::InitParams::Type::TYPE_WINDOW);
delegate_ = std::make_unique<TestWidgetFadeAnimator>(widget_.get());
delegate_->set_fade_in_duration(kFadeDuration);
delegate_->set_fade_out_duration(kFadeDuration);
}
void TearDown() override {
if (widget_ && !widget_->IsClosed())
widget_->CloseNow();
test::WidgetTest::TearDown();
}
protected:
std::unique_ptr<Widget> widget_;
std::unique_ptr<TestWidgetFadeAnimator> delegate_;
};
TEST_F(WidgetFadeAnimatorTest, FadeIn) {
EXPECT_FALSE(widget_->IsVisible());
delegate_->FadeIn();
// Fade in should set visibility and opacity to some small value.
EXPECT_TRUE(widget_->IsVisible());
EXPECT_TRUE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, FadeInAnimationProgressesToEnd) {
delegate_->FadeIn();
// Note that there is currently no way to *read* a widget's opacity, so we can
// only verify that the widget's visibility changes appropriately at the
// beginning and end of each animation.
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_TRUE(widget_->IsVisible());
EXPECT_TRUE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_TRUE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, FadeOut) {
widget_->Show();
EXPECT_TRUE(widget_->IsVisible());
delegate_->FadeOut();
// Fade in should set visibility and opacity to some small value.
EXPECT_TRUE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_TRUE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, FadeOutAnimationProgressesToEnd) {
widget_->Show();
delegate_->FadeOut();
// Note that there is currently no way to *read* a widget's opacity, so we can
// only verify that the widget's visibility changes appropriately at the
// beginning and end of each animation.
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_TRUE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_TRUE(delegate_->IsFadingOut());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_FALSE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, CancelFadeOutAtStart) {
widget_->Show();
delegate_->FadeOut();
delegate_->CancelFadeOut();
EXPECT_TRUE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, CancelFadeOutInMiddle) {
widget_->Show();
delegate_->FadeOut();
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
delegate_->CancelFadeOut();
EXPECT_TRUE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, CancelFadeOutAtEndHasNoEffect) {
widget_->Show();
delegate_->FadeOut();
delegate_->test_api()->IncrementTime(kFadeDuration);
delegate_->CancelFadeOut();
EXPECT_FALSE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, CancelFadeOutHasNoEffectIfFadingIn) {
delegate_->FadeIn();
delegate_->CancelFadeOut();
EXPECT_TRUE(widget_->IsVisible());
EXPECT_TRUE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
delegate_->CancelFadeOut();
EXPECT_TRUE(widget_->IsVisible());
EXPECT_TRUE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
delegate_->CancelFadeOut();
EXPECT_TRUE(widget_->IsVisible());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, FadeOutClosesWidget) {
delegate_->set_close_on_hide(true);
widget_->Show();
delegate_->FadeOut();
delegate_->test_api()->IncrementTime(kFadeDuration);
EXPECT_TRUE(widget_->IsClosed());
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, WidgetClosedDuringFade) {
widget_->Show();
delegate_->FadeOut();
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
widget_->CloseNow();
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, WidgetDestroyedDuringFade) {
widget_->Show();
delegate_->FadeOut();
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
widget_->Close();
widget_.reset();
EXPECT_FALSE(delegate_->IsFadingOut());
}
TEST_F(WidgetFadeAnimatorTest, AnimatorDestroyedDuringFade) {
delegate_->FadeIn();
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
delegate_.reset();
}
TEST_F(WidgetFadeAnimatorTest, FadeOutInterruptsFadeIn) {
delegate_->FadeIn();
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
delegate_->FadeOut();
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_TRUE(delegate_->IsFadingOut());
EXPECT_TRUE(widget_->IsVisible());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_TRUE(delegate_->IsFadingOut());
EXPECT_TRUE(widget_->IsVisible());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
EXPECT_FALSE(widget_->IsVisible());
}
TEST_F(WidgetFadeAnimatorTest, FadeInInterruptsFadeOut) {
widget_->Show();
delegate_->FadeOut();
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
delegate_->FadeIn();
EXPECT_TRUE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
EXPECT_TRUE(widget_->IsVisible());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_TRUE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
EXPECT_TRUE(widget_->IsVisible());
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_FALSE(delegate_->IsFadingIn());
EXPECT_FALSE(delegate_->IsFadingOut());
EXPECT_TRUE(widget_->IsVisible());
}
TEST_F(WidgetFadeAnimatorTest, FadeInCallback) {
int called_count = 0;
WidgetFadeAnimator::FadeType anim_type = WidgetFadeAnimator::FadeType::kNone;
auto subscription =
delegate_->AddFadeCompleteCallback(base::BindLambdaForTesting(
[&](WidgetFadeAnimator*,
WidgetFadeAnimator::FadeType animation_type) {
++called_count;
anim_type = animation_type;
}));
delegate_->FadeIn();
EXPECT_EQ(0, called_count);
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_EQ(0, called_count);
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_EQ(1, called_count);
EXPECT_EQ(WidgetFadeAnimator::FadeType::kFadeIn, anim_type);
}
TEST_F(WidgetFadeAnimatorTest, FadeOutCallback) {
int called_count = 0;
WidgetFadeAnimator::FadeType anim_type = WidgetFadeAnimator::FadeType::kNone;
auto subscription =
delegate_->AddFadeCompleteCallback(base::BindLambdaForTesting(
[&](WidgetFadeAnimator*,
WidgetFadeAnimator::FadeType animation_type) {
++called_count;
anim_type = animation_type;
}));
widget_->Show();
delegate_->FadeOut();
EXPECT_EQ(0, called_count);
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_EQ(0, called_count);
delegate_->test_api()->IncrementTime(kHalfFadeDuration);
EXPECT_EQ(1, called_count);
EXPECT_EQ(WidgetFadeAnimator::FadeType::kFadeOut, anim_type);
}
} // namespace views