blob: d158fd51b658277217af55a3e1e969cfedb31621 [file] [log] [blame]
// Copyright 2019 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 "chrome/browser/ui/views/tabs/tab_strip_animator.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "chrome/browser/ui/views/tabs/tab_animation.h"
#include "chrome/browser/ui/views/tabs/tab_animation_state.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class TabClosedDetector {
public:
void NotifyTabClosed() { was_closed_ = true; }
bool was_closed_ = false;
};
} // namespace
class TabStripAnimatorTest : public testing::Test {
public:
TabStripAnimatorTest()
: env_(base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
base::test::ScopedTaskEnvironment::NowSource::
MAIN_THREAD_MOCK_TIME),
animator_(
base::BindRepeating(&TabStripAnimatorTest::OnAnimationProgressed,
base::Unretained(this))),
has_animated_(false) {}
void OnAnimationProgressed() { has_animated_ = true; }
float OpennessOf(TabAnimationState state) { return state.openness_; }
float PinnednessOf(TabAnimationState state) { return state.pinnedness_; }
float ActivenessOf(TabAnimationState state) { return state.activeness_; }
base::test::ScopedTaskEnvironment env_;
TabStripAnimator animator_;
bool has_animated_;
};
TEST_F(TabStripAnimatorTest, StaticStripIsNotAnimating) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kPinned);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_FALSE(has_animated_);
}
TEST_F(TabStripAnimatorTest, InsertTabAnimation) {
animator_.InsertTabAt(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_TRUE(animator_.IsAnimating());
EXPECT_EQ(1u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(0.0f, OpennessOf(animator_.GetCurrentTabStates()[0]));
env_.FastForwardBy(2 * TabAnimation::kAnimationDuration);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(1u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_TRUE(has_animated_);
}
TEST_F(TabStripAnimatorTest, ChangeActiveTab) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(1, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
animator_.SetActiveTab(0, 1);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
}
TEST_F(TabStripAnimatorTest, PinAndUnpinTab) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_EQ(0.0f, PinnednessOf(animator_.GetCurrentTabStates()[0]));
animator_.SetPinnednessNoAnimation(0,
TabAnimationState::TabPinnedness::kPinned);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(1.0f, PinnednessOf(animator_.GetCurrentTabStates()[0]));
animator_.SetPinnednessNoAnimation(
0, TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_EQ(0.0f, PinnednessOf(animator_.GetCurrentTabStates()[0]));
}
TEST_F(TabStripAnimatorTest, RemoveTabNoAnimation) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(1, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.RemoveTabNoAnimation(1);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(1u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
}
TEST_F(TabStripAnimatorTest, RemoveTabAnimation) {
TabClosedDetector second_tab;
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(
1,
base::BindOnce(&TabClosedDetector::NotifyTabClosed,
base::Unretained(&second_tab)),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.RemoveTab(1);
EXPECT_TRUE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[1]));
EXPECT_FALSE(second_tab.was_closed_);
env_.FastForwardBy(2 * TabAnimation::kAnimationDuration);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(1u, animator_.GetCurrentTabStates().size());
EXPECT_TRUE(second_tab.was_closed_);
}
TEST_F(TabStripAnimatorTest, CompleteAnimations) {
animator_.InsertTabAt(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_TRUE(animator_.IsAnimating());
EXPECT_EQ(1u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(0.0f, OpennessOf(animator_.GetCurrentTabStates()[0]));
animator_.CompleteAnimations();
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[0]));
}
TEST_F(TabStripAnimatorTest, CompleteAnimationsRemovesClosedTabs) {
TabClosedDetector second_tab;
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(
1,
base::BindOnce(&TabClosedDetector::NotifyTabClosed,
base::Unretained(&second_tab)),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.RemoveTab(1);
EXPECT_TRUE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[1]));
EXPECT_FALSE(second_tab.was_closed_);
animator_.CompleteAnimations();
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(1u, animator_.GetCurrentTabStates().size());
EXPECT_TRUE(second_tab.was_closed_);
}
TEST_F(TabStripAnimatorTest,
CompleteAnimationsWithoutDestroyingTabsDoesNotRemoveClosedTabs) {
TabClosedDetector second_tab;
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(
1,
base::BindOnce(&TabClosedDetector::NotifyTabClosed,
base::Unretained(&second_tab)),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.RemoveTab(1);
EXPECT_TRUE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(1.0f, OpennessOf(animator_.GetCurrentTabStates()[1]));
EXPECT_FALSE(second_tab.was_closed_);
animator_.CompleteAnimationsWithoutDestroyingTabs();
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_FALSE(second_tab.was_closed_);
}
TEST_F(TabStripAnimatorTest, MoveTabRight) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(1, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
animator_.MoveTabNoAnimation(0, 1);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
}
TEST_F(TabStripAnimatorTest, MoveTabLeft) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(1, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
animator_.MoveTabNoAnimation(1, 0);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
}
TEST_F(TabStripAnimatorTest, MoveTabSamePosition) {
animator_.InsertTabAtNoAnimation(0, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kActive,
TabAnimationState::TabPinnedness::kUnpinned);
animator_.InsertTabAtNoAnimation(1, base::BindOnce([]() {}),
TabAnimationState::TabActiveness::kInactive,
TabAnimationState::TabPinnedness::kUnpinned);
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
animator_.MoveTabNoAnimation(0, 0);
EXPECT_FALSE(animator_.IsAnimating());
EXPECT_EQ(2u, animator_.GetCurrentTabStates().size());
EXPECT_EQ(1.0f, ActivenessOf(animator_.GetCurrentTabStates()[0]));
EXPECT_EQ(0.0f, ActivenessOf(animator_.GetCurrentTabStates()[1]));
}