Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / download / download_shelf_controller_unittest.mm
1 // Copyright 2013 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 #import <Cocoa/Cocoa.h>
6
7 #import "base/mac/scoped_block.h"
8 #import "base/mac/scoped_nsobject.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "chrome/browser/download/download_shelf.h"
11 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
12 #import "chrome/browser/ui/cocoa/download/download_item_controller.h"
13 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
14 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
15 #include "content/public/test/mock_download_item.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
18 #import "third_party/ocmock/OCMock/OCMock.h"
19 #import "third_party/ocmock/gtest_support.h"
20
21 using ::testing::Return;
22 using ::testing::AnyNumber;
23
24 // Wraps a content::MockDownloadItem so it can be retained by the mock
25 // DownloadItemController.
26 @interface WrappedMockDownloadItem : NSObject {
27  @private
28   scoped_ptr<content::MockDownloadItem> download_;
29 }
30 - (id)initWithMockDownload:(scoped_ptr<content::MockDownloadItem>)download;
31 - (content::DownloadItem*)download;
32 - (content::MockDownloadItem*)mockDownload;
33 @end
34
35 @implementation WrappedMockDownloadItem
36 - (id)initWithMockDownload:(scoped_ptr<content::MockDownloadItem>)download {
37   if ((self = [super init])) {
38     download_ = download.Pass();
39   }
40   return self;
41 }
42
43 - (content::DownloadItem*)download {
44   return download_.get();
45 }
46
47 - (content::MockDownloadItem*)mockDownload {
48   return download_.get();
49 }
50 @end
51
52 // Test method for accessing the wrapped MockDownloadItem.
53 @interface DownloadItemController (DownloadShelfControllerTest) {
54 }
55 - (WrappedMockDownloadItem*)wrappedMockDownload;
56 @end
57
58 @implementation DownloadItemController (DownloadShelfControllerTest)
59 - (WrappedMockDownloadItem*)wrappedMockDownload {
60   return nil;
61 }
62 @end
63
64 @interface DownloadShelfController (Testing)
65 - (void)animationDidEnd:(NSAnimation*)animation;
66 @end
67
68 // Subclass of the DownloadShelfController to override scheduleAutoClose and
69 // cancelAutoClose. During regular operation, a scheduled autoClose waits for 5
70 // seconds before closing the shelf (unless it is cancelled during this
71 // time). For testing purposes, we count the number of invocations of
72 // {schedule,cancel}AutoClose instead of actually scheduling and cancelling.
73 @interface CountingDownloadShelfController : DownloadShelfController {
74  @public
75   int scheduleAutoCloseCount_;
76   int cancelAutoCloseCount_;
77   base::mac::ScopedBlock<dispatch_block_t> closeAnimationHandler_;
78 }
79
80 // Handler will be called at the end of a close animation.
81 - (void)setCloseAnimationHandler:(dispatch_block_t)handler;
82 @end
83
84 @implementation CountingDownloadShelfController
85
86 -(void)scheduleAutoClose {
87   ++scheduleAutoCloseCount_;
88 }
89
90 -(void)cancelAutoClose {
91   ++cancelAutoCloseCount_;
92 }
93
94 - (void)setCloseAnimationHandler:(dispatch_block_t)handler {
95   closeAnimationHandler_.reset(handler);
96 }
97
98 - (void)animationDidEnd:(NSAnimation*)animation {
99   [super animationDidEnd:animation];
100   if (closeAnimationHandler_)
101     closeAnimationHandler_.get()();
102 }
103
104 @end
105
106 namespace {
107
108 class DownloadShelfControllerTest : public CocoaProfileTest {
109  public:
110   virtual void SetUp() override {
111     CocoaProfileTest::SetUp();
112     ASSERT_TRUE(browser());
113
114     resize_delegate_.reset([[ViewResizerPong alloc] init]);
115     shelf_.reset([[CountingDownloadShelfController alloc]
116                    initWithBrowser:browser()
117                     resizeDelegate:resize_delegate_.get()]);
118     EXPECT_TRUE([shelf_ view]);
119     [[test_window() contentView] addSubview:[shelf_ view]];
120   }
121
122   virtual void TearDown() override {
123     if (shelf_.get()) {
124       [shelf_ exiting];
125       shelf_.reset();
126     }
127     CocoaProfileTest::TearDown();
128   }
129
130  protected:
131   id CreateItemController();
132
133   base::scoped_nsobject<CountingDownloadShelfController> shelf_;
134   base::scoped_nsobject<ViewResizerPong> resize_delegate_;
135 };
136
137 id DownloadShelfControllerTest::CreateItemController() {
138   scoped_ptr<content::MockDownloadItem> download(
139       new ::testing::NiceMock<content::MockDownloadItem>);
140   ON_CALL(*download.get(), GetOpened())
141       .WillByDefault(Return(false));
142   ON_CALL(*download.get(), GetState())
143       .WillByDefault(Return(content::DownloadItem::IN_PROGRESS));
144
145   base::scoped_nsobject<WrappedMockDownloadItem> wrappedMockDownload(
146       [[WrappedMockDownloadItem alloc] initWithMockDownload:download.Pass()]);
147
148   id item_controller =
149       [OCMockObject mockForClass:[DownloadItemController class]];
150   base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSZeroRect]);
151   [[[item_controller stub] andCall:@selector(download)
152                           onObject:wrappedMockDownload.get()] download];
153   [[item_controller stub] updateVisibility:[OCMArg any]];
154   [[[item_controller stub]
155      andReturnValue:[NSValue valueWithSize:NSMakeSize(10,10)]] preferredSize];
156   [[[item_controller stub] andReturn:view.get()] view];
157   [[[item_controller stub]
158      andReturn:wrappedMockDownload.get()] wrappedMockDownload];
159   return [item_controller retain];
160 }
161
162 TEST_VIEW(DownloadShelfControllerTest, [shelf_ view]);
163
164 // Removing the last download from the shelf should cause it to close
165 // immediately.
166 TEST_F(DownloadShelfControllerTest, AddAndRemoveDownload) {
167   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
168   [shelf_ showDownloadShelf:YES
169                isUserAction:NO];
170   EXPECT_TRUE([shelf_ isVisible]);
171   EXPECT_TRUE([shelf_ bridge]->IsShowing());
172   [shelf_ add:item];
173   [shelf_ remove:item];
174   EXPECT_FALSE([shelf_ isVisible]);
175   EXPECT_FALSE([shelf_ bridge]->IsShowing());
176   // The shelf should be closed without scheduling an autoClose.
177   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
178 }
179
180 // Test that the shelf doesn't close automatically after a removal if there are
181 // active download items still on the shelf.
182 TEST_F(DownloadShelfControllerTest, AddAndRemoveWithActiveItem) {
183   base::scoped_nsobject<DownloadItemController> item1(CreateItemController());
184   base::scoped_nsobject<DownloadItemController> item2(CreateItemController());
185   [shelf_ showDownloadShelf:YES
186                isUserAction:NO];
187   EXPECT_TRUE([shelf_ isVisible]);
188   [shelf_ add:item1.get()];
189   [shelf_ add:item2.get()];
190   [shelf_ remove:item1.get()];
191   EXPECT_TRUE([shelf_ isVisible]);
192   [shelf_ remove:item2.get()];
193   EXPECT_FALSE([shelf_ isVisible]);
194   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
195 }
196
197 // DownloadShelf::Unhide() should cause the shelf to be displayed if there are
198 // active downloads on it.
199 TEST_F(DownloadShelfControllerTest, HideAndUnhide) {
200   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
201   [shelf_ showDownloadShelf:YES
202                isUserAction:NO];
203   EXPECT_TRUE([shelf_ isVisible]);
204   [shelf_ add:item.get()];
205   [shelf_ bridge]->Hide();
206   EXPECT_FALSE([shelf_ isVisible]);
207   [shelf_ bridge]->Unhide();
208   EXPECT_TRUE([shelf_ isVisible]);
209   [shelf_ remove:item.get()];
210   EXPECT_FALSE([shelf_ isVisible]);
211 }
212
213 // DownloadShelf::Unhide() shouldn't cause the shelf to be displayed if all
214 // active downloads are removed from the shelf while the shelf was hidden.
215 TEST_F(DownloadShelfControllerTest, HideAutocloseUnhide) {
216   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
217   [shelf_ showDownloadShelf:YES
218                isUserAction:NO];
219   EXPECT_TRUE([shelf_ isVisible]);
220   [shelf_ add:item.get()];
221   [shelf_ bridge]->Hide();
222   EXPECT_FALSE([shelf_ isVisible]);
223   [shelf_ remove:item.get()];
224   EXPECT_FALSE([shelf_ isVisible]);
225   [shelf_ bridge]->Unhide();
226   EXPECT_FALSE([shelf_ isVisible]);
227 }
228
229 // Test of autoclosing behavior after opening a download item. The mouse is on
230 // the download shelf at the time the autoclose is scheduled.
231 TEST_F(DownloadShelfControllerTest, AutoCloseAfterOpenWithMouseInShelf) {
232   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
233   [shelf_ showDownloadShelf:YES
234                isUserAction:NO];
235   EXPECT_TRUE([shelf_ isVisible]);
236   [shelf_ add:item.get()];
237   // Expect 2 cancelAutoClose calls: From the showDownloadShelf: call and the
238   // add: call.
239   EXPECT_EQ(2, shelf_.get()->cancelAutoCloseCount_);
240   shelf_.get()->cancelAutoCloseCount_ = 0;
241
242   // The mouse enters the shelf.
243   [shelf_ mouseEntered:nil];
244   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
245
246   // The download opens.
247   EXPECT_CALL(*[[item wrappedMockDownload] mockDownload], GetOpened())
248       .WillRepeatedly(Return(true));
249   [shelf_ downloadWasOpened:item.get()];
250
251   // The shelf should now be waiting for the mouse to exit.
252   EXPECT_TRUE([shelf_ isVisible]);
253   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
254   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
255
256   // The mouse exits the shelf. autoClose should be scheduled now.
257   [shelf_ mouseExited:nil];
258   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
259   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
260
261   // The mouse enters the shelf again. The autoClose should be cancelled.
262   [shelf_ mouseEntered:nil];
263   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
264   EXPECT_EQ(1, shelf_.get()->cancelAutoCloseCount_);
265 }
266
267 // Test of autoclosing behavior after opening a download item.
268 TEST_F(DownloadShelfControllerTest, AutoCloseAfterOpenWithMouseOffShelf) {
269   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
270   [shelf_ showDownloadShelf:YES
271                isUserAction:NO];
272   EXPECT_TRUE([shelf_ isVisible]);
273   [shelf_ add:item.get()];
274
275   // The download is opened.
276   EXPECT_CALL(*[[item wrappedMockDownload] mockDownload], GetOpened())
277       .WillRepeatedly(Return(true));
278   [shelf_ downloadWasOpened:item.get()];
279
280   // The shelf should be closed immediately since the mouse is not over the
281   // shelf.
282   EXPECT_FALSE([shelf_ isVisible]);
283 }
284
285 // Test that if the shelf is closed while an autoClose is pending, the pending
286 // autoClose is cancelled.
287 TEST_F(DownloadShelfControllerTest, CloseWithPendingAutoClose) {
288   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
289   [shelf_ showDownloadShelf:YES
290                isUserAction:NO];
291   EXPECT_TRUE([shelf_ isVisible]);
292   [shelf_ add:item.get()];
293   // Expect 2 cancelAutoClose calls: From the showDownloadShelf: call and the
294   // add: call.
295   EXPECT_EQ(2, shelf_.get()->cancelAutoCloseCount_);
296   shelf_.get()->cancelAutoCloseCount_ = 0;
297
298   // The mouse enters the shelf.
299   [shelf_ mouseEntered:nil];
300   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
301
302   // The download opens.
303   EXPECT_CALL(*[[item wrappedMockDownload] mockDownload], GetOpened())
304       .WillRepeatedly(Return(true));
305   [shelf_ downloadWasOpened:item.get()];
306
307   // The shelf should now be waiting for the mouse to exit. autoClose should not
308   // be scheduled yet.
309   EXPECT_TRUE([shelf_ isVisible]);
310   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
311   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
312
313   // The mouse exits the shelf. autoClose should be scheduled now.
314   [shelf_ mouseExited:nil];
315   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
316   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
317
318   // Remove the download item. This should cause the download shelf to be hidden
319   // immediately. The pending autoClose should be cancelled.
320   [shelf_ remove:item];
321   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
322   EXPECT_EQ(1, shelf_.get()->cancelAutoCloseCount_);
323   EXPECT_FALSE([shelf_ isVisible]);
324 }
325
326 // That that the shelf cancels a pending autoClose if a new download item is
327 // added to it.
328 TEST_F(DownloadShelfControllerTest, AddItemWithPendingAutoClose) {
329   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
330   [shelf_ showDownloadShelf:YES
331                isUserAction:NO];
332   EXPECT_TRUE([shelf_ isVisible]);
333   [shelf_ add:item.get()];
334   // Expect 2 cancelAutoClose calls: From the showDownloadShelf: call and the
335   // add: call.
336   EXPECT_EQ(2, shelf_.get()->cancelAutoCloseCount_);
337   shelf_.get()->cancelAutoCloseCount_ = 0;
338
339   // The mouse enters the shelf.
340   [shelf_ mouseEntered:nil];
341   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
342
343   // The download opens.
344   EXPECT_CALL(*[[item wrappedMockDownload] mockDownload], GetOpened())
345       .WillRepeatedly(Return(true));
346   [shelf_ downloadWasOpened:item.get()];
347
348   // The shelf should now be waiting for the mouse to exit. autoClose should not
349   // be scheduled yet.
350   EXPECT_TRUE([shelf_ isVisible]);
351   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
352   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
353
354   // The mouse exits the shelf. autoClose should be scheduled now.
355   [shelf_ mouseExited:nil];
356   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
357   EXPECT_EQ(0, shelf_.get()->cancelAutoCloseCount_);
358
359   // Add a new download item. The pending autoClose should be cancelled.
360   base::scoped_nsobject<DownloadItemController> item2(CreateItemController());
361   [shelf_ add:item.get()];
362   EXPECT_EQ(1, shelf_.get()->scheduleAutoCloseCount_);
363   EXPECT_EQ(1, shelf_.get()->cancelAutoCloseCount_);
364   EXPECT_TRUE([shelf_ isVisible]);
365 }
366
367 // Test that pending autoClose calls are cancelled when exiting.
368 TEST_F(DownloadShelfControllerTest, CancelAutoCloseOnExit) {
369   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
370   [shelf_ showDownloadShelf:YES
371                isUserAction:NO];
372   EXPECT_TRUE([shelf_ isVisible]);
373   [shelf_ add:item.get()];
374   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
375   EXPECT_EQ(2, shelf_.get()->cancelAutoCloseCount_);
376
377   [shelf_ exiting];
378   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
379   EXPECT_EQ(3, shelf_.get()->cancelAutoCloseCount_);
380   shelf_.reset();
381 }
382
383 // The view should not be hidden when the shelf is shown.
384 // The view should be hidden after the closing animation.
385 TEST_F(DownloadShelfControllerTest, ViewVisibility) {
386   [shelf_ showDownloadShelf:YES isUserAction:NO];
387   EXPECT_FALSE([[shelf_ view] isHidden]);
388
389   [shelf_ setCloseAnimationHandler:^{
390       base::MessageLoop::current()->QuitNow();
391   }];
392   [shelf_ showDownloadShelf:NO isUserAction:NO];
393   base::MessageLoop::current()->Run();
394   EXPECT_TRUE([[shelf_ view] isHidden]);
395
396   [shelf_ showDownloadShelf:YES isUserAction:NO];
397   EXPECT_FALSE([[shelf_ view] isHidden]);
398 }
399
400 }  // namespace