ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / ui / autofill / autofill_popup_controller_unittest.cc
blob71e262aa36d1f5a6e5a69a561fadf426267bfb25
1 // Copyright (c) 2012 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 "base/memory/scoped_ptr.h"
6 #include "base/memory/weak_ptr.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
10 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
11 #include "chrome/browser/ui/autofill/popup_constants.h"
12 #include "chrome/browser/ui/autofill/test_popup_controller_common.h"
13 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "components/autofill/content/browser/content_autofill_driver.h"
16 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
17 #include "components/autofill/core/browser/autofill_external_delegate.h"
18 #include "components/autofill/core/browser/autofill_manager.h"
19 #include "components/autofill/core/browser/autofill_test_utils.h"
20 #include "components/autofill/core/browser/popup_item_ids.h"
21 #include "components/autofill/core/browser/test_autofill_client.h"
22 #include "components/autofill/core/browser/test_autofill_external_delegate.h"
23 #include "content/public/browser/web_contents.h"
24 #include "grit/components_scaled_resources.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/display.h"
29 #include "ui/gfx/geometry/rect.h"
30 #include "ui/gfx/text_utils.h"
32 using ::testing::_;
33 using ::testing::AtLeast;
34 using ::testing::NiceMock;
35 using base::ASCIIToUTF16;
36 using base::WeakPtr;
38 namespace autofill {
39 namespace {
41 class MockAutofillExternalDelegate : public AutofillExternalDelegate {
42 public:
43 MockAutofillExternalDelegate(AutofillManager* autofill_manager,
44 AutofillDriver* autofill_driver)
45 : AutofillExternalDelegate(autofill_manager, autofill_driver) {}
46 ~MockAutofillExternalDelegate() override {}
48 void DidSelectSuggestion(const base::string16& value,
49 int identifier) override {}
50 void RemoveSuggestion(const base::string16& value, int identifier) override {}
51 void ClearPreviewedForm() override {}
52 base::WeakPtr<AutofillExternalDelegate> GetWeakPtr() {
53 return AutofillExternalDelegate::GetWeakPtr();
57 class MockAutofillClient : public autofill::TestAutofillClient {
58 public:
59 MockAutofillClient() : prefs_(autofill::test::PrefServiceForTesting()) {}
60 ~MockAutofillClient() override {}
62 PrefService* GetPrefs() override { return prefs_.get(); }
64 private:
65 scoped_ptr<PrefService> prefs_;
67 DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
70 class TestAutofillPopupController : public AutofillPopupControllerImpl {
71 public:
72 explicit TestAutofillPopupController(
73 base::WeakPtr<AutofillExternalDelegate> external_delegate,
74 const gfx::RectF& element_bounds)
75 : AutofillPopupControllerImpl(
76 external_delegate, NULL, NULL, element_bounds,
77 base::i18n::UNKNOWN_DIRECTION),
78 test_controller_common_(new TestPopupControllerCommon(element_bounds)) {
79 controller_common_.reset(test_controller_common_);
81 virtual ~TestAutofillPopupController() {}
83 void set_display(const gfx::Display& display) {
84 test_controller_common_->set_display(display);
87 // Making protected functions public for testing
88 using AutofillPopupControllerImpl::SetPopupBounds;
89 using AutofillPopupControllerImpl::GetLineCount;
90 using AutofillPopupControllerImpl::GetSuggestionAt;
91 using AutofillPopupControllerImpl::GetElidedValueAt;
92 using AutofillPopupControllerImpl::GetElidedLabelAt;
93 using AutofillPopupControllerImpl::selected_line;
94 using AutofillPopupControllerImpl::SetSelectedLine;
95 using AutofillPopupControllerImpl::SelectNextLine;
96 using AutofillPopupControllerImpl::SelectPreviousLine;
97 using AutofillPopupControllerImpl::RemoveSelectedLine;
98 using AutofillPopupControllerImpl::popup_bounds;
99 using AutofillPopupControllerImpl::element_bounds;
100 #if !defined(OS_ANDROID)
101 using AutofillPopupControllerImpl::GetValueFontListForRow;
102 using AutofillPopupControllerImpl::GetLabelFontList;
103 using AutofillPopupControllerImpl::RowWidthWithoutText;
104 #endif
105 using AutofillPopupControllerImpl::SetValues;
106 using AutofillPopupControllerImpl::GetDesiredPopupWidth;
107 using AutofillPopupControllerImpl::GetDesiredPopupHeight;
108 using AutofillPopupControllerImpl::GetWeakPtr;
109 MOCK_METHOD1(InvalidateRow, void(size_t));
110 MOCK_METHOD0(UpdateBoundsAndRedrawPopup, void());
111 MOCK_METHOD0(Hide, void());
113 void DoHide() {
114 AutofillPopupControllerImpl::Hide();
117 private:
118 virtual void ShowView() override {}
120 TestPopupControllerCommon* test_controller_common_;
123 } // namespace
125 class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness {
126 public:
127 AutofillPopupControllerUnitTest()
128 : autofill_client_(new MockAutofillClient()),
129 autofill_popup_controller_(NULL) {}
130 ~AutofillPopupControllerUnitTest() override {}
132 void SetUp() override {
133 ChromeRenderViewHostTestHarness::SetUp();
135 ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
136 web_contents(), autofill_client_.get(), "en-US",
137 AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
138 ContentAutofillDriverFactory* factory =
139 ContentAutofillDriverFactory::FromWebContents(web_contents());
140 ContentAutofillDriver* driver =
141 factory->DriverForFrame(web_contents()->GetMainFrame());
142 external_delegate_.reset(
143 new NiceMock<MockAutofillExternalDelegate>(
144 driver->autofill_manager(),
145 driver));
147 autofill_popup_controller_ =
148 new testing::NiceMock<TestAutofillPopupController>(
149 external_delegate_->GetWeakPtr(),gfx::Rect());
152 void TearDown() override {
153 // This will make sure the controller and the view (if any) are both
154 // cleaned up.
155 if (autofill_popup_controller_)
156 autofill_popup_controller_->DoHide();
158 external_delegate_.reset();
159 ChromeRenderViewHostTestHarness::TearDown();
162 TestAutofillPopupController* popup_controller() {
163 return autofill_popup_controller_;
166 MockAutofillExternalDelegate* delegate() {
167 return external_delegate_.get();
170 protected:
171 scoped_ptr<MockAutofillClient> autofill_client_;
172 scoped_ptr<NiceMock<MockAutofillExternalDelegate> > external_delegate_;
173 testing::NiceMock<TestAutofillPopupController>* autofill_popup_controller_;
176 TEST_F(AutofillPopupControllerUnitTest, SetBounds) {
177 // Ensure the popup size can be set and causes a redraw.
178 gfx::Rect popup_bounds(10, 10, 100, 100);
180 EXPECT_CALL(*autofill_popup_controller_,
181 UpdateBoundsAndRedrawPopup());
183 popup_controller()->SetPopupBounds(popup_bounds);
185 EXPECT_EQ(popup_bounds, popup_controller()->popup_bounds());
188 TEST_F(AutofillPopupControllerUnitTest, ChangeSelectedLine) {
189 // Set up the popup.
190 std::vector<Suggestion> suggestions;
191 suggestions.push_back(Suggestion("", "", "", 0));
192 suggestions.push_back(Suggestion("", "", "", 0));
193 autofill_popup_controller_->Show(suggestions);
195 EXPECT_LT(autofill_popup_controller_->selected_line(), 0);
196 // Check that there are at least 2 values so that the first and last selection
197 // are different.
198 EXPECT_GE(2,
199 static_cast<int>(autofill_popup_controller_->GetLineCount()));
201 // Test wrapping before the front.
202 autofill_popup_controller_->SelectPreviousLine();
203 EXPECT_EQ(static_cast<int>(
204 autofill_popup_controller_->GetLineCount() - 1),
205 autofill_popup_controller_->selected_line());
207 // Test wrapping after the end.
208 autofill_popup_controller_->SelectNextLine();
209 EXPECT_EQ(0, autofill_popup_controller_->selected_line());
212 TEST_F(AutofillPopupControllerUnitTest, RedrawSelectedLine) {
213 // Set up the popup.
214 std::vector<Suggestion> suggestions;
215 suggestions.push_back(Suggestion("", "", "", 0));
216 suggestions.push_back(Suggestion("", "", "", 0));
217 autofill_popup_controller_->Show(suggestions);
219 // Make sure that when a new line is selected, it is invalidated so it can
220 // be updated to show it is selected.
221 int selected_line = 0;
222 EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
223 autofill_popup_controller_->SetSelectedLine(selected_line);
225 // Ensure that the row isn't invalidated if it didn't change.
226 EXPECT_CALL(*autofill_popup_controller_,
227 InvalidateRow(selected_line)).Times(0);
228 autofill_popup_controller_->SetSelectedLine(selected_line);
230 // Change back to no selection.
231 EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
232 autofill_popup_controller_->SetSelectedLine(-1);
235 TEST_F(AutofillPopupControllerUnitTest, RemoveLine) {
236 // Set up the popup.
237 std::vector<Suggestion> suggestions;
238 suggestions.push_back(Suggestion("", "", "", 1));
239 suggestions.push_back(Suggestion("", "", "", 1));
240 suggestions.push_back(Suggestion("", "", "", POPUP_ITEM_ID_AUTOFILL_OPTIONS));
241 autofill_popup_controller_->Show(suggestions);
243 // Generate a popup, so it can be hidden later. It doesn't matter what the
244 // external_delegate thinks is being shown in the process, since we are just
245 // testing the popup here.
246 autofill::GenerateTestAutofillPopup(external_delegate_.get());
248 // No line is selected so the removal should fail.
249 EXPECT_FALSE(autofill_popup_controller_->RemoveSelectedLine());
251 // Try to remove the last entry and ensure it fails (it is an option).
252 autofill_popup_controller_->SetSelectedLine(
253 autofill_popup_controller_->GetLineCount() - 1);
254 EXPECT_FALSE(autofill_popup_controller_->RemoveSelectedLine());
255 EXPECT_LE(0, autofill_popup_controller_->selected_line());
257 // Remove the first entry. The popup should be redrawn since its size has
258 // changed.
259 EXPECT_CALL(*autofill_popup_controller_, UpdateBoundsAndRedrawPopup());
260 autofill_popup_controller_->SetSelectedLine(0);
261 EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
263 // Remove the last entry. The popup should then be hidden since there are
264 // no Autofill entries left.
265 EXPECT_CALL(*autofill_popup_controller_, Hide());
266 autofill_popup_controller_->SetSelectedLine(0);
267 EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
270 TEST_F(AutofillPopupControllerUnitTest, RemoveOnlyLine) {
271 // Set up the popup.
272 std::vector<Suggestion> suggestions;
273 suggestions.push_back(Suggestion("", "", "", 1));
274 autofill_popup_controller_->Show(suggestions);
276 // Generate a popup.
277 autofill::GenerateTestAutofillPopup(external_delegate_.get());
279 // Select the only line.
280 autofill_popup_controller_->SetSelectedLine(0);
282 // Remove the only line. There should be no row invalidation and the popup
283 // should then be hidden since there are no Autofill entries left.
284 EXPECT_CALL(*autofill_popup_controller_, Hide());
285 EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(_)).Times(0);
286 EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
289 TEST_F(AutofillPopupControllerUnitTest, SkipSeparator) {
290 // Set up the popup.
291 std::vector<Suggestion> suggestions;
292 suggestions.push_back(Suggestion("", "", "", 1));
293 suggestions.push_back(Suggestion("", "", "", POPUP_ITEM_ID_SEPARATOR));
294 suggestions.push_back(Suggestion("", "", "", POPUP_ITEM_ID_AUTOFILL_OPTIONS));
295 autofill_popup_controller_->Show(suggestions);
297 autofill_popup_controller_->SetSelectedLine(0);
299 // Make sure next skips the unselectable separator.
300 autofill_popup_controller_->SelectNextLine();
301 EXPECT_EQ(2, autofill_popup_controller_->selected_line());
303 // Make sure previous skips the unselectable separator.
304 autofill_popup_controller_->SelectPreviousLine();
305 EXPECT_EQ(0, autofill_popup_controller_->selected_line());
308 TEST_F(AutofillPopupControllerUnitTest, RowWidthWithoutText) {
309 // Give elements 1 and 3 subtexts and elements 2 and 3 icons, to ensure
310 // all combinations of subtexts and icons.
311 std::vector<Suggestion> suggestions;
312 suggestions.push_back(Suggestion("", "", "", 0));
313 suggestions.push_back(Suggestion("", "x", "", 0));
314 suggestions.push_back(Suggestion("", "", "americanExpressCC", 0));
315 suggestions.push_back(Suggestion("", "x", "genericCC", 0));
317 // Set up some visible display so the text values are kept.
318 gfx::Display display(0, gfx::Rect(0, 0, 100, 100));
319 autofill_popup_controller_->set_display(display);
321 autofill_popup_controller_->Show(suggestions);
323 int base_size =
324 AutofillPopupView::kEndPadding * 2 +
325 kPopupBorderThickness * 2;
326 int subtext_increase = AutofillPopupView::kNamePadding;
328 EXPECT_EQ(base_size, autofill_popup_controller_->RowWidthWithoutText(0));
329 EXPECT_EQ(base_size + subtext_increase,
330 autofill_popup_controller_->RowWidthWithoutText(1));
331 EXPECT_EQ(base_size + AutofillPopupView::kIconPadding +
332 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
333 IDR_AUTOFILL_CC_AMEX).Width(),
334 autofill_popup_controller_->RowWidthWithoutText(2));
335 EXPECT_EQ(base_size + subtext_increase + AutofillPopupView::kIconPadding +
336 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
337 IDR_AUTOFILL_CC_GENERIC).Width(),
338 autofill_popup_controller_->RowWidthWithoutText(3));
341 TEST_F(AutofillPopupControllerUnitTest, UpdateDataListValues) {
342 std::vector<Suggestion> suggestions;
343 suggestions.push_back(Suggestion("", "", "", 1));
344 autofill_popup_controller_->Show(suggestions);
346 // Add one data list entry.
347 base::string16 value1 = ASCIIToUTF16("data list value 1");
348 std::vector<base::string16> data_list_values;
349 data_list_values.push_back(value1);
351 autofill_popup_controller_->UpdateDataListValues(data_list_values,
352 data_list_values);
354 ASSERT_EQ(3u, autofill_popup_controller_->GetLineCount());
356 Suggestion result0 = autofill_popup_controller_->GetSuggestionAt(0);
357 EXPECT_EQ(value1, result0.value);
358 EXPECT_EQ(value1, autofill_popup_controller_->GetElidedValueAt(0));
359 EXPECT_EQ(value1, result0.label);
360 EXPECT_EQ(value1, autofill_popup_controller_->GetElidedLabelAt(0));
361 EXPECT_EQ(POPUP_ITEM_ID_DATALIST_ENTRY, result0.frontend_id);
363 Suggestion result1 = autofill_popup_controller_->GetSuggestionAt(1);
364 EXPECT_EQ(base::string16(), result1.value);
365 EXPECT_EQ(base::string16(), result1.label);
366 EXPECT_EQ(POPUP_ITEM_ID_SEPARATOR, result1.frontend_id);
368 Suggestion result2 = autofill_popup_controller_->GetSuggestionAt(2);
369 EXPECT_EQ(base::string16(), result2.value);
370 EXPECT_EQ(base::string16(), result2.label);
371 EXPECT_EQ(1, result2.frontend_id);
373 // Add two data list entries (which should replace the current one).
374 base::string16 value2 = ASCIIToUTF16("data list value 2");
375 data_list_values.push_back(value2);
377 autofill_popup_controller_->UpdateDataListValues(data_list_values,
378 data_list_values);
379 ASSERT_EQ(4u, autofill_popup_controller_->GetLineCount());
381 // Original one first, followed by new one, then separator.
382 EXPECT_EQ(value1, autofill_popup_controller_->GetSuggestionAt(0).value);
383 EXPECT_EQ(value1, autofill_popup_controller_->GetElidedValueAt(0));
384 EXPECT_EQ(value2, autofill_popup_controller_->GetSuggestionAt(1).value);
385 EXPECT_EQ(value2, autofill_popup_controller_->GetElidedValueAt(1));
386 EXPECT_EQ(POPUP_ITEM_ID_SEPARATOR,
387 autofill_popup_controller_->GetSuggestionAt(2).frontend_id);
389 // Clear all data list values.
390 data_list_values.clear();
391 autofill_popup_controller_->UpdateDataListValues(data_list_values,
392 data_list_values);
394 ASSERT_EQ(1u, autofill_popup_controller_->GetLineCount());
395 EXPECT_EQ(1, autofill_popup_controller_->GetSuggestionAt(0).frontend_id);
398 TEST_F(AutofillPopupControllerUnitTest, PopupsWithOnlyDataLists) {
399 // Create the popup with a single datalist element.
400 std::vector<Suggestion> suggestions;
401 suggestions.push_back(Suggestion("", "", "", POPUP_ITEM_ID_DATALIST_ENTRY));
402 autofill_popup_controller_->Show(suggestions);
404 // Replace the datalist element with a new one.
405 base::string16 value1 = ASCIIToUTF16("data list value 1");
406 std::vector<base::string16> data_list_values;
407 data_list_values.push_back(value1);
409 autofill_popup_controller_->UpdateDataListValues(data_list_values,
410 data_list_values);
412 ASSERT_EQ(1u, autofill_popup_controller_->GetLineCount());
413 EXPECT_EQ(value1, autofill_popup_controller_->GetSuggestionAt(0).value);
414 EXPECT_EQ(POPUP_ITEM_ID_DATALIST_ENTRY,
415 autofill_popup_controller_->GetSuggestionAt(0).frontend_id);
417 // Clear datalist values and check that the popup becomes hidden.
418 EXPECT_CALL(*autofill_popup_controller_, Hide());
419 data_list_values.clear();
420 autofill_popup_controller_->UpdateDataListValues(data_list_values,
421 data_list_values);
424 TEST_F(AutofillPopupControllerUnitTest, GetOrCreate) {
425 ContentAutofillDriverFactory* factory =
426 ContentAutofillDriverFactory::FromWebContents(web_contents());
427 ContentAutofillDriver* driver =
428 factory->DriverForFrame(web_contents()->GetMainFrame());
429 MockAutofillExternalDelegate delegate(driver->autofill_manager(), driver);
431 WeakPtr<AutofillPopupControllerImpl> controller =
432 AutofillPopupControllerImpl::GetOrCreate(
433 WeakPtr<AutofillPopupControllerImpl>(), delegate.GetWeakPtr(),
434 NULL, NULL, gfx::Rect(), base::i18n::UNKNOWN_DIRECTION);
435 EXPECT_TRUE(controller.get());
437 controller->Hide();
439 controller = AutofillPopupControllerImpl::GetOrCreate(
440 WeakPtr<AutofillPopupControllerImpl>(), delegate.GetWeakPtr(),
441 NULL, NULL, gfx::Rect(), base::i18n::UNKNOWN_DIRECTION);
442 EXPECT_TRUE(controller.get());
444 WeakPtr<AutofillPopupControllerImpl> controller2 =
445 AutofillPopupControllerImpl::GetOrCreate(controller,
446 delegate.GetWeakPtr(),
447 NULL,
448 NULL,
449 gfx::Rect(),
450 base::i18n::UNKNOWN_DIRECTION);
451 EXPECT_EQ(controller.get(), controller2.get());
452 controller->Hide();
454 testing::NiceMock<TestAutofillPopupController>* test_controller =
455 new testing::NiceMock<TestAutofillPopupController>(delegate.GetWeakPtr(),
456 gfx::Rect());
457 EXPECT_CALL(*test_controller, Hide());
459 gfx::RectF bounds(0.f, 0.f, 1.f, 2.f);
460 base::WeakPtr<AutofillPopupControllerImpl> controller3 =
461 AutofillPopupControllerImpl::GetOrCreate(
462 test_controller->GetWeakPtr(),
463 delegate.GetWeakPtr(),
464 NULL,
465 NULL,
466 bounds,
467 base::i18n::UNKNOWN_DIRECTION);
468 EXPECT_EQ(
469 bounds,
470 static_cast<AutofillPopupController*>(controller3.get())->
471 element_bounds());
472 controller3->Hide();
474 // Hide the test_controller to delete it.
475 test_controller->DoHide();
478 TEST_F(AutofillPopupControllerUnitTest, ProperlyResetController) {
479 std::vector<Suggestion> suggestions;
480 suggestions.push_back(Suggestion("", "", "", 0));
481 suggestions.push_back(Suggestion("", "", "", 0));
482 popup_controller()->SetValues(suggestions);
483 popup_controller()->SetSelectedLine(0);
485 // Now show a new popup with the same controller, but with fewer items.
486 WeakPtr<AutofillPopupControllerImpl> controller =
487 AutofillPopupControllerImpl::GetOrCreate(
488 popup_controller()->GetWeakPtr(),
489 delegate()->GetWeakPtr(),
490 NULL,
491 NULL,
492 gfx::Rect(),
493 base::i18n::UNKNOWN_DIRECTION);
494 EXPECT_NE(0, controller->selected_line());
495 EXPECT_EQ(0u, controller->GetLineCount());
498 #if !defined(OS_ANDROID)
499 TEST_F(AutofillPopupControllerUnitTest, ElideText) {
500 std::vector<Suggestion> suggestions;
501 suggestions.push_back(
502 Suggestion("Text that will need to be trimmed",
503 "Label that will be trimmed", "genericCC", 0));
504 suggestions.push_back(
505 Suggestion("untrimmed", "Untrimmed", "genericCC", 0));
507 // Show the popup once so we can easily generate the size it needs.
508 autofill_popup_controller_->Show(suggestions);
510 // Ensure the popup will be too small to display all of the first row.
511 int popup_max_width =
512 gfx::GetStringWidth(
513 suggestions[0].value,
514 autofill_popup_controller_->GetValueFontListForRow(0)) +
515 gfx::GetStringWidth(
516 suggestions[0].label,
517 autofill_popup_controller_->GetLabelFontList()) - 25;
518 gfx::Rect popup_bounds = gfx::Rect(0, 0, popup_max_width, 0);
519 autofill_popup_controller_->set_display(gfx::Display(0, popup_bounds));
521 autofill_popup_controller_->Show(suggestions);
523 // The first element was long so it should have been trimmed.
524 EXPECT_NE(autofill_popup_controller_->GetSuggestionAt(0).value,
525 autofill_popup_controller_->GetElidedValueAt(0));
526 EXPECT_NE(autofill_popup_controller_->GetSuggestionAt(0).label,
527 autofill_popup_controller_->GetElidedLabelAt(0));
529 // The second element was shorter so it should be unchanged.
530 EXPECT_EQ(autofill_popup_controller_->GetSuggestionAt(1).value,
531 autofill_popup_controller_->GetElidedValueAt(1));
532 EXPECT_EQ(autofill_popup_controller_->GetSuggestionAt(1).label,
533 autofill_popup_controller_->GetElidedLabelAt(1));
535 #endif
537 } // namespace autofill