1// Copyright 2014 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#include "ui/app_list/views/search_box_view.h"
6
7#include <cctype>
8#include <map>
9
10#include "base/strings/utf_string_conversions.h"
11#include "ui/app_list/test/app_list_test_view_delegate.h"
12#include "ui/app_list/views/search_box_view_delegate.h"
13#include "ui/views/controls/textfield/textfield.h"
14#include "ui/views/test/widget_test.h"
15
16namespace app_list {
17namespace test {
18
19class KeyPressCounterView : public views::View {
20 public:
21  KeyPressCounterView() : count_(0) {}
22  virtual ~KeyPressCounterView() {}
23
24  int GetCountAndReset() {
25    int count = count_;
26    count_ = 0;
27    return count;
28  }
29
30 private:
31  // Overridden from views::View:
32  virtual bool OnKeyPressed(const ui::KeyEvent& key_event) OVERRIDE {
33    if (!::isalnum(static_cast<int>(key_event.key_code()))) {
34      ++count_;
35      return true;
36    }
37    return false;
38  }
39  int count_;
40
41  DISALLOW_COPY_AND_ASSIGN(KeyPressCounterView);
42};
43
44class SearchBoxViewTest : public views::test::WidgetTest,
45                          public SearchBoxViewDelegate {
46 public:
47  SearchBoxViewTest() : query_changed_count_(0) {}
48  virtual ~SearchBoxViewTest() {}
49
50  // Overridden from testing::Test:
51  virtual void SetUp() OVERRIDE {
52    views::test::WidgetTest::SetUp();
53    widget_ = CreateTopLevelPlatformWidget();
54    view_ = new SearchBoxView(this, &view_delegate_);
55    counter_view_ = new KeyPressCounterView();
56    widget_->GetContentsView()->AddChildView(view_);
57    widget_->GetContentsView()->AddChildView(counter_view_);
58    view_->set_contents_view(counter_view_);
59  }
60
61  virtual void TearDown() OVERRIDE {
62    widget_->CloseNow();
63    views::test::WidgetTest::TearDown();
64  }
65
66 protected:
67  SearchBoxView* view() { return view_; }
68
69  void SetLongAutoLaunchTimeout() {
70    // Sets a long timeout that lasts longer than the test run.
71    view_delegate_.set_auto_launch_timeout(base::TimeDelta::FromDays(1));
72  }
73
74  base::TimeDelta GetAutoLaunchTimeout() {
75    return view_delegate_.GetAutoLaunchTimeout();
76  }
77
78  void ResetAutoLaunchTimeout() {
79    view_delegate_.set_auto_launch_timeout(base::TimeDelta());
80  }
81
82  int GetContentsViewKeyPressCountAndReset() {
83    return counter_view_->GetCountAndReset();
84  }
85
86  void KeyPress(ui::KeyboardCode key_code) {
87    ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE);
88    view_->search_box()->OnKeyPressed(event);
89    // Emulates the input method.
90    if (::isalnum(static_cast<int>(key_code))) {
91      base::char16 character = ::tolower(static_cast<int>(key_code));
92      view_->search_box()->InsertText(base::string16(1, character));
93    }
94  }
95
96  std::string GetLastQueryAndReset() {
97    base::string16 query = last_query_;
98    last_query_.clear();
99    return base::UTF16ToUTF8(query);
100  }
101
102  int GetQueryChangedCountAndReset() {
103    int result = query_changed_count_;
104    query_changed_count_ = 0;
105    return result;
106  }
107
108 private:
109  // Overridden from SearchBoxViewDelegate:
110  virtual void QueryChanged(SearchBoxView* sender) OVERRIDE {
111    ++query_changed_count_;
112    last_query_ = sender->search_box()->text();
113  }
114
115  AppListTestViewDelegate view_delegate_;
116  views::Widget* widget_;
117  SearchBoxView* view_;
118  KeyPressCounterView* counter_view_;
119  base::string16 last_query_;
120  int query_changed_count_;
121
122  DISALLOW_COPY_AND_ASSIGN(SearchBoxViewTest);
123};
124
125TEST_F(SearchBoxViewTest, Basic) {
126  KeyPress(ui::VKEY_A);
127  EXPECT_EQ("a", GetLastQueryAndReset());
128  EXPECT_EQ(1, GetQueryChangedCountAndReset());
129  EXPECT_EQ(0, GetContentsViewKeyPressCountAndReset());
130
131  KeyPress(ui::VKEY_DOWN);
132  EXPECT_EQ(0, GetQueryChangedCountAndReset());
133  EXPECT_EQ(1, GetContentsViewKeyPressCountAndReset());
134
135  view()->ClearSearch();
136  EXPECT_EQ(1, GetQueryChangedCountAndReset());
137  EXPECT_TRUE(GetLastQueryAndReset().empty());
138}
139
140TEST_F(SearchBoxViewTest, CancelAutoLaunch) {
141  SetLongAutoLaunchTimeout();
142  ASSERT_NE(base::TimeDelta(), GetAutoLaunchTimeout());
143
144  // Normal key event cancels the timeout.
145  KeyPress(ui::VKEY_A);
146  EXPECT_EQ(base::TimeDelta(), GetAutoLaunchTimeout());
147  ResetAutoLaunchTimeout();
148
149  // Unusual key event doesn't cancel -- it will be canceled in
150  // SearchResultListView.
151  SetLongAutoLaunchTimeout();
152  KeyPress(ui::VKEY_DOWN);
153  EXPECT_NE(base::TimeDelta(), GetAutoLaunchTimeout());
154  ResetAutoLaunchTimeout();
155
156  // Clearing search box also cancels.
157  SetLongAutoLaunchTimeout();
158  view()->ClearSearch();
159  EXPECT_EQ(base::TimeDelta(), GetAutoLaunchTimeout());
160}
161
162}  // namespace test
163}  // namespace app_list
164