1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/controls/button/radio_button.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/strings/utf_string_conversions.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/events/base_event_utils.h"
13 #include "ui/views/test/views_test_base.h"
14
15 namespace {
16 // Group ID of the test radio buttons.
17 constexpr int kGroup = 1;
18 } // namespace
19
20 namespace views {
21
22 class RadioButtonTest : public ViewsTestBase {
23 public:
24 RadioButtonTest() = default;
25
SetUp()26 void SetUp() override {
27 ViewsTestBase::SetUp();
28
29 // Create a Widget so the radio buttons can find their group siblings.
30 widget_ = std::make_unique<Widget>();
31 Widget::InitParams params =
32 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
33 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
34 widget_->Init(std::move(params));
35 widget_->Show();
36
37 button_container_ = widget_->SetContentsView(std::make_unique<View>());
38 }
39
TearDown()40 void TearDown() override {
41 button_container_ = nullptr;
42 widget_.reset();
43 ViewsTestBase::TearDown();
44 }
45
46 protected:
button_container()47 View& button_container() { return *button_container_; }
48
49 private:
50 View* button_container_ = nullptr;
51 std::unique_ptr<Widget> widget_;
52
53 DISALLOW_COPY_AND_ASSIGN(RadioButtonTest);
54 };
55
TEST_F(RadioButtonTest,Basics)56 TEST_F(RadioButtonTest, Basics) {
57 RadioButton* button1 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
58 button_container().AddChildView(button1);
59 RadioButton* button2 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
60 button_container().AddChildView(button2);
61
62 button1->SetChecked(true);
63 EXPECT_TRUE(button1->GetChecked());
64 EXPECT_FALSE(button2->GetChecked());
65
66 button2->SetChecked(true);
67 EXPECT_FALSE(button1->GetChecked());
68 EXPECT_TRUE(button2->GetChecked());
69 }
70
TEST_F(RadioButtonTest,Focus)71 TEST_F(RadioButtonTest, Focus) {
72 RadioButton* button1 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
73 button_container().AddChildView(button1);
74 RadioButton* button2 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
75 button_container().AddChildView(button2);
76
77 // Tabbing through only focuses the checked button.
78 button1->SetChecked(true);
79 auto* focus_manager = button_container().GetFocusManager();
80 ui::KeyEvent pressed_tab(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE);
81 focus_manager->OnKeyEvent(pressed_tab);
82 EXPECT_EQ(button1, focus_manager->GetFocusedView());
83 focus_manager->OnKeyEvent(pressed_tab);
84 EXPECT_EQ(button1, focus_manager->GetFocusedView());
85
86 // The checked button can be moved using arrow keys.
87 focus_manager->OnKeyEvent(
88 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE));
89 EXPECT_EQ(button2, focus_manager->GetFocusedView());
90 EXPECT_FALSE(button1->GetChecked());
91 EXPECT_TRUE(button2->GetChecked());
92
93 focus_manager->OnKeyEvent(
94 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE));
95 EXPECT_EQ(button1, focus_manager->GetFocusedView());
96 EXPECT_TRUE(button1->GetChecked());
97 EXPECT_FALSE(button2->GetChecked());
98 }
99
TEST_F(RadioButtonTest,FocusOnClick)100 TEST_F(RadioButtonTest, FocusOnClick) {
101 RadioButton* button1 = new RadioButton(base::string16(), kGroup);
102 button1->SetSize(gfx::Size(10, 10));
103 button_container().AddChildView(button1);
104 button1->SetChecked(true);
105 RadioButton* button2 = new RadioButton(base::string16(), kGroup);
106 button2->SetSize(gfx::Size(10, 10));
107 button_container().AddChildView(button2);
108
109 const gfx::Point point(1, 1);
110 const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, point, point,
111 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
112 ui::EF_LEFT_MOUSE_BUTTON);
113 button2->OnMousePressed(event);
114 button2->OnMouseReleased(event);
115
116 EXPECT_TRUE(button2->GetChecked());
117 auto* focus_manager = button_container().GetFocusManager();
118 // No focus on click.
119 EXPECT_EQ(nullptr, focus_manager->GetFocusedView());
120
121 ui::KeyEvent pressed_tab(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE);
122 focus_manager->OnKeyEvent(pressed_tab);
123 EXPECT_EQ(button2, focus_manager->GetFocusedView());
124
125 button1->OnMousePressed(event);
126 button1->OnMouseReleased(event);
127 // Button 1 gets focus on click because button 2 already had it.
128 EXPECT_TRUE(button1->GetChecked());
129 EXPECT_EQ(button1, focus_manager->GetFocusedView());
130 }
131
132 } // namespace views
133