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_factory.h" 6 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" 7 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h" 8 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" 9 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h" 10 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h" 11 #include "chrome/test/base/testing_profile.h" 12 #include "components/bookmarks/browser/bookmark_model.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 34 class 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 47 TEST_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 profile:profile()]); 64 65 [target openBookmarkFolderFromButton:sender]; 66 EXPECT_OCMOCK_VERIFY(controller); 67 } 68 69 TEST_F(BookmarkFolderTargetTest, ReopenSameFolder) { 70 // Need a fake "button" which has a bookmark node. 71 id sender = [OCMockObject mockForClass:[BookmarkButton class]]; 72 [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode]; 73 74 // Fake controller 75 id controller = [OCMockObject mockForClass:[BookmarkBarFolderController 76 class]]; 77 // YES a current folder. Self-mock that as well, so "same" will be 78 // true. Note this creates a retain cycle in OCMockObject; we 79 // accomodate at the end of this function. 80 [[[controller stub] andReturn:controller] folderController]; 81 [[[controller stub] andReturn:sender] parentButton]; 82 83 // The folder is open, so a click should close just that folder (and 84 // any subfolders). 85 [[controller expect] closeBookmarkFolder:controller]; 86 87 base::scoped_nsobject<BookmarkFolderTarget> target( 88 [[BookmarkFolderTarget alloc] initWithController:controller 89 profile:profile()]); 90 91 [target openBookmarkFolderFromButton:sender]; 92 EXPECT_OCMOCK_VERIFY(controller); 93 94 // Our use of OCMockObject means an object can return itself. This 95 // creates a retain cycle, since OCMock retains all objects used in 96 // mock creation. Clear out the invocation handlers of all 97 // OCMockRecorders we used to break the cycles. 98 [controller clearRecordersAndExpectations]; 99 } 100 101 TEST_F(BookmarkFolderTargetTest, ReopenNotSame) { 102 // Need a fake "button" which has a bookmark node. 103 id sender = [OCMockObject mockForClass:[BookmarkButton class]]; 104 [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode]; 105 106 // Fake controller 107 id controller = [OCMockObject mockForClass:[BookmarkBarFolderController 108 class]]; 109 // YES a current folder but NOT same. 110 [[[controller stub] andReturn:controller] folderController]; 111 [[[controller stub] andReturn:nil] parentButton]; 112 113 // Insure the controller gets a chance to decide which folders to 114 // close and open. 115 [[controller expect] addNewFolderControllerWithParentButton:sender]; 116 117 base::scoped_nsobject<BookmarkFolderTarget> target( 118 [[BookmarkFolderTarget alloc] initWithController:controller 119 profile:profile()]); 120 121 [target openBookmarkFolderFromButton:sender]; 122 EXPECT_OCMOCK_VERIFY(controller); 123 124 // Break retain cycles. 125 [controller clearRecordersAndExpectations]; 126 } 127