blob: 93c3431310ac1c418de6d53f29a96cf7c23e069a [file] [log] [blame]
// Copyright 2017 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/try_chrome_dialog_win/button_layout.h"
#include <algorithm>
#include <memory>
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/view.h"
class ButtonLayoutTest
: public ::testing::TestWithParam<::testing::tuple<int, int>> {
private:
enum {
// The width of an imaginary host view in the test.
kFixedHostWidth = 100,
};
public:
// Various button widths to be tested.
enum {
// Magic width meaning no button at all.
kNoButton = 0,
// Some small "narrow" button that fits within half of the test's host.
kNarrowButtonMin = 8,
// The largest "narrow" button that could fit within the test's host.
kNarrowButtonMax =
(kFixedHostWidth - ButtonLayout::kPaddingBetweenButtons) / 2,
// Some mid-sized "narrow" button that could fit within the test's host.
kNarrowButtonMid = (kNarrowButtonMin + kNarrowButtonMax) / 2,
// The least wide "wide" button that could fit within the test's host.
kWideButtonMin = kNarrowButtonMax + 1,
// The largest "wide" button that could fit within the test's host.
kWideButtonMax = kFixedHostWidth,
// Some mid-sized "wide" button that could fit within the test's host.
kWideButtonMid = (kWideButtonMin + kWideButtonMax) / 2,
// A button that is too big to fit within the host.
kSuperSizedButton = kWideButtonMax + 1,
};
protected:
ButtonLayoutTest()
: layout_(host_.SetLayoutManager(
std::make_unique<ButtonLayout>(kFixedHostWidth))),
button_1_width_(::testing::get<0>(GetParam())),
button_2_width_(::testing::get<1>(GetParam())) {}
void SetUp() override {
ASSERT_NE(0, button_1_width_) << "Button 1 must always be present.";
}
views::View* host() { return &host_; }
views::LayoutManager* layout() { return layout_; }
bool has_two_buttons() const { return button_2_width_; }
// Adds one or two child views of widths specified by the test parameters.
void AddChildViews() {
auto view = std::make_unique<views::View>();
view->SetPreferredSize({button_1_width_, kButtonHeight});
host()->AddChildView(view.release());
if (has_two_buttons()) {
view = std::make_unique<views::View>();
view->SetPreferredSize({button_2_width_, kButtonHeight});
host()->AddChildView(view.release());
}
}
// Returns the (fixed) width of the host.
int GetExpectedWidth() const { return kFixedHostWidth; }
// Returns the height of the host, which is dependent on the number and widths
// of the children.
int GetExpectedHeight() const {
if (!has_two_buttons())
return kButtonHeight;
if (button_1_width_ <= kNarrowButtonMax &&
button_2_width_ <= kNarrowButtonMax) {
return kButtonHeight;
}
return 2 * kButtonHeight + ButtonLayout::kPaddingBetweenButtons;
}
// Returns the expected bounding rectangle for |child_number|.
gfx::Rect GetExpectedButtonBounds(int child_number) const {
gfx::Rect bounds;
// Width is determined by the max of the two buttons being bigger than
// the max narrow button.
if (std::max(button_1_width_, button_2_width_) > kNarrowButtonMax)
bounds.set_width(kWideButtonMax);
else
bounds.set_width(kNarrowButtonMax);
// All buttons have the same height.
bounds.set_height(kButtonHeight);
// Position is based on which button we're talking about.
switch (child_number) {
case 1:
// Offset button 1 if there's only one button and it's narrow.
if (!has_two_buttons() && bounds.width() == kNarrowButtonMax)
bounds.set_x(kRightButtonXOffset);
break;
case 2:
// Offset button 2 horizontally if the buttons are narrow; vertically,
// otherwise.
if (bounds.width() == kNarrowButtonMax)
bounds.set_x(kRightButtonXOffset);
else
bounds.set_y(kBottomButtonYOffset);
break;
default:
ADD_FAILURE() << "child_number out of bounds";
return gfx::Rect();
}
return bounds;
}
// Expects that the bounds of |view| are equal to |bounds|.
void ExpectViewBoundsEquals(const views::View* view,
const gfx::Rect& bounds) {
const gfx::Rect& child_bounds = view->bounds();
EXPECT_EQ(child_bounds.x(), bounds.x());
EXPECT_EQ(child_bounds.y(), bounds.y());
EXPECT_EQ(child_bounds.width(), bounds.width());
EXPECT_EQ(child_bounds.height(), bounds.height());
}
private:
enum {
// The height of an imaginary button in the test.
kButtonHeight = 20,
// The horizontal offset of the right-hand button for narrow button layouts.
kRightButtonXOffset =
kNarrowButtonMax + ButtonLayout::kPaddingBetweenButtons,
// The vertical offset of the lower button for wide button layouts.
kBottomButtonYOffset = kButtonHeight + ButtonLayout::kPaddingBetweenButtons,
};
views::View host_;
ButtonLayout* const layout_; // Owned by |host_|.
const int button_1_width_;
const int button_2_width_;
DISALLOW_COPY_AND_ASSIGN(ButtonLayoutTest);
};
TEST_P(ButtonLayoutTest, GetPreferredSize) {
AddChildViews();
const gfx::Size preferred_size = layout()->GetPreferredSize(host());
EXPECT_EQ(preferred_size.width(), GetExpectedWidth());
EXPECT_EQ(preferred_size.height(), GetExpectedHeight());
}
TEST_P(ButtonLayoutTest, Layout) {
AddChildViews();
host()->SetBounds(0, 0, GetExpectedWidth(), GetExpectedHeight());
layout()->Layout(host());
ExpectViewBoundsEquals(host()->child_at(0), GetExpectedButtonBounds(1));
if (has_two_buttons())
ExpectViewBoundsEquals(host()->child_at(1), GetExpectedButtonBounds(2));
}
// Test all combinations of one or two buttons at many sizes.
INSTANTIATE_TEST_CASE_P(
,
ButtonLayoutTest,
::testing::Combine(::testing::Values(ButtonLayoutTest::kNarrowButtonMin,
ButtonLayoutTest::kNarrowButtonMid,
ButtonLayoutTest::kNarrowButtonMax,
ButtonLayoutTest::kWideButtonMin,
ButtonLayoutTest::kWideButtonMid,
ButtonLayoutTest::kWideButtonMax,
ButtonLayoutTest::kSuperSizedButton),
::testing::Values(ButtonLayoutTest::kNoButton,
ButtonLayoutTest::kNarrowButtonMin,
ButtonLayoutTest::kNarrowButtonMid,
ButtonLayoutTest::kNarrowButtonMax,
ButtonLayoutTest::kWideButtonMin,
ButtonLayoutTest::kWideButtonMid,
ButtonLayoutTest::kWideButtonMax,
ButtonLayoutTest::kSuperSizedButton)));