apps_search_box_controller_unittest.mm revision 58537e28ecd584eab876aee8be7156509866d23a
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#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"
17
18@interface TestAppsSearchBoxDelegate : NSObject<AppsSearchBoxDelegate> {
19 @private
20  app_list::SearchBoxModel searchBoxModel_;
21  app_list::test::AppListTestViewDelegate appListDelegate_;
22  int textChangeCount_;
23}
24
25@property(assign, nonatomic) int textChangeCount;
26
27@end
28
29@implementation TestAppsSearchBoxDelegate
30
31@synthesize textChangeCount = textChangeCount_;
32
33- (app_list::SearchBoxModel*)searchBoxModel {
34  return &searchBoxModel_;
35}
36
37- (app_list::AppListViewDelegate*)appListDelegate {
38  return &appListDelegate_;
39}
40
41- (BOOL)control:(NSControl*)control
42               textView:(NSTextView*)textView
43    doCommandBySelector:(SEL)command {
44  return NO;
45}
46
47- (void)modelTextDidChange {
48  ++textChangeCount_;
49}
50
51- (CGFloat)bubbleCornerRadius {
52  return 3;
53}
54
55- (NSString*)currentUserName {
56  return @"";
57}
58
59- (NSString*)currentUserEmail {
60  return @"";
61}
62
63@end
64
65namespace app_list {
66namespace test {
67
68class AppsSearchBoxControllerTest : public ui::CocoaTest {
69 public:
70  AppsSearchBoxControllerTest() {
71    Init();
72  }
73
74  virtual void SetUp() OVERRIDE {
75    apps_search_box_controller_.reset(
76        [[AppsSearchBoxController alloc] initWithFrame:
77            NSMakeRect(0, 0, 400, 100)]);
78    delegate_.reset([[TestAppsSearchBoxDelegate alloc] init]);
79    [apps_search_box_controller_ setDelegate:delegate_];
80
81    ui::CocoaTest::SetUp();
82    [[test_window() contentView] addSubview:[apps_search_box_controller_ view]];
83  }
84
85  virtual void TearDown() OVERRIDE {
86    [apps_search_box_controller_ setDelegate:nil];
87    ui::CocoaTest::TearDown();
88  }
89
90  void SimulateKeyAction(SEL c) {
91    NSControl* control = [apps_search_box_controller_ searchTextField];
92    [apps_search_box_controller_ control:control
93                                textView:nil
94                     doCommandBySelector:c];
95  }
96
97 protected:
98  base::scoped_nsobject<TestAppsSearchBoxDelegate> delegate_;
99  base::scoped_nsobject<AppsSearchBoxController> apps_search_box_controller_;
100
101 private:
102  DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxControllerTest);
103};
104
105TEST_VIEW(AppsSearchBoxControllerTest, [apps_search_box_controller_ view]);
106
107// Test the search box initialization, and search input and clearing.
108TEST_F(AppsSearchBoxControllerTest, SearchBoxModel) {
109  app_list::SearchBoxModel* model = [delegate_ searchBoxModel];
110  // Usually localized "Search".
111  const base::string16 hit_text(ASCIIToUTF16("hint"));
112  model->SetHintText(hit_text);
113  EXPECT_NSEQ(base::SysUTF16ToNSString(hit_text),
114      [[[apps_search_box_controller_ searchTextField] cell] placeholderString]);
115
116  const base::string16 search_text(ASCIIToUTF16("test"));
117  model->SetText(search_text);
118  EXPECT_NSEQ(base::SysUTF16ToNSString(search_text),
119              [[apps_search_box_controller_ searchTextField] stringValue]);
120  // Updates coming via the model should notify the delegate.
121  EXPECT_EQ(1, [delegate_ textChangeCount]);
122
123  // Updates from the view should update the model and notify the delegate.
124  [apps_search_box_controller_ clearSearch];
125  EXPECT_EQ(base::string16(), model->text());
126  EXPECT_NSEQ([NSString string],
127              [[apps_search_box_controller_ searchTextField] stringValue]);
128  EXPECT_EQ(2, [delegate_ textChangeCount]);
129
130  // Test pressing escape clears the search. First add some text.
131  model->SetText(search_text);
132  EXPECT_EQ(3, [delegate_ textChangeCount]);
133
134  EXPECT_NSEQ(base::SysUTF16ToNSString(search_text),
135              [[apps_search_box_controller_ searchTextField] stringValue]);
136  SimulateKeyAction(@selector(complete:));
137  EXPECT_NSEQ([NSString string],
138              [[apps_search_box_controller_ searchTextField] stringValue]);
139  EXPECT_EQ(4, [delegate_ textChangeCount]);
140}
141
142// Test the popup menu items.
143TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) {
144  NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl];
145  EXPECT_TRUE([apps_search_box_controller_ appListMenu]);
146  ui::MenuModel* menu_model
147      = [apps_search_box_controller_ appListMenu]->menu_model();
148  // Add one to the item count to account for the blank, first item that Cocoa
149  // has in its popup menus.
150  EXPECT_EQ(menu_model->GetItemCount() + 1,
151            [[menu_control menu] numberOfItems]);
152
153  // The CURRENT_USER item should contain our custom view.
154  ui::MenuModel* found_menu_model = menu_model;
155  int index;
156  EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId(
157      AppListMenu::CURRENT_USER, &menu_model, &index));
158  EXPECT_EQ(found_menu_model, menu_model);
159  NSMenuItem* current_user_item = [[menu_control menu] itemAtIndex:index + 1];
160  EXPECT_TRUE([current_user_item view]);
161
162  // A regular item should have just the label.
163  EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId(
164      AppListMenu::SHOW_SETTINGS, &menu_model, &index));
165  EXPECT_EQ(found_menu_model, menu_model);
166  NSMenuItem* settings_item = [[menu_control menu] itemAtIndex:index + 1];
167  EXPECT_FALSE([settings_item view]);
168  EXPECT_NSEQ(base::SysUTF16ToNSString(menu_model->GetLabelAt(index)),
169              [settings_item title]);
170}
171
172// Test initialization and display of the custom menu item that shows the
173// currently signed-in user. This is a non-interactive view.
174class AppsSearchBoxCustomMenuItemTest : public ui::CocoaTest {
175 public:
176  AppsSearchBoxCustomMenuItemTest() {
177    Init();
178  }
179
180  virtual void SetUp() OVERRIDE {
181    current_user_menu_item_.reset([[[CurrentUserMenuItemView alloc]
182        initWithCurrentUser:@"testUser"
183                  userEmail:@"testUser@chromium.org"] retain]);
184    ui::CocoaTest::SetUp();
185    [[test_window() contentView] addSubview:current_user_menu_item_];
186  }
187
188 protected:
189  base::scoped_nsobject<NSView> current_user_menu_item_;
190
191 private:
192  DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxCustomMenuItemTest);
193};
194
195TEST_VIEW(AppsSearchBoxCustomMenuItemTest, current_user_menu_item_);
196
197}  // namespace test
198}  // namespace app_list
199