1 // Copyright 2014 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/menu_button.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "ui/aura/test/event_generator.h" 9 #include "ui/aura/window.h" 10 #include "ui/views/controls/button/menu_button_listener.h" 11 #include "ui/views/test/views_test_base.h" 12 13 using base::ASCIIToUTF16; 14 15 namespace views { 16 17 class MenuButtonTest : public ViewsTestBase { 18 public: 19 MenuButtonTest() : widget_(NULL), button_(NULL) {} 20 virtual ~MenuButtonTest() {} 21 22 virtual void TearDown() OVERRIDE { 23 if (widget_ && !widget_->IsClosed()) 24 widget_->Close(); 25 26 ViewsTestBase::TearDown(); 27 } 28 29 Widget* widget() { return widget_; } 30 MenuButton* button() { return button_; } 31 32 protected: 33 // Creates a MenuButton with a ButtonListener. In this case, the MenuButton 34 // acts like a regular button. 35 void CreateMenuButtonWithButtonListener(ButtonListener* button_listener) { 36 CreateWidget(); 37 38 const base::string16 label(ASCIIToUTF16("button")); 39 button_ = new MenuButton(button_listener, label, NULL, false); 40 button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20)); 41 widget_->SetContentsView(button_); 42 43 widget_->Show(); 44 } 45 46 // Creates a MenuButton with a MenuButtonListener. In this case, when the 47 // MenuButton is pushed, it notifies the MenuButtonListener to open a 48 // drop-down menu. 49 void CreateMenuButtonWithMenuButtonListener( 50 MenuButtonListener* menu_button_listener) { 51 CreateWidget(); 52 53 const base::string16 label(ASCIIToUTF16("button")); 54 button_ = new MenuButton(NULL, label, menu_button_listener, false); 55 button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20)); 56 widget_->SetContentsView(button_); 57 58 widget_->Show(); 59 } 60 61 private: 62 void CreateWidget() { 63 DCHECK(!widget_); 64 65 widget_ = new Widget; 66 Widget::InitParams params = 67 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); 68 params.bounds = gfx::Rect(0, 0, 200, 200); 69 widget_->Init(params); 70 } 71 72 Widget* widget_; 73 MenuButton* button_; 74 }; 75 76 class TestButtonListener : public ButtonListener { 77 public: 78 TestButtonListener() 79 : last_sender_(NULL), 80 last_sender_state_(Button::STATE_NORMAL), 81 last_event_type_(ui::ET_UNKNOWN) {} 82 virtual ~TestButtonListener() {} 83 84 virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE { 85 last_sender_ = sender; 86 CustomButton* custom_button = CustomButton::AsCustomButton(sender); 87 DCHECK(custom_button); 88 last_sender_state_ = custom_button->state(); 89 last_event_type_ = event.type(); 90 } 91 92 Button* last_sender() { return last_sender_; } 93 Button::ButtonState last_sender_state() { return last_sender_state_; } 94 ui::EventType last_event_type() { return last_event_type_; } 95 96 private: 97 Button* last_sender_; 98 Button::ButtonState last_sender_state_; 99 ui::EventType last_event_type_; 100 101 DISALLOW_COPY_AND_ASSIGN(TestButtonListener); 102 }; 103 104 class TestMenuButtonListener : public MenuButtonListener { 105 public: 106 TestMenuButtonListener() {} 107 virtual ~TestMenuButtonListener() {} 108 109 virtual void OnMenuButtonClicked(View* source, 110 const gfx::Point& /*point*/) OVERRIDE { 111 last_source_ = source; 112 CustomButton* custom_button = CustomButton::AsCustomButton(source); 113 DCHECK(custom_button); 114 last_source_state_ = custom_button->state(); 115 } 116 117 View* last_source() { return last_source_; } 118 Button::ButtonState last_source_state() { return last_source_state_; } 119 120 private: 121 View* last_source_; 122 Button::ButtonState last_source_state_; 123 }; 124 125 // Tests if the listener is notified correctly, when a mouse click happens on a 126 // MenuButton that has a regular ButtonListener. 127 TEST_F(MenuButtonTest, ActivateNonDropDownOnMouseClick) { 128 scoped_ptr<TestButtonListener> button_listener(new TestButtonListener); 129 CreateMenuButtonWithButtonListener(button_listener.get()); 130 131 aura::test::EventGenerator generator( 132 widget()->GetNativeView()->GetRootWindow()); 133 134 generator.set_current_location(gfx::Point(10, 10)); 135 generator.ClickLeftButton(); 136 137 // Check that MenuButton has notified the listener on mouse-released event, 138 // while it was in hovered state. 139 EXPECT_EQ(button(), button_listener->last_sender()); 140 EXPECT_EQ(ui::ET_MOUSE_RELEASED, button_listener->last_event_type()); 141 EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state()); 142 } 143 144 // Tests if the listener is notified correctly when a gesture tap happens on a 145 // MenuButton that has a regular ButtonListener. 146 TEST_F(MenuButtonTest, ActivateNonDropDownOnGestureTap) { 147 scoped_ptr<TestButtonListener> button_listener(new TestButtonListener); 148 CreateMenuButtonWithButtonListener(button_listener.get()); 149 150 aura::test::EventGenerator generator( 151 widget()->GetNativeView()->GetRootWindow()); 152 153 generator.GestureTapAt(gfx::Point(10, 10)); 154 155 // Check that MenuButton has notified the listener on gesture tap event, while 156 // it was in hovered state. 157 EXPECT_EQ(button(), button_listener->last_sender()); 158 EXPECT_EQ(ui::ET_GESTURE_TAP, button_listener->last_event_type()); 159 EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state()); 160 } 161 162 // Tests if the listener is notified correctly when a mouse click happens on a 163 // MenuButton that has a MenuButtonListener. 164 TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) { 165 scoped_ptr<TestMenuButtonListener> menu_button_listener( 166 new TestMenuButtonListener); 167 CreateMenuButtonWithMenuButtonListener(menu_button_listener.get()); 168 169 aura::test::EventGenerator generator( 170 widget()->GetNativeView()->GetRootWindow()); 171 172 generator.set_current_location(gfx::Point(10, 10)); 173 generator.ClickLeftButton(); 174 175 // Check that MenuButton has notified the listener, while it was in pressed 176 // state. 177 EXPECT_EQ(button(), menu_button_listener->last_source()); 178 EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state()); 179 } 180 181 // Tests if the listener is notified correctly when a gesture tap happens on a 182 // MenuButton that has a MenuButtonListener. 183 TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) { 184 scoped_ptr<TestMenuButtonListener> menu_button_listener( 185 new TestMenuButtonListener); 186 CreateMenuButtonWithMenuButtonListener(menu_button_listener.get()); 187 188 aura::test::EventGenerator generator( 189 widget()->GetNativeView()->GetRootWindow()); 190 191 generator.GestureTapAt(gfx::Point(10, 10)); 192 193 // Check that MenuButton has notified the listener, while it was in pressed 194 // state. 195 EXPECT_EQ(button(), menu_button_listener->last_source()); 196 EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state()); 197 } 198 199 } // namespace views 200