1 // Copyright (c) 2010 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 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" 7 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h" 8 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h" 9 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" 10 #include "chrome/browser/ui/cocoa/browser_test_helper.h" 11 #include "chrome/browser/ui/cocoa/cocoa_test_helper.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/platform_test.h" 14 #import "third_party/ocmock/OCMock/OCMock.h" 15 16 @interface OCMockObject(PreventRetainCycle) 17 - (void)clearRecordersAndExpectations; 18 @end 19 20 @implementation OCMockObject(PreventRetainCycle) 21 22 // We need a mechanism to clear the invocation handlers to break a 23 // retain cycle (see below; search for "retain cycle"). 24 - (void)clearRecordersAndExpectations { 25 [recorders removeAllObjects]; 26 [expectations removeAllObjects]; 27 } 28 29 @end 30 31 32 class BookmarkFolderTargetTest : public CocoaTest { 33 public: 34 virtual void SetUp() { 35 CocoaTest::SetUp(); 36 BookmarkModel* model = helper_.profile()->GetBookmarkModel(); 37 bmbNode_ = model->GetBookmarkBarNode(); 38 } 39 virtual void TearDown() { 40 pool_.Recycle(); 41 CocoaTest::TearDown(); 42 } 43 44 BrowserTestHelper helper_; 45 const BookmarkNode* bmbNode_; 46 base::mac::ScopedNSAutoreleasePool pool_; 47 }; 48 49 TEST_F(BookmarkFolderTargetTest, StartWithNothing) { 50 // Need a fake "button" which has a bookmark node. 51 id sender = [OCMockObject mockForClass:[BookmarkButton class]]; 52 [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode]; 53 54 // Fake controller 55 id controller = [OCMockObject mockForClass:[BookmarkBarFolderController 56 class]]; 57 // No current folder 58 [[[controller stub] andReturn:nil] folderController]; 59 60 // Make sure we get an addNew 61 [[controller expect] addNewFolderControllerWithParentButton:sender]; 62 63 scoped_nsobject<BookmarkFolderTarget> target( 64 [[BookmarkFolderTarget alloc] initWithController:controller]); 65 66 [target openBookmarkFolderFromButton:sender]; 67 [controller verify]; 68 } 69 70 TEST_F(BookmarkFolderTargetTest, ReopenSameFolder) { 71 // Need a fake "button" which has a bookmark node. 72 id sender = [OCMockObject mockForClass:[BookmarkButton class]]; 73 [[[sender stub] andReturnValue:OCMOCK_VALUE(bmbNode_)] bookmarkNode]; 74 75 // Fake controller 76 id controller = [OCMockObject mockForClass:[BookmarkBarFolderController 77 class]]; 78 // YES a current folder. Self-mock that as well, so "same" will be 79 // true. Note this creates a retain cycle in OCMockObject; we 80 // accomodate at the end of this function. 81 [[[controller stub] andReturn:controller] folderController]; 82 [[[controller stub] andReturn:sender] parentButton]; 83 84 // The folder is open, so a click should close just that folder (and 85 // any subfolders). 86 [[controller expect] closeBookmarkFolder:controller]; 87 88 scoped_nsobject<BookmarkFolderTarget> target( 89 [[BookmarkFolderTarget alloc] initWithController:controller]); 90 91 [target openBookmarkFolderFromButton:sender]; 92 [controller verify]; 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 scoped_nsobject<BookmarkFolderTarget> target( 118 [[BookmarkFolderTarget alloc] initWithController:controller]); 119 120 [target openBookmarkFolderFromButton:sender]; 121 [controller verify]; 122 123 // Break retain cycles. 124 [controller clearRecordersAndExpectations]; 125 } 126