Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / base / ime / input_method_base_unittest.cc
blob129d3c531e74d2c53bc3d544826d7e58b49e9944
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 #include "ui/base/ime/input_method_base.h"
7 #include "base/gtest_prod_util.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/scoped_observer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/base/ime/dummy_text_input_client.h"
14 #include "ui/base/ime/input_method_observer.h"
15 #include "ui/base/ime/text_input_focus_manager.h"
16 #include "ui/base/ui_base_switches_util.h"
17 #include "ui/events/event.h"
19 namespace ui {
20 namespace {
22 class ClientChangeVerifier {
23 public:
24 ClientChangeVerifier()
25 : previous_client_(NULL),
26 next_client_(NULL),
27 call_expected_(false),
28 on_will_change_focused_client_called_(false),
29 on_did_change_focused_client_called_(false),
30 on_text_input_state_changed_(false) {
33 // Expects that focused text input client will not be changed.
34 void ExpectClientDoesNotChange() {
35 previous_client_ = NULL;
36 next_client_ = NULL;
37 call_expected_ = false;
38 on_will_change_focused_client_called_ = false;
39 on_did_change_focused_client_called_ = false;
40 on_text_input_state_changed_ = false;
43 // Expects that focused text input client will be changed from
44 // |previous_client| to |next_client|.
45 void ExpectClientChange(TextInputClient* previous_client,
46 TextInputClient* next_client) {
47 previous_client_ = previous_client;
48 next_client_ = next_client;
49 call_expected_ = true;
50 on_will_change_focused_client_called_ = false;
51 on_did_change_focused_client_called_ = false;
52 on_text_input_state_changed_ = false;
55 // Verifies the result satisfies the expectation or not.
56 void Verify() {
57 if (switches::IsTextInputFocusManagerEnabled()) {
58 EXPECT_FALSE(on_will_change_focused_client_called_);
59 EXPECT_FALSE(on_did_change_focused_client_called_);
60 EXPECT_FALSE(on_text_input_state_changed_);
61 } else {
62 EXPECT_EQ(call_expected_, on_will_change_focused_client_called_);
63 EXPECT_EQ(call_expected_, on_did_change_focused_client_called_);
64 EXPECT_EQ(call_expected_, on_text_input_state_changed_);
68 void OnWillChangeFocusedClient(TextInputClient* focused_before,
69 TextInputClient* focused) {
70 EXPECT_TRUE(call_expected_);
72 // Check arguments
73 EXPECT_EQ(previous_client_, focused_before);
74 EXPECT_EQ(next_client_, focused);
76 // Check call order
77 EXPECT_FALSE(on_will_change_focused_client_called_);
78 EXPECT_FALSE(on_did_change_focused_client_called_);
79 EXPECT_FALSE(on_text_input_state_changed_);
81 on_will_change_focused_client_called_ = true;
84 void OnDidChangeFocusedClient(TextInputClient* focused_before,
85 TextInputClient* focused) {
86 EXPECT_TRUE(call_expected_);
88 // Check arguments
89 EXPECT_EQ(previous_client_, focused_before);
90 EXPECT_EQ(next_client_, focused);
92 // Check call order
93 EXPECT_TRUE(on_will_change_focused_client_called_);
94 EXPECT_FALSE(on_did_change_focused_client_called_);
95 EXPECT_FALSE(on_text_input_state_changed_);
97 on_did_change_focused_client_called_ = true;
100 void OnTextInputStateChanged(const TextInputClient* client) {
101 EXPECT_TRUE(call_expected_);
103 // Check arguments
104 EXPECT_EQ(next_client_, client);
106 // Check call order
107 EXPECT_TRUE(on_will_change_focused_client_called_);
108 EXPECT_TRUE(on_did_change_focused_client_called_);
109 EXPECT_FALSE(on_text_input_state_changed_);
111 on_text_input_state_changed_ = true;
114 private:
115 TextInputClient* previous_client_;
116 TextInputClient* next_client_;
117 bool call_expected_;
118 bool on_will_change_focused_client_called_;
119 bool on_did_change_focused_client_called_;
120 bool on_text_input_state_changed_;
122 DISALLOW_COPY_AND_ASSIGN(ClientChangeVerifier);
125 class InputMethodBaseTest : public testing::Test {
126 protected:
127 InputMethodBaseTest() {
129 ~InputMethodBaseTest() override {}
131 void SetUp() override { message_loop_.reset(new base::MessageLoopForUI); }
133 void TearDown() override { message_loop_.reset(); }
135 private:
136 scoped_ptr<base::MessageLoop> message_loop_;
137 DISALLOW_COPY_AND_ASSIGN(InputMethodBaseTest);
140 class MockInputMethodBase : public InputMethodBase {
141 public:
142 // Note: this class does not take the ownership of |verifier|.
143 MockInputMethodBase(ClientChangeVerifier* verifier) : verifier_(verifier) {
145 ~MockInputMethodBase() override {}
147 private:
148 // Overriden from InputMethod.
149 bool OnUntranslatedIMEMessage(
150 const base::NativeEvent& event,
151 InputMethod::NativeEventResult* result) override {
152 return false;
154 bool DispatchKeyEvent(const ui::KeyEvent&) override { return false; }
155 void OnCaretBoundsChanged(const TextInputClient* client) override {}
156 void CancelComposition(const TextInputClient* client) override {}
157 void OnInputLocaleChanged() override {}
158 std::string GetInputLocale() override { return ""; }
159 bool IsActive() override { return false; }
160 bool IsCandidatePopupOpen() const override { return false; }
161 // Overriden from InputMethodBase.
162 void OnWillChangeFocusedClient(TextInputClient* focused_before,
163 TextInputClient* focused) override {
164 verifier_->OnWillChangeFocusedClient(focused_before, focused);
167 void OnDidChangeFocusedClient(TextInputClient* focused_before,
168 TextInputClient* focused) override {
169 verifier_->OnDidChangeFocusedClient(focused_before, focused);
172 ClientChangeVerifier* verifier_;
174 FRIEND_TEST_ALL_PREFIXES(InputMethodBaseTest, CandidateWindowEvents);
175 DISALLOW_COPY_AND_ASSIGN(MockInputMethodBase);
178 class MockInputMethodObserver : public InputMethodObserver {
179 public:
180 // Note: this class does not take the ownership of |verifier|.
181 explicit MockInputMethodObserver(ClientChangeVerifier* verifier)
182 : verifier_(verifier) {
184 ~MockInputMethodObserver() override {}
186 private:
187 void OnTextInputTypeChanged(const TextInputClient* client) override {}
188 void OnFocus() override {}
189 void OnBlur() override {}
190 void OnCaretBoundsChanged(const TextInputClient* client) override {}
191 void OnTextInputStateChanged(const TextInputClient* client) override {
192 verifier_->OnTextInputStateChanged(client);
194 void OnShowImeIfNeeded() override {}
195 void OnInputMethodDestroyed(const InputMethod* client) override {}
197 ClientChangeVerifier* verifier_;
198 DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
201 class MockTextInputClient : public DummyTextInputClient {
202 public:
203 MockTextInputClient()
204 : shown_event_count_(0), updated_event_count_(0), hidden_event_count_(0) {
206 ~MockTextInputClient() override {}
208 void OnCandidateWindowShown() override { ++shown_event_count_; }
209 void OnCandidateWindowUpdated() override { ++updated_event_count_; }
210 void OnCandidateWindowHidden() override { ++hidden_event_count_; }
212 int shown_event_count() const { return shown_event_count_; }
213 int updated_event_count() const { return updated_event_count_; }
214 int hidden_event_count() const { return hidden_event_count_; }
216 private:
217 int shown_event_count_;
218 int updated_event_count_;
219 int hidden_event_count_;
222 typedef ScopedObserver<InputMethod, InputMethodObserver>
223 InputMethodScopedObserver;
225 void SetFocusedTextInputClient(InputMethod* input_method,
226 TextInputClient* text_input_client) {
227 if (switches::IsTextInputFocusManagerEnabled()) {
228 TextInputFocusManager::GetInstance()->FocusTextInputClient(
229 text_input_client);
230 } else {
231 input_method->SetFocusedTextInputClient(text_input_client);
235 TEST_F(InputMethodBaseTest, SetFocusedTextInputClient) {
236 DummyTextInputClient text_input_client_1st;
237 DummyTextInputClient text_input_client_2nd;
239 ClientChangeVerifier verifier;
240 MockInputMethodBase input_method(&verifier);
241 MockInputMethodObserver input_method_observer(&verifier);
242 InputMethodScopedObserver scoped_observer(&input_method_observer);
243 scoped_observer.Add(&input_method);
245 // Assume that the top-level-widget gains focus.
246 input_method.OnFocus();
249 SCOPED_TRACE("Focus from NULL to 1st TextInputClient");
251 ASSERT_EQ(NULL, input_method.GetTextInputClient());
252 verifier.ExpectClientChange(NULL, &text_input_client_1st);
253 SetFocusedTextInputClient(&input_method, &text_input_client_1st);
254 EXPECT_EQ(&text_input_client_1st, input_method.GetTextInputClient());
255 verifier.Verify();
259 SCOPED_TRACE("Redundant focus events must be ignored");
260 verifier.ExpectClientDoesNotChange();
261 SetFocusedTextInputClient(&input_method, &text_input_client_1st);
262 verifier.Verify();
266 SCOPED_TRACE("Focus from 1st to 2nd TextInputClient");
268 ASSERT_EQ(&text_input_client_1st, input_method.GetTextInputClient());
269 verifier.ExpectClientChange(&text_input_client_1st,
270 &text_input_client_2nd);
271 SetFocusedTextInputClient(&input_method, &text_input_client_2nd);
272 EXPECT_EQ(&text_input_client_2nd, input_method.GetTextInputClient());
273 verifier.Verify();
277 SCOPED_TRACE("Focus from 2nd TextInputClient to NULL");
279 ASSERT_EQ(&text_input_client_2nd, input_method.GetTextInputClient());
280 verifier.ExpectClientChange(&text_input_client_2nd, NULL);
281 SetFocusedTextInputClient(&input_method, NULL);
282 EXPECT_EQ(NULL, input_method.GetTextInputClient());
283 verifier.Verify();
287 SCOPED_TRACE("Redundant focus events must be ignored");
288 verifier.ExpectClientDoesNotChange();
289 SetFocusedTextInputClient(&input_method, NULL);
290 verifier.Verify();
294 TEST_F(InputMethodBaseTest, DetachTextInputClient) {
295 // DetachTextInputClient is not supported when IsTextInputFocusManagerEnabled.
296 if (switches::IsTextInputFocusManagerEnabled())
297 return;
299 DummyTextInputClient text_input_client;
300 DummyTextInputClient text_input_client_the_other;
302 ClientChangeVerifier verifier;
303 MockInputMethodBase input_method(&verifier);
304 MockInputMethodObserver input_method_observer(&verifier);
305 InputMethodScopedObserver scoped_observer(&input_method_observer);
306 scoped_observer.Add(&input_method);
308 // Assume that the top-level-widget gains focus.
309 input_method.OnFocus();
311 // Initialize for the next test.
313 verifier.ExpectClientChange(NULL, &text_input_client);
314 input_method.SetFocusedTextInputClient(&text_input_client);
315 verifier.Verify();
319 SCOPED_TRACE("DetachTextInputClient must be ignored for other clients");
320 ASSERT_EQ(&text_input_client, input_method.GetTextInputClient());
321 verifier.ExpectClientDoesNotChange();
322 input_method.DetachTextInputClient(&text_input_client_the_other);
323 EXPECT_EQ(&text_input_client, input_method.GetTextInputClient());
324 verifier.Verify();
328 SCOPED_TRACE("DetachTextInputClient must succeed even after the "
329 "top-level loses the focus");
331 ASSERT_EQ(&text_input_client, input_method.GetTextInputClient());
332 input_method.OnBlur();
333 input_method.OnFocus();
334 verifier.ExpectClientChange(&text_input_client, NULL);
335 input_method.DetachTextInputClient(&text_input_client);
336 EXPECT_EQ(NULL, input_method.GetTextInputClient());
337 verifier.Verify();
341 TEST_F(InputMethodBaseTest, CandidateWindowEvents) {
342 MockTextInputClient text_input_client;
345 ClientChangeVerifier verifier;
346 MockInputMethodBase input_method_base(&verifier);
347 input_method_base.OnFocus();
349 verifier.ExpectClientChange(NULL, &text_input_client);
350 SetFocusedTextInputClient(&input_method_base, &text_input_client);
352 EXPECT_EQ(0, text_input_client.shown_event_count());
353 EXPECT_EQ(0, text_input_client.updated_event_count());
354 EXPECT_EQ(0, text_input_client.hidden_event_count());
356 input_method_base.OnCandidateWindowShown();
357 base::RunLoop().RunUntilIdle();
359 EXPECT_EQ(1, text_input_client.shown_event_count());
360 EXPECT_EQ(0, text_input_client.updated_event_count());
361 EXPECT_EQ(0, text_input_client.hidden_event_count());
363 input_method_base.OnCandidateWindowUpdated();
364 base::RunLoop().RunUntilIdle();
366 EXPECT_EQ(1, text_input_client.shown_event_count());
367 EXPECT_EQ(1, text_input_client.updated_event_count());
368 EXPECT_EQ(0, text_input_client.hidden_event_count());
370 input_method_base.OnCandidateWindowHidden();
371 base::RunLoop().RunUntilIdle();
373 EXPECT_EQ(1, text_input_client.shown_event_count());
374 EXPECT_EQ(1, text_input_client.updated_event_count());
375 EXPECT_EQ(1, text_input_client.hidden_event_count());
377 input_method_base.OnCandidateWindowShown();
380 // If InputMethod is deleted immediately after an event happens, but before
381 // its callback is invoked, the callback will be cancelled.
382 base::RunLoop().RunUntilIdle();
383 EXPECT_EQ(1, text_input_client.shown_event_count());
384 EXPECT_EQ(1, text_input_client.updated_event_count());
385 EXPECT_EQ(1, text_input_client.hidden_event_count());
388 } // namespace
389 } // namespace ui