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