| // 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 "chrome/browser/ui/views/tabs/overflow_view.h" |
| |
| #include <algorithm> |
| #include <memory> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/views/layout/fill_layout.h" |
| #include "ui/views/layout/flex_layout_types.h" |
| #include "ui/views/layout/layout_types.h" |
| #include "ui/views/test/test_views.h" |
| #include "ui/views/view_class_properties.h" |
| |
| class OverflowViewTest : public testing::Test { |
| public: |
| OverflowViewTest() = default; |
| ~OverflowViewTest() override = default; |
| |
| void SetUp() override { |
| parent_view_ = std::make_unique<views::View>(); |
| parent_view_->SetLayoutManager(std::make_unique<views::FillLayout>()); |
| parent_view_->SetSize(kDefaultParentSize); |
| } |
| |
| void TearDown() override { |
| parent_view_.reset(); |
| overflow_view_ = nullptr; |
| } |
| |
| void Init(const gfx::Size& primary_minimum_size, |
| const gfx::Size& primary_preferred_size, |
| const gfx::Size& indicator_minimum_size, |
| const gfx::Size& indicator_preferred_size) { |
| auto primary_view = |
| std::make_unique<views::StaticSizedView>(primary_preferred_size); |
| primary_view->set_minimum_size(primary_minimum_size); |
| primary_view_ = primary_view.get(); |
| auto indicator_view = |
| std::make_unique<views::StaticSizedView>(indicator_preferred_size); |
| indicator_view->set_minimum_size(indicator_minimum_size); |
| indicator_view_ = indicator_view.get(); |
| overflow_view_ = parent_view_->AddChildView(std::make_unique<OverflowView>( |
| std::move(primary_view), std::move(indicator_view))); |
| } |
| |
| protected: |
| static int InterpolateByTens(int minimum, |
| int preferred, |
| views::SizeBound bound) { |
| if (!bound.is_bounded()) |
| return preferred; |
| if (bound.value() <= minimum) |
| return minimum; |
| if (bound.value() >= preferred) |
| return preferred; |
| return minimum + 10 * ((bound.value() - minimum) / 10); |
| } |
| |
| // Flex rule where height and width step by 10s up from minimum to preferred |
| // size. |
| static gfx::Size StepwiseFlexRule(const views::View* view, |
| const views::SizeBounds& bounds) { |
| const gfx::Size preferred = view->GetPreferredSize(); |
| const gfx::Size minimum = view->GetMinimumSize(); |
| return gfx::Size( |
| InterpolateByTens(minimum.width(), preferred.width(), bounds.width()), |
| InterpolateByTens(minimum.height(), preferred.height(), |
| bounds.height())); |
| } |
| |
| // Flex rule where the vertical axis contracts from preferred to minimum size |
| // by the same percentage as the horizontal axis is shrunk between preferred |
| // and minimum size. So for instance, if the horizontal axis is constrained |
| // by 20 DIPs and the difference between minimum and preferred is 80 DIPs, |
| // then the vertical axis will be 75% of the way between minimum and preferred |
| // size. |
| static gfx::Size ProportionalFlexRule(const views::View* view, |
| const views::SizeBounds& bounds) { |
| const gfx::Size preferred = view->GetPreferredSize(); |
| const gfx::Size minimum = view->GetMinimumSize(); |
| const int width = |
| std::max(minimum.width(), bounds.width().min_of(preferred.width())); |
| DCHECK_GT(preferred.width(), minimum.width()); |
| double ratio = static_cast<double>(width - minimum.width()) / |
| (preferred.width() - minimum.width()); |
| const int height = bounds.height().min_of( |
| minimum.height() + |
| base::ClampRound(ratio * (preferred.height() - minimum.height()))); |
| return gfx::Size(width, height); |
| } |
| |
| static constexpr gfx::Size kDefaultParentSize{100, 70}; |
| static constexpr gfx::Size kPreferredSize{120, 80}; |
| static constexpr gfx::Size kMinimumSize{40, 20}; |
| static constexpr gfx::Size kPreferredSize2{55, 50}; |
| static constexpr gfx::Size kMinimumSize2{25, 30}; |
| std::unique_ptr<views::View> parent_view_; |
| OverflowView* overflow_view_ = nullptr; |
| views::StaticSizedView* primary_view_ = nullptr; |
| views::StaticSizedView* indicator_view_ = nullptr; |
| }; |
| |
| constexpr gfx::Size OverflowViewTest::kDefaultParentSize; |
| constexpr gfx::Size OverflowViewTest::kPreferredSize; |
| constexpr gfx::Size OverflowViewTest::kMinimumSize; |
| constexpr gfx::Size OverflowViewTest::kPreferredSize2; |
| constexpr gfx::Size OverflowViewTest::kMinimumSize2; |
| |
| TEST_F(OverflowViewTest, SizesNoFlexRules) { |
| Init(kMinimumSize, kPreferredSize, kMinimumSize2, kPreferredSize2); |
| const gfx::Size expected_min( |
| kMinimumSize2.width(), |
| std::max(kMinimumSize.height(), kMinimumSize2.height())); |
| EXPECT_EQ(expected_min, overflow_view_->GetMinimumSize()); |
| EXPECT_EQ(kPreferredSize, overflow_view_->GetPreferredSize()); |
| } |
| |
| TEST_F(OverflowViewTest, SizesNoFlexRulesIndicatorIsLarger) { |
| Init(kMinimumSize2, kPreferredSize2, kMinimumSize, kPreferredSize); |
| const gfx::Size expected_min( |
| kMinimumSize.width(), |
| std::max(kMinimumSize.height(), kMinimumSize2.height())); |
| EXPECT_EQ(expected_min, overflow_view_->GetMinimumSize()); |
| EXPECT_EQ(kPreferredSize, overflow_view_->GetPreferredSize()); |
| EXPECT_EQ(kPreferredSize.height(), overflow_view_->GetHeightForWidth(200)); |
| } |
| |
| TEST_F(OverflowViewTest, SizesNoFlexRulesVertical) { |
| Init(kMinimumSize, kPreferredSize, kMinimumSize2, kPreferredSize2); |
| overflow_view_->SetOrientation(views::LayoutOrientation::kVertical); |
| const gfx::Size expected_min( |
| std::max(kMinimumSize.width(), kMinimumSize2.width()), |
| kMinimumSize2.height()); |
| EXPECT_EQ(expected_min, overflow_view_->GetMinimumSize()); |
| EXPECT_EQ(kPreferredSize, overflow_view_->GetPreferredSize()); |
| } |
| |
| TEST_F(OverflowViewTest, SizesNoFlexRulesIndicatorIsLargerVertical) { |
| Init(kMinimumSize2, kPreferredSize2, kMinimumSize, kPreferredSize); |
| overflow_view_->SetOrientation(views::LayoutOrientation::kVertical); |
| const gfx::Size expected_min( |
| std::max(kMinimumSize.width(), kMinimumSize2.width()), |
| kMinimumSize.height()); |
| EXPECT_EQ(expected_min, overflow_view_->GetMinimumSize()); |
| EXPECT_EQ(kPreferredSize, overflow_view_->GetPreferredSize()); |
| EXPECT_EQ(kPreferredSize.height(), overflow_view_->GetHeightForWidth(200)); |
| } |
| |
| class OverflowViewLayoutTest : public OverflowViewTest { |
| public: |
| OverflowViewLayoutTest() = default; |
| ~OverflowViewLayoutTest() override = default; |
| |
| void SetUp() override { |
| OverflowViewTest::SetUp(); |
| Init(kPrimaryMinimumSize, kPrimaryPreferredSize, kIndicatorMinimumSize, |
| kIndicatorPreferredSize); |
| } |
| |
| void Resize(gfx::Size size) { |
| parent_view_->SetSize(size); |
| parent_view_->Layout(); |
| } |
| |
| void SizeToPreferredSize() { parent_view_->SizeToPreferredSize(); } |
| |
| gfx::Rect primary_bounds() const { return primary_view_->bounds(); } |
| gfx::Rect indicator_bounds() const { return indicator_view_->bounds(); } |
| bool primary_visible() const { return primary_view_->GetVisible(); } |
| bool indicator_visible() const { return indicator_view_->GetVisible(); } |
| |
| protected: |
| static constexpr gfx::Size kPrimaryMinimumSize{80, 20}; |
| static constexpr gfx::Size kPrimaryPreferredSize{160, 30}; |
| static constexpr gfx::Size kIndicatorMinimumSize{16, 16}; |
| static constexpr gfx::Size kIndicatorPreferredSize{32, 32}; |
| |
| static gfx::Size Transpose(const gfx::Size size) { |
| return gfx::Size(size.height(), size.width()); |
| } |
| |
| static gfx::Size TransposingFlexRule(const views::View* view, |
| const views::SizeBounds& size_bounds) { |
| const gfx::Size preferred = Transpose(view->GetPreferredSize()); |
| const gfx::Size minimum = Transpose(view->GetMinimumSize()); |
| int height; |
| int width; |
| if (size_bounds.height().is_bounded()) { |
| height = std::max(minimum.height(), |
| size_bounds.height().min_of(preferred.height())); |
| } else { |
| height = preferred.height(); |
| } |
| if (size_bounds.width().is_bounded()) { |
| width = std::max(minimum.width(), |
| size_bounds.width().min_of(preferred.width())); |
| } else { |
| width = preferred.width(); |
| } |
| return gfx::Size(width, height); |
| } |
| }; |
| |
| constexpr gfx::Size OverflowViewLayoutTest::kPrimaryMinimumSize; |
| constexpr gfx::Size OverflowViewLayoutTest::kPrimaryPreferredSize; |
| constexpr gfx::Size OverflowViewLayoutTest::kIndicatorMinimumSize; |
| constexpr gfx::Size OverflowViewLayoutTest::kIndicatorPreferredSize; |
| |
| TEST_F(OverflowViewLayoutTest, SizeToPreferredSizeIndicatorSmallerThanPrimary) { |
| indicator_view_->SetPreferredSize(kIndicatorMinimumSize); |
| SizeToPreferredSize(); |
| EXPECT_EQ(gfx::Rect(kPrimaryPreferredSize), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, SizeToPreferredSizeIndicatorLargerThanPrimary) { |
| SizeToPreferredSize(); |
| gfx::Size expected = kPrimaryPreferredSize; |
| expected.SetToMax(kIndicatorPreferredSize); |
| EXPECT_EQ(gfx::Rect(expected), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, ScaleToMinimum) { |
| // Since default cross-axis alignment is stretch, the view should fill the |
| // space even if it's larger than the preferred size. |
| gfx::Size size = kPrimaryPreferredSize; |
| size.Enlarge(10, 10); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(kPrimaryPreferredSize.width(), size.height()), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| // Default behavior is to scale down smoothly between preferred and minimum |
| // size. |
| size = kPrimaryPreferredSize; |
| size.Enlarge(-10, -10); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| size = kPrimaryMinimumSize; |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| // Below minimum size, the stretch alignment means we'll compress. |
| size.Enlarge(0, -5); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, Alignment) { |
| gfx::Size size = kPrimaryPreferredSize; |
| size.Enlarge(0, 10); |
| Resize(size); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, 0), kPrimaryPreferredSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kCenter); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, 5), kPrimaryPreferredSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kEnd); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, 10), kPrimaryPreferredSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| size = kPrimaryMinimumSize; |
| size.Enlarge(0, -10); |
| Resize(size); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, 0), kPrimaryMinimumSize), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kCenter); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, -5), kPrimaryMinimumSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kEnd); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, -10), kPrimaryMinimumSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, ScaleToMinimumVertical) { |
| overflow_view_->SetOrientation(views::LayoutOrientation::kVertical); |
| |
| gfx::Size size = kPrimaryPreferredSize; |
| size.Enlarge(10, 10); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size.width(), kPrimaryPreferredSize.height()), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| // Default behavior is to scale down smoothly between preferred and minimum |
| // size. |
| size = kPrimaryPreferredSize; |
| size.Enlarge(-10, -10); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| size = kPrimaryMinimumSize; |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| // Below minimum size, the stretch alignment means we'll compress. |
| size.Enlarge(-5, 0); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, AlignmentVertical) { |
| overflow_view_->SetOrientation(views::LayoutOrientation::kVertical); |
| |
| gfx::Size size = kPrimaryPreferredSize; |
| size.Enlarge(10, 0); |
| Resize(size); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(), kPrimaryPreferredSize), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kCenter); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(5, 0), kPrimaryPreferredSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kEnd); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(10, 0), kPrimaryPreferredSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| size = kPrimaryMinimumSize; |
| size.Enlarge(-10, 0); |
| Resize(size); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(0, 0), kPrimaryMinimumSize), primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kCenter); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(-5, 0), kPrimaryMinimumSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kEnd); |
| parent_view_->Layout(); |
| EXPECT_EQ(gfx::Rect(gfx::Point(-10, 0), kPrimaryMinimumSize), |
| primary_bounds()); |
| EXPECT_FALSE(indicator_visible()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, PrimaryOnlyRespectsFlexRule) { |
| primary_view_->SetProperty(views::kFlexBehaviorKey, |
| views::FlexSpecification(base::BindRepeating( |
| &OverflowViewTest::StepwiseFlexRule))); |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| |
| // Since default cross-axis alignment is stretch, the view should fill the |
| // space even if it's larger than the preferred size. |
| gfx::Size size = kPrimaryPreferredSize; |
| size.Enlarge(7, 7); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(kPrimaryPreferredSize), primary_bounds()); |
| |
| // At intermediate sizes, this flex rule steps down by multiples of 10, to the |
| // next multiple smaller than the available space. |
| size = kPrimaryPreferredSize; |
| size.Enlarge(-7, -7); |
| Resize(size); |
| gfx::Size expected = kPrimaryPreferredSize; |
| expected.Enlarge(-10, -10); |
| EXPECT_EQ(gfx::Rect(expected), primary_bounds()); |
| |
| // The height bottoms out against the minimum size first. |
| size = kPrimaryPreferredSize; |
| size.Enlarge(-13, -13); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(kPrimaryPreferredSize.width() - 20, |
| kPrimaryMinimumSize.height()), |
| primary_bounds()); |
| |
| size = kPrimaryMinimumSize; |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| |
| // Below minimum vertical size we won't compress the primary view since we're |
| // not stretching it. |
| size.Enlarge(0, -5); |
| Resize(size); |
| EXPECT_EQ(gfx::Rect(kPrimaryMinimumSize), primary_bounds()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, HorizontalOverflow) { |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| |
| // The primary view should start at the preferred size and scale down until it |
| // hits the minimum size. |
| gfx::Size size = kPrimaryPreferredSize; |
| size.Enlarge(10, 0); |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_FALSE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(kPrimaryPreferredSize), primary_bounds()); |
| |
| size = kPrimaryPreferredSize; |
| size.Enlarge(-10, 0); |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_FALSE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| |
| size = kPrimaryMinimumSize; |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_FALSE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| |
| // Below minimum size, the indicator will be displayed. |
| size.Enlarge(-5, 0); |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_TRUE(indicator_view_->GetVisible()); |
| const gfx::Rect expected_indicator{ |
| size.width() - kIndicatorPreferredSize.width(), 0, |
| kIndicatorPreferredSize.width(), size.height()}; |
| const gfx::Rect expected_primary( |
| gfx::Size(expected_indicator.x(), size.height())); |
| EXPECT_EQ(expected_indicator, indicator_bounds()); |
| EXPECT_EQ(expected_primary, primary_bounds()); |
| |
| // If there is only enough room to show the indicator, then the primary view |
| // loses visibility. |
| size = kIndicatorMinimumSize; |
| Resize(size); |
| EXPECT_FALSE(primary_view_->GetVisible()); |
| EXPECT_TRUE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(size), indicator_bounds()); |
| } |
| |
| TEST_F(OverflowViewLayoutTest, VerticalOverflow) { |
| overflow_view_->SetOrientation(views::LayoutOrientation::kVertical); |
| overflow_view_->SetCrossAxisAlignment(views::LayoutAlignment::kStart); |
| const views::FlexRule flex_rule = |
| base::BindRepeating(&OverflowViewLayoutTest::TransposingFlexRule); |
| primary_view_->SetProperty(views::kFlexBehaviorKey, |
| views::FlexSpecification(flex_rule)); |
| indicator_view_->SetProperty(views::kFlexBehaviorKey, |
| views::FlexSpecification(flex_rule)); |
| |
| const gfx::Size primary_preferred = Transpose(kPrimaryPreferredSize); |
| const gfx::Size primary_minimum = Transpose(kPrimaryMinimumSize); |
| const gfx::Size indicator_preferred = Transpose(kIndicatorPreferredSize); |
| const gfx::Size indicator_minimum = Transpose(kIndicatorMinimumSize); |
| |
| // The primary view should start at the preferred size and scale down until it |
| // hits the minimum size. |
| gfx::Size size = primary_preferred; |
| size.Enlarge(0, 10); |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_FALSE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(primary_preferred), primary_bounds()); |
| |
| size = primary_preferred; |
| size.Enlarge(0, -10); |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_FALSE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| |
| size = primary_minimum; |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_FALSE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(size), primary_bounds()); |
| |
| // Below minimum size, the indicator will be displayed. |
| size.Enlarge(0, -5); |
| Resize(size); |
| EXPECT_TRUE(primary_view_->GetVisible()); |
| EXPECT_TRUE(indicator_view_->GetVisible()); |
| const gfx::Rect expected_indicator{ |
| 0, size.height() - indicator_preferred.height(), size.width(), |
| indicator_preferred.height()}; |
| const gfx::Rect expected_primary( |
| gfx::Size(size.width(), expected_indicator.y())); |
| EXPECT_EQ(expected_indicator, indicator_bounds()); |
| EXPECT_EQ(expected_primary, primary_bounds()); |
| |
| size = indicator_minimum; |
| Resize(size); |
| EXPECT_FALSE(primary_view_->GetVisible()); |
| EXPECT_TRUE(indicator_view_->GetVisible()); |
| EXPECT_EQ(gfx::Rect(size), indicator_bounds()); |
| } |