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