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.
5 #import "ui/app_list/cocoa/apps_search_box_controller.h"
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 #import "ui/app_list/cocoa/current_user_menu_item_view.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/test/ui_cocoa_test_helper.h"
18 @interface TestAppsSearchBoxDelegate : NSObject<AppsSearchBoxDelegate> {
20 app_list::SearchBoxModel searchBoxModel_;
21 app_list::test::AppListTestViewDelegate appListDelegate_;
25 @property(assign, nonatomic) int textChangeCount;
29 @implementation TestAppsSearchBoxDelegate
31 @synthesize textChangeCount = textChangeCount_;
33 - (app_list::SearchBoxModel*)searchBoxModel {
34 return &searchBoxModel_;
37 - (app_list::AppListViewDelegate*)appListDelegate {
38 return &appListDelegate_;
41 - (BOOL)control:(NSControl*)control
42 textView:(NSTextView*)textView
43 doCommandBySelector:(SEL)command {
47 - (void)modelTextDidChange {
51 - (CGFloat)bubbleCornerRadius {
60 class AppsSearchBoxControllerTest : public ui::CocoaTest {
62 AppsSearchBoxControllerTest() {
66 virtual void SetUp() OVERRIDE {
67 apps_search_box_controller_.reset(
68 [[AppsSearchBoxController alloc] initWithFrame:
69 NSMakeRect(0, 0, 400, 100)]);
70 delegate_.reset([[TestAppsSearchBoxDelegate alloc] init]);
71 [apps_search_box_controller_ setDelegate:delegate_];
73 ui::CocoaTest::SetUp();
74 [[test_window() contentView] addSubview:[apps_search_box_controller_ view]];
77 virtual void TearDown() OVERRIDE {
78 [apps_search_box_controller_ setDelegate:nil];
79 ui::CocoaTest::TearDown();
82 void SimulateKeyAction(SEL c) {
83 NSControl* control = [apps_search_box_controller_ searchTextField];
84 [apps_search_box_controller_ control:control
86 doCommandBySelector:c];
90 base::scoped_nsobject<TestAppsSearchBoxDelegate> delegate_;
91 base::scoped_nsobject<AppsSearchBoxController> apps_search_box_controller_;
94 DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxControllerTest);
97 TEST_VIEW(AppsSearchBoxControllerTest, [apps_search_box_controller_ view]);
99 // Test the search box initialization, and search input and clearing.
100 TEST_F(AppsSearchBoxControllerTest, SearchBoxModel) {
101 app_list::SearchBoxModel* model = [delegate_ searchBoxModel];
102 // Usually localized "Search".
103 const base::string16 hit_text(ASCIIToUTF16("hint"));
104 model->SetHintText(hit_text);
105 EXPECT_NSEQ(base::SysUTF16ToNSString(hit_text),
106 [[[apps_search_box_controller_ searchTextField] cell] placeholderString]);
108 const base::string16 search_text(ASCIIToUTF16("test"));
109 model->SetText(search_text);
110 EXPECT_NSEQ(base::SysUTF16ToNSString(search_text),
111 [[apps_search_box_controller_ searchTextField] stringValue]);
112 // Updates coming via the model should not notify the delegate.
113 EXPECT_EQ(0, [delegate_ textChangeCount]);
115 // Updates from the view should update the model and notify the delegate.
116 [apps_search_box_controller_ clearSearch];
117 EXPECT_EQ(base::string16(), model->text());
118 EXPECT_NSEQ([NSString string],
119 [[apps_search_box_controller_ searchTextField] stringValue]);
120 EXPECT_EQ(1, [delegate_ textChangeCount]);
122 // Test pressing escape clears the search.
123 model->SetText(search_text);
124 EXPECT_NSEQ(base::SysUTF16ToNSString(search_text),
125 [[apps_search_box_controller_ searchTextField] stringValue]);
126 SimulateKeyAction(@selector(complete:));
127 EXPECT_NSEQ([NSString string],
128 [[apps_search_box_controller_ searchTextField] stringValue]);
129 EXPECT_EQ(2, [delegate_ textChangeCount]);
132 // Test the popup menu items.
133 TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) {
134 NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl];
135 EXPECT_TRUE([apps_search_box_controller_ appListMenu]);
136 ui::MenuModel* menu_model
137 = [apps_search_box_controller_ appListMenu]->menu_model();
138 // Add one to the item count to account for the blank, first item that Cocoa
139 // has in its popup menus.
140 EXPECT_EQ(menu_model->GetItemCount() + 1,
141 [[menu_control menu] numberOfItems]);
143 // The CURRENT_USER item should contain our custom view.
144 ui::MenuModel* found_menu_model = menu_model;
146 EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId(
147 AppListMenu::CURRENT_USER, &menu_model, &index));
148 EXPECT_EQ(found_menu_model, menu_model);
149 NSMenuItem* current_user_item = [[menu_control menu] itemAtIndex:index + 1];
150 EXPECT_TRUE([current_user_item view]);
152 // A regular item should have just the label.
153 EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId(
154 AppListMenu::SHOW_SETTINGS, &menu_model, &index));
155 EXPECT_EQ(found_menu_model, menu_model);
156 NSMenuItem* settings_item = [[menu_control menu] itemAtIndex:index + 1];
157 EXPECT_FALSE([settings_item view]);
158 EXPECT_NSEQ(base::SysUTF16ToNSString(menu_model->GetLabelAt(index)),
159 [settings_item title]);
162 // Test initialization and display of the custom menu item that shows the
163 // currently signed-in user. This is a non-interactive view.
164 class AppsSearchBoxCustomMenuItemTest : public ui::CocoaTest {
166 AppsSearchBoxCustomMenuItemTest() {
170 virtual void SetUp() OVERRIDE {
171 scoped_ptr<AppListViewDelegate> delegate(new AppListTestViewDelegate);
172 current_user_menu_item_.reset([[[CurrentUserMenuItemView alloc]
173 initWithDelegate:delegate.get()] retain]);
174 ui::CocoaTest::SetUp();
175 [[test_window() contentView] addSubview:current_user_menu_item_];
179 base::scoped_nsobject<NSView> current_user_menu_item_;
182 DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxCustomMenuItemTest);
185 TEST_VIEW(AppsSearchBoxCustomMenuItemTest, current_user_menu_item_);
188 } // namespace app_list