apps_search_box_controller_unittest.mm revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright 2013 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 "ui/app_list/cocoa/apps_search_box_controller.h" 6 7#include "base/mac/scoped_nsobject.h" 8#include "base/strings/sys_string_conversions.h" 9#include "base/strings/utf_string_conversions.h" 10#import "testing/gtest_mac.h" 11#include "ui/app_list/app_list_menu.h" 12#include "ui/app_list/app_list_model_observer.h" 13#include "ui/app_list/search_box_model.h" 14#include "ui/app_list/test/app_list_test_model.h" 15#include "ui/app_list/test/app_list_test_view_delegate.h" 16#import "ui/base/cocoa/menu_controller.h" 17#import "ui/base/test/ui_cocoa_test_helper.h" 18 19@interface TestAppsSearchBoxDelegate : NSObject<AppsSearchBoxDelegate> { 20 @private 21 app_list::SearchBoxModel searchBoxModel_; 22 app_list::test::AppListTestViewDelegate appListDelegate_; 23 app_list::test::AppListTestModel appListModel_; 24 int textChangeCount_; 25} 26 27@property(assign, nonatomic) int textChangeCount; 28 29@end 30 31@implementation TestAppsSearchBoxDelegate 32 33@synthesize textChangeCount = textChangeCount_; 34 35- (id)init { 36 if ((self = [super init])) { 37 app_list::AppListModel::Users users(2); 38 users[0].name = ASCIIToUTF16("user1"); 39 users[1].name = ASCIIToUTF16("user2"); 40 users[1].email = ASCIIToUTF16("user2@chromium.org"); 41 users[1].active = true; 42 appListModel_.SetUsers(users); 43 } 44 return self; 45} 46 47- (app_list::SearchBoxModel*)searchBoxModel { 48 return &searchBoxModel_; 49} 50 51- (app_list::AppListViewDelegate*)appListDelegate { 52 return &appListDelegate_; 53} 54 55- (BOOL)control:(NSControl*)control 56 textView:(NSTextView*)textView 57 doCommandBySelector:(SEL)command { 58 return NO; 59} 60 61- (void)modelTextDidChange { 62 ++textChangeCount_; 63} 64 65- (CGFloat)bubbleCornerRadius { 66 return 3; 67} 68 69- (app_list::AppListModel*)appListModel { 70 return &appListModel_; 71} 72 73@end 74 75namespace app_list { 76namespace test { 77 78class AppsSearchBoxControllerTest : public ui::CocoaTest, 79 public AppListModelObserver { 80 public: 81 AppsSearchBoxControllerTest() { 82 Init(); 83 } 84 85 virtual void SetUp() OVERRIDE { 86 apps_search_box_controller_.reset( 87 [[AppsSearchBoxController alloc] initWithFrame: 88 NSMakeRect(0, 0, 400, 100)]); 89 delegate_.reset([[TestAppsSearchBoxDelegate alloc] init]); 90 [apps_search_box_controller_ setDelegate:delegate_]; 91 [delegate_ appListModel]->AddObserver(this); 92 93 ui::CocoaTest::SetUp(); 94 [[test_window() contentView] addSubview:[apps_search_box_controller_ view]]; 95 } 96 97 virtual void TearDown() OVERRIDE { 98 [delegate_ appListModel]->RemoveObserver(this); 99 [apps_search_box_controller_ setDelegate:nil]; 100 ui::CocoaTest::TearDown(); 101 } 102 103 void SimulateKeyAction(SEL c) { 104 NSControl* control = [apps_search_box_controller_ searchTextField]; 105 [apps_search_box_controller_ control:control 106 textView:nil 107 doCommandBySelector:c]; 108 } 109 110 protected: 111 // Overridden from app_list::AppListModelObserver: 112 virtual void OnAppListModelUsersChanged() OVERRIDE { 113 [apps_search_box_controller_ rebuildMenu]; 114 } 115 116 virtual void OnAppListModelSigninStatusChanged() OVERRIDE {} 117 118 base::scoped_nsobject<TestAppsSearchBoxDelegate> delegate_; 119 base::scoped_nsobject<AppsSearchBoxController> apps_search_box_controller_; 120 121 private: 122 DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxControllerTest); 123}; 124 125TEST_VIEW(AppsSearchBoxControllerTest, [apps_search_box_controller_ view]); 126 127// Test the search box initialization, and search input and clearing. 128TEST_F(AppsSearchBoxControllerTest, SearchBoxModel) { 129 app_list::SearchBoxModel* model = [delegate_ searchBoxModel]; 130 // Usually localized "Search". 131 const base::string16 hit_text(ASCIIToUTF16("hint")); 132 model->SetHintText(hit_text); 133 EXPECT_NSEQ(base::SysUTF16ToNSString(hit_text), 134 [[[apps_search_box_controller_ searchTextField] cell] placeholderString]); 135 136 const base::string16 search_text(ASCIIToUTF16("test")); 137 model->SetText(search_text); 138 EXPECT_NSEQ(base::SysUTF16ToNSString(search_text), 139 [[apps_search_box_controller_ searchTextField] stringValue]); 140 // Updates coming via the model should notify the delegate. 141 EXPECT_EQ(1, [delegate_ textChangeCount]); 142 143 // Updates from the view should update the model and notify the delegate. 144 [apps_search_box_controller_ clearSearch]; 145 EXPECT_EQ(base::string16(), model->text()); 146 EXPECT_NSEQ([NSString string], 147 [[apps_search_box_controller_ searchTextField] stringValue]); 148 EXPECT_EQ(2, [delegate_ textChangeCount]); 149 150 // Test pressing escape clears the search. First add some text. 151 model->SetText(search_text); 152 EXPECT_EQ(3, [delegate_ textChangeCount]); 153 154 EXPECT_NSEQ(base::SysUTF16ToNSString(search_text), 155 [[apps_search_box_controller_ searchTextField] stringValue]); 156 SimulateKeyAction(@selector(complete:)); 157 EXPECT_NSEQ([NSString string], 158 [[apps_search_box_controller_ searchTextField] stringValue]); 159 EXPECT_EQ(4, [delegate_ textChangeCount]); 160} 161 162// Test the popup menu items when there is only one user.. 163TEST_F(AppsSearchBoxControllerTest, SearchBoxMenuSingleUser) { 164 // Set a single user. We need to set the delegate again because the 165 // AppListModel observer isn't hooked up in these tests. 166 [delegate_ appListModel]->SetUsers(app_list::AppListModel::Users(1)); 167 [apps_search_box_controller_ setDelegate:delegate_]; 168 169 NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; 170 EXPECT_TRUE([apps_search_box_controller_ appListMenu]); 171 ui::MenuModel* menu_model 172 = [apps_search_box_controller_ appListMenu]->menu_model(); 173 // Add one to the item count to account for the blank, first item that Cocoa 174 // has in its popup menus. 175 EXPECT_EQ(menu_model->GetItemCount() + 1, 176 [[menu_control menu] numberOfItems]); 177 178 // All command ids should be less than |SELECT_PROFILE| as no user menu items 179 // are being shown. 180 for (int i = 0; i < menu_model->GetItemCount(); ++i) 181 EXPECT_LT(menu_model->GetCommandIdAt(i), AppListMenu::SELECT_PROFILE); 182 183 // The number of items should match the index that starts profile items. 184 EXPECT_EQ(AppListMenu::SELECT_PROFILE, menu_model->GetItemCount()); 185} 186 187// Test the popup menu items for the multi-profile case. 188TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) { 189 const app_list::AppListModel::Users& users = 190 [delegate_ appListModel]->users(); 191 NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; 192 EXPECT_TRUE([apps_search_box_controller_ appListMenu]); 193 ui::MenuModel* menu_model 194 = [apps_search_box_controller_ appListMenu]->menu_model(); 195 // Add one to the item count to account for the blank, first item that Cocoa 196 // has in its popup menus. 197 EXPECT_EQ(menu_model->GetItemCount() + 1, 198 [[menu_control menu] numberOfItems]); 199 200 ui::MenuModel* found_menu_model = menu_model; 201 int index; 202 MenuController* controller = [[menu_control menu] delegate]; 203 204 // The first user item is an unchecked label. 205 EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( 206 AppListMenu::SELECT_PROFILE, &menu_model, &index)); 207 EXPECT_EQ(found_menu_model, menu_model); 208 NSMenuItem* unchecked_user_item = [[menu_control menu] itemAtIndex:index + 1]; 209 [controller validateUserInterfaceItem:unchecked_user_item]; 210 // The profile name should be shown if there is no email available. 211 EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), 212 [unchecked_user_item title]); 213 EXPECT_EQ(NSOffState, [unchecked_user_item state]); 214 215 // The second user item is a checked label because it is the active profile. 216 EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( 217 AppListMenu::SELECT_PROFILE + 1, &menu_model, &index)); 218 EXPECT_EQ(found_menu_model, menu_model); 219 NSMenuItem* checked_user_item = [[menu_control menu] itemAtIndex:index + 1]; 220 [controller validateUserInterfaceItem:checked_user_item]; 221 // The email is shown when available. 222 EXPECT_NSEQ(base::SysUTF16ToNSString(users[1].email), 223 [checked_user_item title]); 224 EXPECT_EQ(NSOnState, [checked_user_item state]); 225 226 // A regular item should have just the label. 227 EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( 228 AppListMenu::SHOW_SETTINGS, &menu_model, &index)); 229 EXPECT_EQ(found_menu_model, menu_model); 230 NSMenuItem* settings_item = [[menu_control menu] itemAtIndex:index + 1]; 231 EXPECT_FALSE([settings_item view]); 232 EXPECT_NSEQ(base::SysUTF16ToNSString(menu_model->GetLabelAt(index)), 233 [settings_item title]); 234} 235 236// Test adding another user, and changing an existing one. 237TEST_F(AppsSearchBoxControllerTest, SearchBoxMenuChangingUsers) { 238 app_list::AppListModel::Users users = [delegate_ appListModel]->users(); 239 EXPECT_EQ(2u, users.size()); 240 ui::MenuModel* menu_model 241 = [apps_search_box_controller_ appListMenu]->menu_model(); 242 // Adding one to account for the empty item at index 0 in Cocoa popup menus. 243 int non_user_items = menu_model->GetItemCount() - users.size() + 1; 244 245 NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; 246 EXPECT_EQ(2, [[menu_control menu] numberOfItems] - non_user_items); 247 EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), 248 [[[menu_control menu] itemAtIndex:1] title]); 249 250 users[0].name = ASCIIToUTF16("renamed user"); 251 app_list::AppListModel::User new_user; 252 new_user.name = ASCIIToUTF16("user3"); 253 users.push_back(new_user); 254 [delegate_ appListModel]->SetUsers(users); 255 256 // Should now be an extra item, and it should have correct titles. 257 EXPECT_EQ(3, [[menu_control menu] numberOfItems] - non_user_items); 258 EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), 259 [[[menu_control menu] itemAtIndex:1] title]); 260 EXPECT_NSEQ(base::SysUTF16ToNSString(new_user.name), 261 [[[menu_control menu] itemAtIndex:3] title]); 262} 263 264} // namespace test 265} // namespace app_list 266