Home | History | Annotate | Download | only in bookmarks
      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