bookmark_folder_target_unittest.mm revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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.
4
5#include "chrome/browser/bookmarks/bookmark_model.h"
6#include "chrome/browser/bookmarks/bookmark_model_factory.h"
7#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
8#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h"
9#include "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
10#import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h"
11#include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
12#include "chrome/test/base/testing_profile.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "testing/platform_test.h"
15#import "third_party/ocmock/OCMock/OCMock.h"
16#include "third_party/ocmock/gtest_support.h"
17
18@interface OCMockObject(PreventRetainCycle)
19- (void)clearRecordersAndExpectations;
20@end
21
22@implementation OCMockObject(PreventRetainCycle)
23
24// We need a mechanism to clear the invocation handlers to break a
25// retain cycle (see below; search for "retain cycle").
26- (void)clearRecordersAndExpectations {
27  [recorders removeAllObjects];
28  [expectations removeAllObjects];
29}
30
31@end
32
33
34class BookmarkFolderTargetTest : public CocoaProfileTest {
35 public:
36  virtual void SetUp() {
37    CocoaProfileTest::SetUp();
38    ASSERT_TRUE(profile());
39
40    BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile());
41    bmbNode_ = model->bookmark_bar_node();
42  }
43
44  const BookmarkNode* bmbNode_;
45};
46
47TEST_F(BookmarkFolderTargetTest, StartWithNothing) {
48  // Need a fake "button" which has a bookmark node.
49  id sender = [OCMockObject mockForClass:[BookmarkButton class]];
50  [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode];
51
52  // Fake controller
53  id controller = [OCMockObject mockForClass:[BookmarkBarFolderController
54                                               class]];
55  // No current folder
56  [[[controller stub] andReturn:nil] folderController];
57
58  // Make sure we get an addNew
59  [[controller expect] addNewFolderControllerWithParentButton:sender];
60
61  base::scoped_nsobject<BookmarkFolderTarget> target(
62      [[BookmarkFolderTarget alloc] initWithController:controller]);
63
64  [target openBookmarkFolderFromButton:sender];
65  EXPECT_OCMOCK_VERIFY(controller);
66}
67
68TEST_F(BookmarkFolderTargetTest, ReopenSameFolder) {
69  // Need a fake "button" which has a bookmark node.
70  id sender = [OCMockObject mockForClass:[BookmarkButton class]];
71  [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode];
72
73  // Fake controller
74  id controller = [OCMockObject mockForClass:[BookmarkBarFolderController
75                                               class]];
76  // YES a current folder.  Self-mock that as well, so "same" will be
77  // true.  Note this creates a retain cycle in OCMockObject; we
78  // accomodate at the end of this function.
79  [[[controller stub] andReturn:controller] folderController];
80  [[[controller stub] andReturn:sender] parentButton];
81
82  // The folder is open, so a click should close just that folder (and
83  // any subfolders).
84  [[controller expect] closeBookmarkFolder:controller];
85
86  base::scoped_nsobject<BookmarkFolderTarget> target(
87      [[BookmarkFolderTarget alloc] initWithController:controller]);
88
89  [target openBookmarkFolderFromButton:sender];
90  EXPECT_OCMOCK_VERIFY(controller);
91
92  // Our use of OCMockObject means an object can return itself.  This
93  // creates a retain cycle, since OCMock retains all objects used in
94  // mock creation.  Clear out the invocation handlers of all
95  // OCMockRecorders we used to break the cycles.
96  [controller clearRecordersAndExpectations];
97}
98
99TEST_F(BookmarkFolderTargetTest, ReopenNotSame) {
100  // Need a fake "button" which has a bookmark node.
101  id sender = [OCMockObject mockForClass:[BookmarkButton class]];
102  [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode];
103
104  // Fake controller
105  id controller = [OCMockObject mockForClass:[BookmarkBarFolderController
106                                               class]];
107  // YES a current folder but NOT same.
108  [[[controller stub] andReturn:controller] folderController];
109  [[[controller stub] andReturn:nil] parentButton];
110
111  // Insure the controller gets a chance to decide which folders to
112  // close and open.
113  [[controller expect] addNewFolderControllerWithParentButton:sender];
114
115  base::scoped_nsobject<BookmarkFolderTarget> target(
116      [[BookmarkFolderTarget alloc] initWithController:controller]);
117
118  [target openBookmarkFolderFromButton:sender];
119  EXPECT_OCMOCK_VERIFY(controller);
120
121  // Break retain cycles.
122  [controller clearRecordersAndExpectations];
123}
124