1// Copyright (c) 2011 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 "chrome/browser/ui/browser_window.h" 8#include "chrome/browser/ui/cocoa/browser_test_helper.h" 9#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" 10#import "chrome/browser/ui/cocoa/new_tab_button.h" 11#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" 12#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" 13#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 14#include "content/browser/site_instance.h" 15#include "content/browser/tab_contents/tab_contents.h" 16#include "testing/gtest/include/gtest/gtest.h" 17#include "testing/platform_test.h" 18 19@interface TestTabStripControllerDelegate : 20 NSObject<TabStripControllerDelegate> { 21} 22@end 23 24@implementation TestTabStripControllerDelegate 25- (void)onSelectTabWithContents:(TabContents*)contents { 26} 27- (void)onReplaceTabWithContents:(TabContents*)contents { 28} 29- (void)onSelectedTabChange:(TabStripModelObserver::TabChangeType)change { 30} 31- (void)onTabDetachedWithContents:(TabContents*)contents { 32} 33@end 34 35namespace { 36 37// Stub model delegate 38class TestTabStripDelegate : public TabStripModelDelegate { 39 public: 40 virtual TabContentsWrapper* AddBlankTab(bool foreground) { 41 return NULL; 42 } 43 virtual TabContentsWrapper* AddBlankTabAt(int index, bool foreground) { 44 return NULL; 45 } 46 virtual Browser* CreateNewStripWithContents(TabContentsWrapper* contents, 47 const gfx::Rect& window_bounds, 48 const DockInfo& dock_info, 49 bool maximize) { 50 return NULL; 51 } 52 virtual void ContinueDraggingDetachedTab(TabContentsWrapper* contents, 53 const gfx::Rect& window_bounds, 54 const gfx::Rect& tab_bounds) { 55 } 56 virtual int GetDragActions() const { 57 return 0; 58 } 59 virtual TabContentsWrapper* CreateTabContentsForURL( 60 const GURL& url, 61 const GURL& referrer, 62 Profile* profile, 63 PageTransition::Type transition, 64 bool defer_load, 65 SiteInstance* instance) const { 66 return NULL; 67 } 68 virtual bool CanDuplicateContentsAt(int index) { return true; } 69 virtual void DuplicateContentsAt(int index) { } 70 virtual void CloseFrameAfterDragSession() { } 71 virtual void CreateHistoricalTab(TabContentsWrapper* contents) { } 72 virtual bool RunUnloadListenerBeforeClosing(TabContentsWrapper* contents) { 73 return true; 74 } 75 virtual bool CanRestoreTab() { 76 return true; 77 } 78 virtual void RestoreTab() {} 79 80 virtual bool CanCloseContentsAt(int index) { return true; } 81 82 virtual bool CanBookmarkAllTabs() const { return false; } 83 84 virtual bool CanCloseTab() const { return true; } 85 86 virtual void BookmarkAllTabs() {} 87 88 virtual bool UseVerticalTabs() const { return false; } 89 90 virtual void ToggleUseVerticalTabs() {} 91 92 virtual bool LargeIconsPermitted() const { return true; } 93}; 94 95class TabStripControllerTest : public CocoaTest { 96 public: 97 TabStripControllerTest() { 98 Browser* browser = browser_helper_.browser(); 99 BrowserWindow* browser_window = browser_helper_.CreateBrowserWindow(); 100 NSWindow* window = browser_window->GetNativeHandle(); 101 NSView* parent = [window contentView]; 102 NSRect content_frame = [parent frame]; 103 104 // Create the "switch view" (view that gets changed out when a tab 105 // switches). 106 NSRect switch_frame = NSMakeRect(0, 0, content_frame.size.width, 500); 107 scoped_nsobject<NSView> switch_view( 108 [[NSView alloc] initWithFrame:switch_frame]); 109 [parent addSubview:switch_view.get()]; 110 111 // Create the tab strip view. It's expected to have a child button in it 112 // already as the "new tab" button so create that too. 113 NSRect strip_frame = NSMakeRect(0, NSMaxY(switch_frame), 114 content_frame.size.width, 30); 115 scoped_nsobject<TabStripView> tab_strip( 116 [[TabStripView alloc] initWithFrame:strip_frame]); 117 [parent addSubview:tab_strip.get()]; 118 NSRect button_frame = NSMakeRect(0, 0, 15, 15); 119 scoped_nsobject<NewTabButton> new_tab_button( 120 [[NewTabButton alloc] initWithFrame:button_frame]); 121 [tab_strip addSubview:new_tab_button.get()]; 122 [tab_strip setNewTabButton:new_tab_button.get()]; 123 124 delegate_.reset(new TestTabStripDelegate()); 125 model_ = browser->tabstrip_model(); 126 controller_delegate_.reset([TestTabStripControllerDelegate alloc]); 127 controller_.reset([[TabStripController alloc] 128 initWithView:static_cast<TabStripView*>(tab_strip.get()) 129 switchView:switch_view.get() 130 browser:browser 131 delegate:controller_delegate_.get()]); 132 } 133 134 virtual void TearDown() { 135 browser_helper_.CloseBrowserWindow(); 136 // The call to CocoaTest::TearDown() deletes the Browser and TabStripModel 137 // objects, so we first have to delete the controller, which refers to them. 138 controller_.reset(nil); 139 model_ = NULL; 140 CocoaTest::TearDown(); 141 } 142 143 BrowserTestHelper browser_helper_; 144 scoped_ptr<TestTabStripDelegate> delegate_; 145 TabStripModel* model_; 146 scoped_nsobject<TestTabStripControllerDelegate> controller_delegate_; 147 scoped_nsobject<TabStripController> controller_; 148}; 149 150// Test adding and removing tabs and making sure that views get added to 151// the tab strip. 152TEST_F(TabStripControllerTest, AddRemoveTabs) { 153 EXPECT_TRUE(model_->empty()); 154 SiteInstance* instance = 155 SiteInstance::CreateSiteInstance(browser_helper_.profile()); 156 TabContentsWrapper* tab_contents = 157 Browser::TabContentsFactory(browser_helper_.profile(), instance, 158 MSG_ROUTING_NONE, NULL, NULL); 159 model_->AppendTabContents(tab_contents, true); 160 EXPECT_EQ(model_->count(), 1); 161} 162 163TEST_F(TabStripControllerTest, SelectTab) { 164 // TODO(pinkerton): Implement http://crbug.com/10899 165} 166 167TEST_F(TabStripControllerTest, RearrangeTabs) { 168 // TODO(pinkerton): Implement http://crbug.com/10899 169} 170 171// Test that changing the number of tabs broadcasts a 172// kTabStripNumberOfTabsChanged notifiction. 173TEST_F(TabStripControllerTest, Notifications) { 174 // TODO(pinkerton): Implement http://crbug.com/10899 175} 176 177} // namespace 178