1 // Copyright (c) 2012 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.
5 #include "ui/views/controls/slider.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/events/event.h"
16 #include "ui/events/gesture_event_details.h"
17 #include "ui/events/test/event_generator.h"
18 #include "ui/views/test/slider_test_api.h"
19 #include "ui/views/test/views_test_base.h"
20 #include "ui/views/view.h"
21 #include "ui/views/widget/widget.h"
22 #include "ui/views/widget/widget_delegate.h"
26 // A views::SliderListener that tracks simple event call history.
27 class TestSliderListener
: public views::SliderListener
{
30 ~TestSliderListener() override
;
32 int last_event_epoch() {
33 return last_event_epoch_
;
36 int last_drag_started_epoch() {
37 return last_drag_started_epoch_
;
40 int last_drag_ended_epoch() {
41 return last_drag_ended_epoch_
;
44 views::Slider
* last_drag_started_sender() {
45 return last_drag_started_sender_
;
48 views::Slider
* last_drag_ended_sender() {
49 return last_drag_ended_sender_
;
52 // Resets the state of this as if it were newly created.
53 virtual void ResetCallHistory();
55 // views::SliderListener:
56 void SliderValueChanged(views::Slider
* sender
,
59 views::SliderChangeReason reason
) override
;
60 void SliderDragStarted(views::Slider
* sender
) override
;
61 void SliderDragEnded(views::Slider
* sender
) override
;
64 // The epoch of the last event.
65 int last_event_epoch_
;
66 // The epoch of the last time SliderDragStarted was called.
67 int last_drag_started_epoch_
;
68 // The epoch of the last time SliderDragEnded was called.
69 int last_drag_ended_epoch_
;
70 // The sender from the last SliderDragStarted call.
71 views::Slider
* last_drag_started_sender_
;
72 // The sender from the last SliderDragEnded call.
73 views::Slider
* last_drag_ended_sender_
;
75 DISALLOW_COPY_AND_ASSIGN(TestSliderListener
);
78 TestSliderListener::TestSliderListener()
79 : last_event_epoch_(0),
80 last_drag_started_epoch_(-1),
81 last_drag_ended_epoch_(-1),
82 last_drag_started_sender_(NULL
),
83 last_drag_ended_sender_(NULL
) {
86 TestSliderListener::~TestSliderListener() {
87 last_drag_started_sender_
= NULL
;
88 last_drag_ended_sender_
= NULL
;
91 void TestSliderListener::ResetCallHistory() {
92 last_event_epoch_
= 0;
93 last_drag_started_epoch_
= -1;
94 last_drag_ended_epoch_
= -1;
95 last_drag_started_sender_
= NULL
;
96 last_drag_ended_sender_
= NULL
;
99 void TestSliderListener::SliderValueChanged(views::Slider
* sender
,
102 views::SliderChangeReason reason
) {
106 void TestSliderListener::SliderDragStarted(views::Slider
* sender
) {
107 last_drag_started_sender_
= sender
;
108 last_drag_started_epoch_
= ++last_event_epoch_
;
111 void TestSliderListener::SliderDragEnded(views::Slider
* sender
) {
112 last_drag_ended_sender_
= sender
;
113 last_drag_ended_epoch_
= ++last_event_epoch_
;
120 // Base test fixture for Slider tests.
121 class SliderTest
: public views::ViewsTestBase
{
123 explicit SliderTest(Slider::Orientation orientation
);
124 ~SliderTest() override
;
131 TestSliderListener
& slider_listener() {
132 return slider_listener_
;
143 virtual void ClickAt(int x
, int y
);
146 void SetUp() override
;
147 void TearDown() override
;
149 ui::test::EventGenerator
* event_generator() {
150 return event_generator_
.get();
154 // The Slider's orientation
155 Slider::Orientation orientation_
;
156 // The Slider to be tested.
158 // A simple SliderListener test double.
159 TestSliderListener slider_listener_
;
160 // Stores the default locale at test setup so it can be restored
161 // during test teardown.
162 std::string default_locale_
;
163 // The maximum x value within the bounds of the slider.
165 // The maximum y value within the bounds of the slider.
167 // The widget container for the slider being tested.
168 views::Widget
* widget_
;
169 // An event generator.
170 scoped_ptr
<ui::test::EventGenerator
> event_generator_
;
172 DISALLOW_COPY_AND_ASSIGN(SliderTest
);
175 SliderTest::SliderTest(Slider::Orientation orientation
)
176 : orientation_(orientation
),
183 SliderTest::~SliderTest() {
186 void SliderTest::SetUp() {
187 views::ViewsTestBase::SetUp();
189 slider_
= new Slider(NULL
, orientation_
);
190 View
* view
= slider_
;
191 gfx::Size size
= view
->GetPreferredSize();
193 max_x_
= size
.width() - 1;
194 max_y_
= size
.height() - 1;
195 default_locale_
= l10n_util::GetApplicationLocale("");
197 views::Widget::InitParams
init_params(CreateParams(
198 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
));
199 init_params
.bounds
= gfx::Rect(size
);
201 widget_
= new views::Widget();
202 widget_
->Init(init_params
);
203 widget_
->SetContentsView(slider_
);
206 event_generator_
.reset(new ui::test::EventGenerator(
207 GetContext(), widget_
->GetNativeWindow()));
210 void SliderTest::TearDown() {
211 if (widget_
&& !widget_
->IsClosed())
214 base::i18n::SetICUDefaultLocale(default_locale_
);
216 views::ViewsTestBase::TearDown();
219 void SliderTest::ClickAt(int x
, int y
) {
220 gfx::Point
point(x
, y
);
221 event_generator_
->MoveMouseTo(point
);
222 event_generator_
->ClickLeftButton();
225 // Test fixture for horizontally oriented slider tests.
226 class HorizontalSliderTest
: public SliderTest
{
228 HorizontalSliderTest();
229 ~HorizontalSliderTest() override
;
232 DISALLOW_COPY_AND_ASSIGN(HorizontalSliderTest
);
235 HorizontalSliderTest::HorizontalSliderTest()
236 : SliderTest(Slider::HORIZONTAL
) {
239 HorizontalSliderTest::~HorizontalSliderTest() {
242 // Test fixture for vertically oriented slider tests.
243 class VerticalSliderTest
: public SliderTest
{
245 VerticalSliderTest();
246 ~VerticalSliderTest() override
;
249 DISALLOW_COPY_AND_ASSIGN(VerticalSliderTest
);
252 VerticalSliderTest::VerticalSliderTest()
253 : SliderTest(Slider::VERTICAL
) {
256 VerticalSliderTest::~VerticalSliderTest() {
259 TEST_F(HorizontalSliderTest
, UpdateFromClickHorizontal
) {
261 EXPECT_EQ(0.0f
, slider()->value());
264 EXPECT_EQ(1.0f
, slider()->value());
267 TEST_F(VerticalSliderTest
, UpdateFromClickVertical
) {
269 EXPECT_EQ(1.0f
, slider()->value());
272 EXPECT_EQ(0.0f
, slider()->value());
275 TEST_F(HorizontalSliderTest
, UpdateFromClickRTLHorizontal
) {
276 base::i18n::SetICUDefaultLocale("he");
279 EXPECT_EQ(1.0f
, slider()->value());
282 EXPECT_EQ(0.0f
, slider()->value());
285 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
286 #if !defined(OS_MACOSX) || defined(USE_AURA)
288 // Test the slider location after a tap gesture.
289 TEST_F(HorizontalSliderTest
, SliderValueForTapGesture
) {
290 // Tap below the minimum.
291 slider()->SetValue(0.5);
292 event_generator()->GestureTapAt(gfx::Point(0, 0));
293 EXPECT_FLOAT_EQ(0, slider()->value());
295 // Tap above the maximum.
296 slider()->SetValue(0.5);
297 event_generator()->GestureTapAt(gfx::Point(max_x(), max_y()));
298 EXPECT_FLOAT_EQ(1, slider()->value());
300 // Tap somwhere in the middle.
301 slider()->SetValue(0.5);
302 event_generator()->GestureTapAt(gfx::Point(0.75 * max_x(), 0.75 * max_y()));
303 EXPECT_NEAR(0.75, slider()->value(), 0.03);
306 // Test the slider location after a scroll gesture.
307 TEST_F(HorizontalSliderTest
, SliderValueForScrollGesture
) {
308 // Scroll below the minimum.
309 slider()->SetValue(0.5);
310 event_generator()->GestureScrollSequence(
311 gfx::Point(0.5 * max_x(), 0.5 * max_y()),
313 base::TimeDelta::FromMilliseconds(10),
315 EXPECT_EQ(0, slider()->value());
317 // Scroll above the maximum.
318 slider()->SetValue(0.5);
319 event_generator()->GestureScrollSequence(
320 gfx::Point(0.5 * max_x(), 0.5 * max_y()),
321 gfx::Point(max_x(), max_y()),
322 base::TimeDelta::FromMilliseconds(10),
324 EXPECT_EQ(1, slider()->value());
326 // Scroll somewhere in the middle.
327 slider()->SetValue(0.25);
328 event_generator()->GestureScrollSequence(
329 gfx::Point(0.25 * max_x(), 0.25 * max_y()),
330 gfx::Point(0.75 * max_x(), 0.75 * max_y()),
331 base::TimeDelta::FromMilliseconds(10),
333 EXPECT_NEAR(0.75, slider()->value(), 0.03);
336 // Verifies the correct SliderListener events are raised for a tap gesture.
337 TEST_F(HorizontalSliderTest
, SliderListenerEventsForTapGesture
) {
338 test::SliderTestApi
slider_test_api(slider());
339 slider_test_api
.SetListener(&slider_listener());
341 event_generator()->GestureTapAt(gfx::Point(0, 0));
342 EXPECT_EQ(1, slider_listener().last_drag_started_epoch());
343 EXPECT_EQ(2, slider_listener().last_drag_ended_epoch());
344 EXPECT_EQ(slider(), slider_listener().last_drag_started_sender());
345 EXPECT_EQ(slider(), slider_listener().last_drag_ended_sender());
348 // Verifies the correct SliderListener events are raised for a scroll gesture.
349 TEST_F(HorizontalSliderTest
, SliderListenerEventsForScrollGesture
) {
350 test::SliderTestApi
slider_test_api(slider());
351 slider_test_api
.SetListener(&slider_listener());
353 event_generator()->GestureScrollSequence(
354 gfx::Point(0.25 * max_x(), 0.25 * max_y()),
355 gfx::Point(0.75 * max_x(), 0.75 * max_y()),
356 base::TimeDelta::FromMilliseconds(0),
359 EXPECT_EQ(1, slider_listener().last_drag_started_epoch());
360 EXPECT_GT(slider_listener().last_drag_ended_epoch(),
361 slider_listener().last_drag_started_epoch());
362 EXPECT_EQ(slider(), slider_listener().last_drag_started_sender());
363 EXPECT_EQ(slider(), slider_listener().last_drag_ended_sender());
366 // Verifies the correct SliderListener events are raised for a multi
367 // finger scroll gesture.
368 TEST_F(HorizontalSliderTest
, SliderListenerEventsForMultiFingerScrollGesture
) {
369 test::SliderTestApi
slider_test_api(slider());
370 slider_test_api
.SetListener(&slider_listener());
372 gfx::Point points
[] = {gfx::Point(0, 0.1 * max_y()),
373 gfx::Point(0, 0.2 * max_y())};
374 event_generator()->GestureMultiFingerScroll(2 /* count */, points
,
375 0 /* event_separation_time_ms */, 5 /* steps */,
376 2 /* move_x */, 0 /* move_y */);
378 EXPECT_EQ(1, slider_listener().last_drag_started_epoch());
379 EXPECT_GT(slider_listener().last_drag_ended_epoch(),
380 slider_listener().last_drag_started_epoch());
381 EXPECT_EQ(slider(), slider_listener().last_drag_started_sender());
382 EXPECT_EQ(slider(), slider_listener().last_drag_ended_sender());
385 #endif // !defined(OS_MACOSX) || defined(USE_AURA)