[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / wrench_menu / wrench_menu_controller_unittest.mm
blob774b5597c7ca28cd4efcd36a9937a57572073685
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.
5 #include "base/command_line.h"
6 #include "base/mac/scoped_nsobject.h"
7 #include "base/strings/sys_string_conversions.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/app/chrome_command_ids.h"
10 #include "chrome/browser/sync/glue/device_info.h"
11 #include "chrome/browser/sync/profile_sync_service_factory.h"
12 #include "chrome/browser/sync/sessions/sessions_sync_manager.h"
13 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
14 #include "chrome/browser/ui/cocoa/run_loop_testing.h"
15 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
16 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
17 #import "chrome/browser/ui/cocoa/wrench_menu/wrench_menu_controller.h"
18 #include "chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h"
19 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
20 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "grit/generated_resources.h"
24 #include "grit/theme_resources.h"
25 #include "sync/api/fake_sync_change_processor.h"
26 #include "sync/api/sync_error_factory_mock.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/gtest_mac.h"
30 #include "testing/platform_test.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h"
34 namespace {
36 class MockWrenchMenuModel : public WrenchMenuModel {
37  public:
38   MockWrenchMenuModel() : WrenchMenuModel() {}
39   ~MockWrenchMenuModel() {
40     // This dirty, ugly hack gets around a bug in the test. In
41     // ~WrenchMenuModel(), there's a call to TabstripModel::RemoveObserver(this)
42     // which mysteriously leads to this crash: http://crbug.com/49206 .  It
43     // seems that the vector of observers is getting hosed somewhere between
44     // |-[ToolbarController dealloc]| and ~MockWrenchMenuModel(). This line
45     // short-circuits the parent destructor to avoid this crash.
46     tab_strip_model_ = NULL;
47   }
48   MOCK_METHOD2(ExecuteCommand, void(int command_id, int event_flags));
51 class DummyRouter : public browser_sync::LocalSessionEventRouter {
52  public:
53   virtual ~DummyRouter() {}
54   virtual void StartRoutingTo(
55       browser_sync::LocalSessionEventHandler* handler) OVERRIDE {}
56   virtual void Stop() OVERRIDE {}
59 class WrenchMenuControllerTest
60     : public CocoaProfileTest,
61       public browser_sync::SessionsSyncManager::SyncInternalApiDelegate {
62  public:
63   virtual void SetUp() OVERRIDE {
64     CocoaProfileTest::SetUp();
65     ASSERT_TRUE(browser());
67     controller_.reset([[WrenchMenuController alloc] initWithBrowser:browser()]);
68     fake_model_.reset(new MockWrenchMenuModel);
70     manager_.reset(new browser_sync::SessionsSyncManager(
71         profile(),
72         this,
73         scoped_ptr<browser_sync::LocalSessionEventRouter>(
74             new DummyRouter())));
75     manager_->MergeDataAndStartSyncing(
76         syncer::SESSIONS,
77         syncer::SyncDataList(),
78         scoped_ptr<syncer::SyncChangeProcessor>(
79             new syncer::FakeSyncChangeProcessor),
80         scoped_ptr<syncer::SyncErrorFactory>(
81             new syncer::SyncErrorFactoryMock));
82   }
84   virtual scoped_ptr<browser_sync::DeviceInfo> GetLocalDeviceInfo()
85       const OVERRIDE {
86     return scoped_ptr<browser_sync::DeviceInfo>(
87         new browser_sync::DeviceInfo(GetLocalSyncCacheGUID(),
88                        "Test Machine",
89                        "Chromium 10k",
90                        "Chrome 10k",
91                        sync_pb::SyncEnums_DeviceType_TYPE_LINUX));
92   }
94   virtual std::string GetLocalSyncCacheGUID() const OVERRIDE {
95     return "WrenchMenuControllerTest";
96   }
98   void RegisterRecentTabs(RecentTabsBuilderTestHelper* helper) {
99     helper->ExportToSessionsSyncManager(manager_.get());
100   }
102   browser_sync::OpenTabsUIDelegate* GetOpenTabsDelegate() {
103     return manager_.get();
104   }
106   virtual void TearDown() OVERRIDE {
107     fake_model_.reset();
108     controller_.reset();
109     manager_.reset();
110     CocoaProfileTest::TearDown();
111   }
113   WrenchMenuController* controller() {
114     return controller_.get();
115   }
117   base::scoped_nsobject<WrenchMenuController> controller_;
119   scoped_ptr<MockWrenchMenuModel> fake_model_;
121  private:
122   scoped_ptr<browser_sync::SessionsSyncManager> manager_;
125 TEST_F(WrenchMenuControllerTest, Initialized) {
126   EXPECT_TRUE([controller() menu]);
127   EXPECT_GE([[controller() menu] numberOfItems], 5);
130 TEST_F(WrenchMenuControllerTest, DispatchSimple) {
131   base::scoped_nsobject<NSButton> button([[NSButton alloc] init]);
132   [button setTag:IDC_ZOOM_PLUS];
134   // Set fake model to test dispatching.
135   EXPECT_CALL(*fake_model_, ExecuteCommand(IDC_ZOOM_PLUS, 0));
136   [controller() setModel:fake_model_.get()];
138   [controller() dispatchWrenchMenuCommand:button.get()];
139   chrome::testing::NSRunLoopRunAllPending();
142 TEST_F(WrenchMenuControllerTest, RecentTabsFavIcon) {
143   RecentTabsBuilderTestHelper recent_tabs_builder;
144   recent_tabs_builder.AddSession();
145   recent_tabs_builder.AddWindow(0);
146   recent_tabs_builder.AddTab(0, 0);
147   RegisterRecentTabs(&recent_tabs_builder);
149   RecentTabsSubMenuModel recent_tabs_sub_menu_model(
150       NULL, browser(), GetOpenTabsDelegate());
151   fake_model_->AddSubMenuWithStringId(
152       IDC_RECENT_TABS_MENU, IDS_RECENT_TABS_MENU,
153       &recent_tabs_sub_menu_model);
155   [controller() setModel:fake_model_.get()];
156   NSMenu* menu = [controller() menu];
157   [controller() updateRecentTabsSubmenu];
159   NSString* title = l10n_util::GetNSStringWithFixup(IDS_RECENT_TABS_MENU);
160   NSMenu* recent_tabs_menu = [[menu itemWithTitle:title] submenu];
161   EXPECT_TRUE(recent_tabs_menu);
162   EXPECT_EQ(6, [recent_tabs_menu numberOfItems]);
164   // Send a icon changed event and verify that the icon is updated.
165   gfx::Image icon(ResourceBundle::GetSharedInstance().GetNativeImageNamed(
166       IDR_BOOKMARKS_FAVICON));
167   recent_tabs_sub_menu_model.SetIcon(3, icon);
168   EXPECT_NSNE(icon.ToNSImage(), [[recent_tabs_menu itemAtIndex:3] image]);
169   recent_tabs_sub_menu_model.GetMenuModelDelegate()->OnIconChanged(3);
170   EXPECT_TRUE([[recent_tabs_menu itemAtIndex:3] image]);
171   EXPECT_NSEQ(icon.ToNSImage(), [[recent_tabs_menu itemAtIndex:3] image]);
173   controller_.reset();
174   fake_model_.reset();
177 TEST_F(WrenchMenuControllerTest, RecentTabsElideTitle) {
178   // Add 1 session with 1 window and 2 tabs.
179   RecentTabsBuilderTestHelper recent_tabs_builder;
180   recent_tabs_builder.AddSession();
181   recent_tabs_builder.AddWindow(0);
182   base::string16 tab1_short_title = base::ASCIIToUTF16("Short");
183   recent_tabs_builder.AddTabWithInfo(0, 0, base::Time::Now(), tab1_short_title);
184   base::string16 tab2_long_title = base::ASCIIToUTF16(
185       "Very very very very very very very very very very very very long");
186   recent_tabs_builder.AddTabWithInfo(0, 0,
187       base::Time::Now() - base::TimeDelta::FromMinutes(10), tab2_long_title);
188   RegisterRecentTabs(&recent_tabs_builder);
190   RecentTabsSubMenuModel recent_tabs_sub_menu_model(
191       NULL, browser(), GetOpenTabsDelegate());
192   fake_model_->AddSubMenuWithStringId(
193       IDC_RECENT_TABS_MENU, IDS_RECENT_TABS_MENU,
194       &recent_tabs_sub_menu_model);
196   [controller() setModel:fake_model_.get()];
197   NSMenu* menu = [controller() menu];
198   [controller() updateRecentTabsSubmenu];
200   NSString* title = l10n_util::GetNSStringWithFixup(IDS_RECENT_TABS_MENU);
201   NSMenu* recent_tabs_menu = [[menu itemWithTitle:title] submenu];
202   EXPECT_TRUE(recent_tabs_menu);
203   EXPECT_EQ(7, [recent_tabs_menu numberOfItems]);
205   // Index 0: restore tabs menu item.
206   NSString* restore_tab_label = l10n_util::FixUpWindowsStyleLabel(
207       recent_tabs_sub_menu_model.GetLabelAt(0));
208   EXPECT_NSEQ(restore_tab_label, [[recent_tabs_menu itemAtIndex:0] title]);
210   // Item 1: separator.
211   EXPECT_TRUE([[recent_tabs_menu itemAtIndex:1] isSeparatorItem]);
213   // Item 2: window title.
214   EXPECT_NSEQ(
215       base::SysUTF16ToNSString(recent_tabs_sub_menu_model.GetLabelAt(2)),
216       [[recent_tabs_menu itemAtIndex:2] title]);
218   // Item 3: short tab title.
219   EXPECT_NSEQ(base::SysUTF16ToNSString(tab1_short_title),
220               [[recent_tabs_menu itemAtIndex:3] title]);
222   // Item 4: long tab title.
223   NSString* tab2_actual_title = [[recent_tabs_menu itemAtIndex:4] title];
224   NSUInteger title_length = [tab2_actual_title length];
225   EXPECT_GT(tab2_long_title.size(), title_length);
226   NSString* actual_substring =
227       [tab2_actual_title substringToIndex:title_length - 1];
228   NSString* expected_substring = [base::SysUTF16ToNSString(tab2_long_title)
229       substringToIndex:title_length - 1];
230   EXPECT_NSEQ(expected_substring, actual_substring);
232   controller_.reset();
233   fake_model_.reset();
236 // Verify that |RecentTabsMenuModelDelegate| is deleted before the model
237 // it's observing.
238 TEST_F(WrenchMenuControllerTest, RecentTabDeleteOrder) {
239   [controller_ menuNeedsUpdate:[controller_ menu]];
240   // If the delete order is wrong then the test will crash on exit.
243 }  // namespace