Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / toolbar / reload_button_unittest.mm
blob2661e4c6697d3797d192696f99695e17f39bd75e
1 // Copyright (c) 2011 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 #import <Cocoa/Cocoa.h>
7 #import "chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.h"
9 #include "base/mac/scoped_nsobject.h"
10 #include "chrome/app/chrome_command_ids.h"
11 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
12 #import "chrome/browser/ui/cocoa/image_button_cell.h"
13 #import "testing/gtest_mac.h"
14 #include "testing/platform_test.h"
15 #import "third_party/ocmock/OCMock/OCMock.h"
16 #import "ui/events/test/cocoa_test_event_utils.h"
18 @interface ReloadButton (Testing)
19 + (void)setPendingReloadTimeout:(NSTimeInterval)seconds;
20 @end
22 @interface ReloadButtonTarget : NSObject
23 - (void)anAction:(id)sender;
24 @end
26 @implementation ReloadButtonTarget
27 - (void)anAction:(id)sender {
29 @end
31 namespace {
33 class ReloadButtonTest : public CocoaTest {
34  public:
35   ReloadButtonTest() {
36     NSRect frame = NSMakeRect(0, 0, 20, 20);
37     base::scoped_nsobject<ReloadButton> button(
38         [[ReloadButton alloc] initWithFrame:frame]);
39     button_ = button.get();
41     // Set things up so unit tests have a reliable baseline.
42     [button_ setTag:IDC_RELOAD];
43     [button_ awakeFromNib];
45     [[test_window() contentView] addSubview:button_];
46   }
48   bool IsMouseInside() {
49     return [[button_ cell] isMouseInside];
50   }
52   void MouseEnter() {
53     [[button_ cell] mouseEntered:nil];
54   }
56   void MouseExit() {
57     [[button_ cell] mouseExited:nil];
58   }
60   ReloadButton* button_;
63 TEST_VIEW(ReloadButtonTest, button_)
65 // Test that mouse-tracking is setup and does the right thing.
66 TEST_F(ReloadButtonTest, IsMouseInside) {
67   EXPECT_FALSE(IsMouseInside());
68   MouseEnter();
69   EXPECT_TRUE(IsMouseInside());
70   MouseExit();
73 // Verify that multiple clicks do not result in multiple messages to
74 // the target.
75 TEST_F(ReloadButtonTest, IgnoredMultiClick) {
76   base::scoped_nsobject<ReloadButtonTarget> target(
77       [[ReloadButtonTarget alloc] init]);
78   id mock_target = [OCMockObject partialMockForObject:target];
79   [button_ setTarget:mock_target];
80   [button_ setAction:@selector(anAction:)];
82   // Expect the action once.
83   [[mock_target expect] anAction:button_];
85   const std::pair<NSEvent*,NSEvent*> click_one =
86       cocoa_test_event_utils::MouseClickInView(button_, 1);
87   const std::pair<NSEvent*,NSEvent*> click_two =
88       cocoa_test_event_utils::MouseClickInView(button_, 2);
89   [NSApp postEvent:click_one.second atStart:YES];
90   [button_ mouseDown:click_one.first];
91   [NSApp postEvent:click_two.second atStart:YES];
92   [button_ mouseDown:click_two.first];
94   [button_ setTarget:nil];
97 TEST_F(ReloadButtonTest, UpdateTag) {
98   [button_ setTag:IDC_STOP];
100   [button_ updateTag:IDC_RELOAD];
101   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
102   NSString* const reloadToolTip = [button_ toolTip];
104   [button_ updateTag:IDC_STOP];
105   EXPECT_EQ(IDC_STOP, [button_ tag]);
106   NSString* const stopToolTip = [button_ toolTip];
107   EXPECT_NSNE(reloadToolTip, stopToolTip);
109   [button_ updateTag:IDC_RELOAD];
110   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
111   EXPECT_NSEQ(reloadToolTip, [button_ toolTip]);
114 // Test that when forcing the mode, it takes effect immediately,
115 // regardless of whether the mouse is hovering.
116 TEST_F(ReloadButtonTest, SetIsLoadingForce) {
117   EXPECT_FALSE(IsMouseInside());
118   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
120   // Changes to stop immediately.
121   [button_ setIsLoading:YES force:YES];
122   EXPECT_EQ(IDC_STOP, [button_ tag]);
124   // Changes to reload immediately.
125   [button_ setIsLoading:NO force:YES];
126   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
128   // Changes to stop immediately when the mouse is hovered, and
129   // doesn't change when the mouse exits.
130   MouseEnter();
131   EXPECT_TRUE(IsMouseInside());
132   [button_ setIsLoading:YES force:YES];
133   EXPECT_EQ(IDC_STOP, [button_ tag]);
134   MouseExit();
135   EXPECT_FALSE(IsMouseInside());
136   EXPECT_EQ(IDC_STOP, [button_ tag]);
138   // Changes to reload immediately when the mouse is hovered, and
139   // doesn't change when the mouse exits.
140   MouseEnter();
141   EXPECT_TRUE(IsMouseInside());
142   [button_ setIsLoading:NO force:YES];
143   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
144   MouseExit();
145   EXPECT_FALSE(IsMouseInside());
146   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
149 // Test that without force, stop mode is set immediately, but reload
150 // is affected by the hover status.
151 TEST_F(ReloadButtonTest, SetIsLoadingNoForceUnHover) {
152   EXPECT_FALSE(IsMouseInside());
153   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
155   // Changes to stop immediately when the mouse is not hovering.
156   [button_ setIsLoading:YES force:NO];
157   EXPECT_EQ(IDC_STOP, [button_ tag]);
159   // Changes to reload immediately when the mouse is not hovering.
160   [button_ setIsLoading:NO force:NO];
161   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
163   // Changes to stop immediately when the mouse is hovered, and
164   // doesn't change when the mouse exits.
165   MouseEnter();
166   EXPECT_TRUE(IsMouseInside());
167   [button_ setIsLoading:YES force:NO];
168   EXPECT_EQ(IDC_STOP, [button_ tag]);
169   MouseExit();
170   EXPECT_FALSE(IsMouseInside());
171   EXPECT_EQ(IDC_STOP, [button_ tag]);
173   // Does not change to reload immediately when the mouse is hovered,
174   // changes when the mouse exits.
175   MouseEnter();
176   EXPECT_TRUE(IsMouseInside());
177   [button_ setIsLoading:NO force:NO];
178   EXPECT_EQ(IDC_STOP, [button_ tag]);
179   MouseExit();
180   EXPECT_FALSE(IsMouseInside());
181   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
184 // Test that without force, stop mode is set immediately, and reload
185 // will be set after a timeout.
186 // TODO(shess): Reenable, http://crbug.com/61485
187 TEST_F(ReloadButtonTest, DISABLED_SetIsLoadingNoForceTimeout) {
188   // When the event loop first spins, some delayed tracking-area setup
189   // is done, which causes -mouseExited: to be called.  Spin it at
190   // least once, and dequeue any pending events.
191   // TODO(shess): It would be more reasonable to have an MockNSTimer
192   // factory for the class to use, which this code could fire
193   // directly.
194   while ([NSApp nextEventMatchingMask:NSAnyEventMask
195                             untilDate:nil
196                                inMode:NSDefaultRunLoopMode
197                               dequeue:YES]) {
198   }
200   const NSTimeInterval kShortTimeout = 0.1;
201   [ReloadButton setPendingReloadTimeout:kShortTimeout];
203   EXPECT_FALSE(IsMouseInside());
204   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
206   // Move the mouse into the button and press it.
207   MouseEnter();
208   EXPECT_TRUE(IsMouseInside());
209   [button_ setIsLoading:YES force:NO];
210   EXPECT_EQ(IDC_STOP, [button_ tag]);
212   // Does not change to reload immediately when the mouse is hovered.
213   EXPECT_TRUE(IsMouseInside());
214   [button_ setIsLoading:NO force:NO];
215   EXPECT_TRUE(IsMouseInside());
216   EXPECT_EQ(IDC_STOP, [button_ tag]);
217   EXPECT_TRUE(IsMouseInside());
219   // Spin event loop until the timeout passes.
220   NSDate* pastTimeout = [NSDate dateWithTimeIntervalSinceNow:2 * kShortTimeout];
221   [NSApp nextEventMatchingMask:NSAnyEventMask
222                      untilDate:pastTimeout
223                         inMode:NSDefaultRunLoopMode
224                        dequeue:NO];
226   // Mouse is still hovered, button is in reload mode.  If the mouse
227   // is no longer hovered, see comment at top of function.
228   EXPECT_TRUE(IsMouseInside());
229   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
232 // Test that pressing stop after reload mode has been requested
233 // doesn't forward the stop message.
234 TEST_F(ReloadButtonTest, StopAfterReloadSet) {
235   base::scoped_nsobject<ReloadButtonTarget> target(
236       [[ReloadButtonTarget alloc] init]);
237   id mock_target = [OCMockObject partialMockForObject:target];
238   [button_ setTarget:mock_target];
239   [button_ setAction:@selector(anAction:)];
241   EXPECT_FALSE(IsMouseInside());
243   // Get to stop mode.
244   [button_ setIsLoading:YES force:YES];
245   EXPECT_EQ(IDC_STOP, [button_ tag]);
246   EXPECT_TRUE([button_ isEnabled]);
248   // Expect the action once.
249   [[mock_target expect] anAction:button_];
251   // Clicking in stop mode should send the action and transition to
252   // reload mode.
253   const std::pair<NSEvent*,NSEvent*> click =
254       cocoa_test_event_utils::MouseClickInView(button_, 1);
255   [NSApp postEvent:click.second atStart:YES];
256   [button_ mouseDown:click.first];
257   EXPECT_EQ(IDC_RELOAD, [button_ tag]);
258   EXPECT_TRUE([button_ isEnabled]);
260   // Get back to stop mode.
261   [button_ setIsLoading:YES force:YES];
262   EXPECT_EQ(IDC_STOP, [button_ tag]);
263   EXPECT_TRUE([button_ isEnabled]);
265   // If hover prevented reload mode immediately taking effect, clicks should do
266   // nothing, because the button should be disabled.
267   MouseEnter();
268   EXPECT_TRUE(IsMouseInside());
269   [button_ setIsLoading:NO force:NO];
270   EXPECT_EQ(IDC_STOP, [button_ tag]);
271   EXPECT_FALSE([button_ isEnabled]);
272   [NSApp postEvent:click.second atStart:YES];
273   [button_ mouseDown:click.first];
274   EXPECT_EQ(IDC_STOP, [button_ tag]);
276   [button_ setTarget:nil];
279 }  // namespace