Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: chrome/browser/ui/cocoa/toolbar/reload_button_unittest.mm

Issue 7466016: Fix up reload button to not flicker, and simplify implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix up comments Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import <Cocoa/Cocoa.h> 5 #import <Cocoa/Cocoa.h>
6 6
7 #import "chrome/browser/ui/cocoa/toolbar/reload_button.h" 7 #import "chrome/browser/ui/cocoa/toolbar/reload_button.h"
8 8
9 #include "base/memory/scoped_nsobject.h" 9 #include "base/memory/scoped_nsobject.h"
10 #include "chrome/app/chrome_command_ids.h" 10 #include "chrome/app/chrome_command_ids.h"
11 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" 11 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
12 #import "chrome/browser/ui/cocoa/image_button_cell.h"
12 #import "chrome/browser/ui/cocoa/test_event_utils.h" 13 #import "chrome/browser/ui/cocoa/test_event_utils.h"
13 #import "testing/gtest_mac.h" 14 #import "testing/gtest_mac.h"
14 #include "testing/platform_test.h" 15 #include "testing/platform_test.h"
15 #import "third_party/ocmock/OCMock/OCMock.h" 16 #import "third_party/ocmock/OCMock/OCMock.h"
16 17
18 @interface ReloadButton (Testing)
19 + (void)setPendingReloadTimeout:(NSTimeInterval)seconds;
20 @end
21
17 @protocol TargetActionMock <NSObject> 22 @protocol TargetActionMock <NSObject>
18 - (void)anAction:(id)sender; 23 - (void)anAction:(id)sender;
19 @end 24 @end
20 25
21 namespace { 26 namespace {
22 27
23 class ReloadButtonTest : public CocoaTest { 28 class ReloadButtonTest : public CocoaTest {
24 public: 29 public:
25 ReloadButtonTest() { 30 ReloadButtonTest() {
26 NSRect frame = NSMakeRect(0, 0, 20, 20); 31 NSRect frame = NSMakeRect(0, 0, 20, 20);
27 scoped_nsobject<ReloadButton> button( 32 scoped_nsobject<ReloadButton> button(
28 [[ReloadButton alloc] initWithFrame:frame]); 33 [[ReloadButton alloc] initWithFrame:frame]);
29 button_ = button.get(); 34 button_ = button.get();
30 35
31 // Set things up so unit tests have a reliable baseline. 36 // Set things up so unit tests have a reliable baseline.
32 [button_ setTag:IDC_RELOAD]; 37 [button_ setTag:IDC_RELOAD];
33 [button_ awakeFromNib]; 38 [button_ awakeFromNib];
34 39
35 [[test_window() contentView] addSubview:button_]; 40 [[test_window() contentView] addSubview:button_];
36 } 41 }
37 42
43 bool IsMouseInside() {
44 return [[button_ cell] isMouseInside];
45 }
46
47 void MouseEnter() {
48 [[button_ cell] mouseEntered:nil];
49 }
50
51 void MouseExit() {
52 [[button_ cell] mouseExited:nil];
53 }
54
38 ReloadButton* button_; 55 ReloadButton* button_;
39 }; 56 };
40 57
41 TEST_VIEW(ReloadButtonTest, button_) 58 TEST_VIEW(ReloadButtonTest, button_)
42 59
43 // Test that mouse-tracking is setup and does the right thing. 60 // Test that mouse-tracking is setup and does the right thing.
44 TEST_F(ReloadButtonTest, IsMouseInside) { 61 TEST_F(ReloadButtonTest, IsMouseInside) {
45 EXPECT_TRUE([[button_ trackingAreas] containsObject:[button_ trackingArea]]); 62 EXPECT_FALSE(IsMouseInside());
46 63 MouseEnter();
47 EXPECT_FALSE([button_ isMouseInside]); 64 EXPECT_TRUE(IsMouseInside());
48 [button_ mouseEntered:nil]; 65 MouseExit();
49 EXPECT_TRUE([button_ isMouseInside]);
50 [button_ mouseExited:nil];
51 } 66 }
52 67
53 // Verify that multiple clicks do not result in multiple messages to 68 // Verify that multiple clicks do not result in multiple messages to
54 // the target. 69 // the target.
55 TEST_F(ReloadButtonTest, IgnoredMultiClick) { 70 TEST_F(ReloadButtonTest, IgnoredMultiClick) {
56 id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)]; 71 id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)];
57 [button_ setTarget:mock_target]; 72 [button_ setTarget:mock_target];
58 [button_ setAction:@selector(anAction:)]; 73 [button_ setAction:@selector(anAction:)];
59 74
60 // Expect the action once. 75 // Expect the action once.
(...skipping 24 matching lines...) Expand all
85 EXPECT_NSNE(reloadToolTip, stopToolTip); 100 EXPECT_NSNE(reloadToolTip, stopToolTip);
86 101
87 [button_ updateTag:IDC_RELOAD]; 102 [button_ updateTag:IDC_RELOAD];
88 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 103 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
89 EXPECT_NSEQ(reloadToolTip, [button_ toolTip]); 104 EXPECT_NSEQ(reloadToolTip, [button_ toolTip]);
90 } 105 }
91 106
92 // Test that when forcing the mode, it takes effect immediately, 107 // Test that when forcing the mode, it takes effect immediately,
93 // regardless of whether the mouse is hovering. 108 // regardless of whether the mouse is hovering.
94 TEST_F(ReloadButtonTest, SetIsLoadingForce) { 109 TEST_F(ReloadButtonTest, SetIsLoadingForce) {
95 EXPECT_FALSE([button_ isMouseInside]); 110 EXPECT_FALSE(IsMouseInside());
96 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 111 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
97 112
98 // Changes to stop immediately. 113 // Changes to stop immediately.
99 [button_ setIsLoading:YES force:YES]; 114 [button_ setIsLoading:YES force:YES];
100 EXPECT_EQ(IDC_STOP, [button_ tag]); 115 EXPECT_EQ(IDC_STOP, [button_ tag]);
101 116
102 // Changes to reload immediately. 117 // Changes to reload immediately.
103 [button_ setIsLoading:NO force:YES]; 118 [button_ setIsLoading:NO force:YES];
104 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 119 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
105 120
106 // Changes to stop immediately when the mouse is hovered, and 121 // Changes to stop immediately when the mouse is hovered, and
107 // doesn't change when the mouse exits. 122 // doesn't change when the mouse exits.
108 [button_ mouseEntered:nil]; 123 MouseEnter();
109 EXPECT_TRUE([button_ isMouseInside]); 124 EXPECT_TRUE(IsMouseInside());
110 [button_ setIsLoading:YES force:YES]; 125 [button_ setIsLoading:YES force:YES];
111 EXPECT_EQ(IDC_STOP, [button_ tag]); 126 EXPECT_EQ(IDC_STOP, [button_ tag]);
112 [button_ mouseExited:nil]; 127 MouseExit();
113 EXPECT_FALSE([button_ isMouseInside]); 128 EXPECT_FALSE(IsMouseInside());
114 EXPECT_EQ(IDC_STOP, [button_ tag]); 129 EXPECT_EQ(IDC_STOP, [button_ tag]);
115 130
116 // Changes to reload immediately when the mouse is hovered, and 131 // Changes to reload immediately when the mouse is hovered, and
117 // doesn't change when the mouse exits. 132 // doesn't change when the mouse exits.
118 [button_ mouseEntered:nil]; 133 MouseEnter();
119 EXPECT_TRUE([button_ isMouseInside]); 134 EXPECT_TRUE(IsMouseInside());
120 [button_ setIsLoading:NO force:YES]; 135 [button_ setIsLoading:NO force:YES];
121 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 136 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
122 [button_ mouseExited:nil]; 137 MouseExit();
123 EXPECT_FALSE([button_ isMouseInside]); 138 EXPECT_FALSE(IsMouseInside());
124 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 139 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
125 } 140 }
126 141
127 // Test that without force, stop mode is set immediately, but reload 142 // Test that without force, stop mode is set immediately, but reload
128 // is affected by the hover status. 143 // is affected by the hover status.
129 TEST_F(ReloadButtonTest, SetIsLoadingNoForceUnHover) { 144 TEST_F(ReloadButtonTest, SetIsLoadingNoForceUnHover) {
130 EXPECT_FALSE([button_ isMouseInside]); 145 EXPECT_FALSE(IsMouseInside());
131 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 146 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
132 147
133 // Changes to stop immediately when the mouse is not hovering. 148 // Changes to stop immediately when the mouse is not hovering.
134 [button_ setIsLoading:YES force:NO]; 149 [button_ setIsLoading:YES force:NO];
135 EXPECT_EQ(IDC_STOP, [button_ tag]); 150 EXPECT_EQ(IDC_STOP, [button_ tag]);
136 151
137 // Changes to reload immediately when the mouse is not hovering. 152 // Changes to reload immediately when the mouse is not hovering.
138 [button_ setIsLoading:NO force:NO]; 153 [button_ setIsLoading:NO force:NO];
139 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 154 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
140 155
141 // Changes to stop immediately when the mouse is hovered, and 156 // Changes to stop immediately when the mouse is hovered, and
142 // doesn't change when the mouse exits. 157 // doesn't change when the mouse exits.
143 [button_ mouseEntered:nil]; 158 MouseEnter();
144 EXPECT_TRUE([button_ isMouseInside]); 159 EXPECT_TRUE(IsMouseInside());
145 [button_ setIsLoading:YES force:NO]; 160 [button_ setIsLoading:YES force:NO];
146 EXPECT_EQ(IDC_STOP, [button_ tag]); 161 EXPECT_EQ(IDC_STOP, [button_ tag]);
147 [button_ mouseExited:nil]; 162 MouseExit();
148 EXPECT_FALSE([button_ isMouseInside]); 163 EXPECT_FALSE(IsMouseInside());
149 EXPECT_EQ(IDC_STOP, [button_ tag]); 164 EXPECT_EQ(IDC_STOP, [button_ tag]);
150 165
151 // Does not change to reload immediately when the mouse is hovered, 166 // Does not change to reload immediately when the mouse is hovered,
152 // changes when the mouse exits. 167 // changes when the mouse exits.
153 [button_ mouseEntered:nil]; 168 MouseEnter();
154 EXPECT_TRUE([button_ isMouseInside]); 169 EXPECT_TRUE(IsMouseInside());
155 [button_ setIsLoading:NO force:NO]; 170 [button_ setIsLoading:NO force:NO];
156 EXPECT_EQ(IDC_STOP, [button_ tag]); 171 EXPECT_EQ(IDC_STOP, [button_ tag]);
157 [button_ mouseExited:nil]; 172 MouseExit();
158 EXPECT_FALSE([button_ isMouseInside]); 173 EXPECT_FALSE(IsMouseInside());
159 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 174 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
160 } 175 }
161 176
162 // Test that without force, stop mode is set immediately, and reload 177 // Test that without force, stop mode is set immediately, and reload
163 // will be set after a timeout. 178 // will be set after a timeout.
164 // TODO(shess): Reenable, http://crbug.com/61485 179 // TODO(shess): Reenable, http://crbug.com/61485
165 TEST_F(ReloadButtonTest, DISABLED_SetIsLoadingNoForceTimeout) { 180 TEST_F(ReloadButtonTest, DISABLED_SetIsLoadingNoForceTimeout) {
166 // When the event loop first spins, some delayed tracking-area setup 181 // When the event loop first spins, some delayed tracking-area setup
167 // is done, which causes -mouseExited: to be called. Spin it at 182 // is done, which causes -mouseExited: to be called. Spin it at
168 // least once, and dequeue any pending events. 183 // least once, and dequeue any pending events.
169 // TODO(shess): It would be more reasonable to have an MockNSTimer 184 // TODO(shess): It would be more reasonable to have an MockNSTimer
170 // factory for the class to use, which this code could fire 185 // factory for the class to use, which this code could fire
171 // directly. 186 // directly.
172 while ([NSApp nextEventMatchingMask:NSAnyEventMask 187 while ([NSApp nextEventMatchingMask:NSAnyEventMask
173 untilDate:nil 188 untilDate:nil
174 inMode:NSDefaultRunLoopMode 189 inMode:NSDefaultRunLoopMode
175 dequeue:YES]) { 190 dequeue:YES]) {
176 } 191 }
177 192
178 const NSTimeInterval kShortTimeout = 0.1; 193 const NSTimeInterval kShortTimeout = 0.1;
179 [ReloadButton setPendingReloadTimeout:kShortTimeout]; 194 [ReloadButton setPendingReloadTimeout:kShortTimeout];
180 195
181 EXPECT_FALSE([button_ isMouseInside]); 196 EXPECT_FALSE(IsMouseInside());
182 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 197 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
183 198
184 // Move the mouse into the button and press it. 199 // Move the mouse into the button and press it.
185 [button_ mouseEntered:nil]; 200 MouseEnter();
186 EXPECT_TRUE([button_ isMouseInside]); 201 EXPECT_TRUE(IsMouseInside());
187 [button_ setIsLoading:YES force:NO]; 202 [button_ setIsLoading:YES force:NO];
188 EXPECT_EQ(IDC_STOP, [button_ tag]); 203 EXPECT_EQ(IDC_STOP, [button_ tag]);
189 204
190 // Does not change to reload immediately when the mouse is hovered. 205 // Does not change to reload immediately when the mouse is hovered.
191 EXPECT_TRUE([button_ isMouseInside]); 206 EXPECT_TRUE(IsMouseInside());
192 [button_ setIsLoading:NO force:NO]; 207 [button_ setIsLoading:NO force:NO];
193 EXPECT_TRUE([button_ isMouseInside]); 208 EXPECT_TRUE(IsMouseInside());
194 EXPECT_EQ(IDC_STOP, [button_ tag]); 209 EXPECT_EQ(IDC_STOP, [button_ tag]);
195 EXPECT_TRUE([button_ isMouseInside]); 210 EXPECT_TRUE(IsMouseInside());
196 211
197 // Spin event loop until the timeout passes. 212 // Spin event loop until the timeout passes.
198 NSDate* pastTimeout = [NSDate dateWithTimeIntervalSinceNow:2 * kShortTimeout]; 213 NSDate* pastTimeout = [NSDate dateWithTimeIntervalSinceNow:2 * kShortTimeout];
199 [NSApp nextEventMatchingMask:NSAnyEventMask 214 [NSApp nextEventMatchingMask:NSAnyEventMask
200 untilDate:pastTimeout 215 untilDate:pastTimeout
201 inMode:NSDefaultRunLoopMode 216 inMode:NSDefaultRunLoopMode
202 dequeue:NO]; 217 dequeue:NO];
203 218
204 // Mouse is still hovered, button is in reload mode. If the mouse 219 // Mouse is still hovered, button is in reload mode. If the mouse
205 // is no longer hovered, see comment at top of function. 220 // is no longer hovered, see comment at top of function.
206 EXPECT_TRUE([button_ isMouseInside]); 221 EXPECT_TRUE(IsMouseInside());
207 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 222 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
208 } 223 }
209 224
210 // Test that pressing stop after reload mode has been requested 225 // Test that pressing stop after reload mode has been requested
211 // doesn't forward the stop message. 226 // doesn't forward the stop message.
212 TEST_F(ReloadButtonTest, StopAfterReloadSet) { 227 TEST_F(ReloadButtonTest, StopAfterReloadSet) {
213 id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)]; 228 id mock_target = [OCMockObject mockForProtocol:@protocol(TargetActionMock)];
214 [button_ setTarget:mock_target]; 229 [button_ setTarget:mock_target];
215 [button_ setAction:@selector(anAction:)]; 230 [button_ setAction:@selector(anAction:)];
216 231
217 EXPECT_FALSE([button_ isMouseInside]); 232 EXPECT_FALSE(IsMouseInside());
218 233
219 // Get to stop mode. 234 // Get to stop mode.
220 [button_ setIsLoading:YES force:YES]; 235 [button_ setIsLoading:YES force:YES];
221 EXPECT_EQ(IDC_STOP, [button_ tag]); 236 EXPECT_EQ(IDC_STOP, [button_ tag]);
222 EXPECT_TRUE([button_ isEnabled]); 237 EXPECT_TRUE([button_ isEnabled]);
223 238
224 // Expect the action once. 239 // Expect the action once.
225 [[mock_target expect] anAction:button_]; 240 [[mock_target expect] anAction:button_];
226 241
227 // Clicking in stop mode should send the action and transition to 242 // Clicking in stop mode should send the action and transition to
228 // reload mode. 243 // reload mode.
229 const std::pair<NSEvent*,NSEvent*> click = 244 const std::pair<NSEvent*,NSEvent*> click =
230 test_event_utils::MouseClickInView(button_, 1); 245 test_event_utils::MouseClickInView(button_, 1);
231 [NSApp postEvent:click.second atStart:YES]; 246 [NSApp postEvent:click.second atStart:YES];
232 [button_ mouseDown:click.first]; 247 [button_ mouseDown:click.first];
233 EXPECT_EQ(IDC_RELOAD, [button_ tag]); 248 EXPECT_EQ(IDC_RELOAD, [button_ tag]);
234 EXPECT_TRUE([button_ isEnabled]); 249 EXPECT_TRUE([button_ isEnabled]);
235 250
236 // Get back to stop mode. 251 // Get back to stop mode.
237 [button_ setIsLoading:YES force:YES]; 252 [button_ setIsLoading:YES force:YES];
238 EXPECT_EQ(IDC_STOP, [button_ tag]); 253 EXPECT_EQ(IDC_STOP, [button_ tag]);
239 EXPECT_TRUE([button_ isEnabled]); 254 EXPECT_TRUE([button_ isEnabled]);
240 255
241 // If hover prevented reload mode immediately taking effect, clicks should do 256 // If hover prevented reload mode immediately taking effect, clicks should do
242 // nothing, because the button should be disabled. 257 // nothing, because the button should be disabled.
243 [button_ mouseEntered:nil]; 258 MouseEnter();
244 EXPECT_TRUE([button_ isMouseInside]); 259 EXPECT_TRUE(IsMouseInside());
245 [button_ setIsLoading:NO force:NO]; 260 [button_ setIsLoading:NO force:NO];
246 EXPECT_EQ(IDC_STOP, [button_ tag]); 261 EXPECT_EQ(IDC_STOP, [button_ tag]);
247 EXPECT_FALSE([button_ isEnabled]); 262 EXPECT_FALSE([button_ isEnabled]);
248 [NSApp postEvent:click.second atStart:YES]; 263 [NSApp postEvent:click.second atStart:YES];
249 [button_ mouseDown:click.first]; 264 [button_ mouseDown:click.first];
250 EXPECT_EQ(IDC_STOP, [button_ tag]); 265 EXPECT_EQ(IDC_STOP, [button_ tag]);
251 266
252 [button_ setTarget:nil]; 267 [button_ setTarget:nil];
253 } 268 }
254 269
255 } // namespace 270 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698