Add unit test for the Settings API Bubble.
[chromium-blink-merge.git] / chrome / browser / ui / autofill / autofill_popup_controller_unittest.cc
blobb320deb399d0aaf814a01e6a6feffc09c3fc549d
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/core/browser/autofill_external_delegate.h"
17 #include "components/autofill/core/browser/autofill_manager.h"
18 #include "components/autofill/core/browser/autofill_test_utils.h"
19 #include "components/autofill/core/browser/popup_item_ids.h"
20 #include "components/autofill/core/browser/test_autofill_external_delegate.h"
21 #include "components/autofill/core/browser/test_autofill_manager_delegate.h"
22 #include "grit/component_scaled_resources.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/base/resource/resource_bundle.h"
26 #include "ui/gfx/display.h"
27 #include "ui/gfx/rect.h"
28 #include "ui/gfx/text_utils.h"
30 using ::testing::_;
31 using ::testing::AtLeast;
32 using ::testing::NiceMock;
33 using base::ASCIIToUTF16;
34 using base::WeakPtr;
36 namespace autofill {
37 namespace {
39 class MockAutofillExternalDelegate : public AutofillExternalDelegate {
40 public:
41 MockAutofillExternalDelegate(AutofillManager* autofill_manager,
42 AutofillDriver* autofill_driver)
43 : AutofillExternalDelegate(autofill_manager, autofill_driver) {}
44 virtual ~MockAutofillExternalDelegate() {}
46 virtual void DidSelectSuggestion(const base::string16& value,
47 int identifier) OVERRIDE {}
48 virtual void RemoveSuggestion(const base::string16& value,
49 int identifier) OVERRIDE {}
50 virtual void ClearPreviewedForm() OVERRIDE {}
51 base::WeakPtr<AutofillExternalDelegate> GetWeakPtr() {
52 return AutofillExternalDelegate::GetWeakPtr();
56 class MockAutofillManagerDelegate
57 : public autofill::TestAutofillManagerDelegate {
58 public:
59 MockAutofillManagerDelegate()
60 : prefs_(autofill::test::PrefServiceForTesting()) {
62 virtual ~MockAutofillManagerDelegate() {}
64 virtual PrefService* GetPrefs() OVERRIDE { return prefs_.get(); }
66 private:
67 scoped_ptr<PrefService> prefs_;
69 DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
72 class TestAutofillPopupController : public AutofillPopupControllerImpl {
73 public:
74 explicit TestAutofillPopupController(
75 base::WeakPtr<AutofillExternalDelegate> external_delegate,
76 const gfx::RectF& element_bounds)
77 : AutofillPopupControllerImpl(
78 external_delegate, NULL, NULL, element_bounds,
79 base::i18n::UNKNOWN_DIRECTION),
80 test_controller_common_(new TestPopupControllerCommon(element_bounds)) {
81 controller_common_.reset(test_controller_common_);
83 virtual ~TestAutofillPopupController() {}
85 void set_display(const gfx::Display& display) {
86 test_controller_common_->set_display(display);
89 // Making protected functions public for testing
90 using AutofillPopupControllerImpl::SetPopupBounds;
91 using AutofillPopupControllerImpl::names;
92 using AutofillPopupControllerImpl::subtexts;
93 using AutofillPopupControllerImpl::identifiers;
94 using AutofillPopupControllerImpl::selected_line;
95 using AutofillPopupControllerImpl::SetSelectedLine;
96 using AutofillPopupControllerImpl::SelectNextLine;
97 using AutofillPopupControllerImpl::SelectPreviousLine;
98 using AutofillPopupControllerImpl::RemoveSelectedLine;
99 using AutofillPopupControllerImpl::popup_bounds;
100 using AutofillPopupControllerImpl::element_bounds;
101 #if !defined(OS_ANDROID)
102 using AutofillPopupControllerImpl::GetNameFontListForRow;
103 using AutofillPopupControllerImpl::subtext_font_list;
104 using AutofillPopupControllerImpl::RowWidthWithoutText;
105 #endif
106 using AutofillPopupControllerImpl::SetValues;
107 using AutofillPopupControllerImpl::GetDesiredPopupWidth;
108 using AutofillPopupControllerImpl::GetDesiredPopupHeight;
109 using AutofillPopupControllerImpl::GetWeakPtr;
110 MOCK_METHOD1(InvalidateRow, void(size_t));
111 MOCK_METHOD0(UpdateBoundsAndRedrawPopup, void());
112 MOCK_METHOD0(Hide, void());
114 void DoHide() {
115 AutofillPopupControllerImpl::Hide();
118 private:
119 virtual void ShowView() OVERRIDE {}
121 TestPopupControllerCommon* test_controller_common_;
124 } // namespace
126 class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness {
127 public:
128 AutofillPopupControllerUnitTest()
129 : manager_delegate_(new MockAutofillManagerDelegate()),
130 autofill_popup_controller_(NULL) {}
131 virtual ~AutofillPopupControllerUnitTest() {}
133 virtual void SetUp() OVERRIDE {
134 ChromeRenderViewHostTestHarness::SetUp();
136 ContentAutofillDriver::CreateForWebContentsAndDelegate(
137 web_contents(),
138 manager_delegate_.get(),
139 "en-US",
140 AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
141 ContentAutofillDriver* driver =
142 ContentAutofillDriver::FromWebContents(web_contents());
143 external_delegate_.reset(
144 new NiceMock<MockAutofillExternalDelegate>(
145 driver->autofill_manager(),
146 driver));
148 autofill_popup_controller_ =
149 new testing::NiceMock<TestAutofillPopupController>(
150 external_delegate_->GetWeakPtr(),gfx::Rect());
153 virtual void TearDown() OVERRIDE {
154 // This will make sure the controller and the view (if any) are both
155 // cleaned up.
156 if (autofill_popup_controller_)
157 autofill_popup_controller_->DoHide();
159 external_delegate_.reset();
160 ChromeRenderViewHostTestHarness::TearDown();
163 TestAutofillPopupController* popup_controller() {
164 return autofill_popup_controller_;
167 MockAutofillExternalDelegate* delegate() {
168 return external_delegate_.get();
171 protected:
172 scoped_ptr<MockAutofillManagerDelegate> manager_delegate_;
173 scoped_ptr<NiceMock<MockAutofillExternalDelegate> > external_delegate_;
174 testing::NiceMock<TestAutofillPopupController>* autofill_popup_controller_;
177 TEST_F(AutofillPopupControllerUnitTest, SetBounds) {
178 // Ensure the popup size can be set and causes a redraw.
179 gfx::Rect popup_bounds(10, 10, 100, 100);
181 EXPECT_CALL(*autofill_popup_controller_,
182 UpdateBoundsAndRedrawPopup());
184 popup_controller()->SetPopupBounds(popup_bounds);
186 EXPECT_EQ(popup_bounds, popup_controller()->popup_bounds());
189 TEST_F(AutofillPopupControllerUnitTest, ChangeSelectedLine) {
190 // Set up the popup.
191 std::vector<base::string16> names(2, base::string16());
192 std::vector<int> autofill_ids(2, 0);
193 autofill_popup_controller_->Show(names, names, names, autofill_ids);
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_->subtexts().size()));
201 // Test wrapping before the front.
202 autofill_popup_controller_->SelectPreviousLine();
203 EXPECT_EQ(static_cast<int>(
204 autofill_popup_controller_->subtexts().size() - 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<base::string16> names(2, base::string16());
215 std::vector<int> autofill_ids(2, 0);
216 autofill_popup_controller_->Show(names, names, names, autofill_ids);
218 // Make sure that when a new line is selected, it is invalidated so it can
219 // be updated to show it is selected.
220 int selected_line = 0;
221 EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
222 autofill_popup_controller_->SetSelectedLine(selected_line);
224 // Ensure that the row isn't invalidated if it didn't change.
225 EXPECT_CALL(*autofill_popup_controller_,
226 InvalidateRow(selected_line)).Times(0);
227 autofill_popup_controller_->SetSelectedLine(selected_line);
229 // Change back to no selection.
230 EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
231 autofill_popup_controller_->SetSelectedLine(-1);
234 TEST_F(AutofillPopupControllerUnitTest, RemoveLine) {
235 // Set up the popup.
236 std::vector<base::string16> names(3, base::string16());
237 std::vector<int> autofill_ids;
238 autofill_ids.push_back(1);
239 autofill_ids.push_back(1);
240 autofill_ids.push_back(POPUP_ITEM_ID_AUTOFILL_OPTIONS);
241 autofill_popup_controller_->Show(names, names, names, autofill_ids);
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_->subtexts().size() - 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<base::string16> names(1, base::string16());
273 std::vector<int> autofill_ids;
274 autofill_ids.push_back(1);
275 autofill_popup_controller_->Show(names, names, names, autofill_ids);
277 // Generate a popup.
278 autofill::GenerateTestAutofillPopup(external_delegate_.get());
280 // Select the only line.
281 autofill_popup_controller_->SetSelectedLine(0);
283 // Remove the only line. There should be no row invalidation and the popup
284 // should then be hidden since there are no Autofill entries left.
285 EXPECT_CALL(*autofill_popup_controller_, Hide());
286 EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(_)).Times(0);
287 EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
290 TEST_F(AutofillPopupControllerUnitTest, SkipSeparator) {
291 // Set up the popup.
292 std::vector<base::string16> names(3, base::string16());
293 std::vector<int> autofill_ids;
294 autofill_ids.push_back(1);
295 autofill_ids.push_back(POPUP_ITEM_ID_SEPARATOR);
296 autofill_ids.push_back(POPUP_ITEM_ID_AUTOFILL_OPTIONS);
297 autofill_popup_controller_->Show(names, names, names, autofill_ids);
299 autofill_popup_controller_->SetSelectedLine(0);
301 // Make sure next skips the unselectable separator.
302 autofill_popup_controller_->SelectNextLine();
303 EXPECT_EQ(2, autofill_popup_controller_->selected_line());
305 // Make sure previous skips the unselectable separator.
306 autofill_popup_controller_->SelectPreviousLine();
307 EXPECT_EQ(0, autofill_popup_controller_->selected_line());
310 TEST_F(AutofillPopupControllerUnitTest, RowWidthWithoutText) {
311 std::vector<base::string16> names(4);
312 std::vector<base::string16> subtexts(4);
313 std::vector<base::string16> icons(4);
314 std::vector<int> ids(4);
316 // Set up some visible display so the text values are kept.
317 gfx::Display display(0, gfx::Rect(0, 0, 100, 100));
318 autofill_popup_controller_->set_display(display);
320 // Give elements 1 and 3 subtexts and elements 2 and 3 icons, to ensure
321 // all combinations of subtexts and icons.
322 subtexts[1] = ASCIIToUTF16("x");
323 subtexts[3] = ASCIIToUTF16("x");
324 icons[2] = ASCIIToUTF16("americanExpressCC");
325 icons[3] = ASCIIToUTF16("genericCC");
326 autofill_popup_controller_->Show(names, subtexts, icons, ids);
328 int base_size =
329 AutofillPopupView::kEndPadding * 2 +
330 kPopupBorderThickness * 2;
331 int subtext_increase = AutofillPopupView::kNamePadding;
333 EXPECT_EQ(base_size, autofill_popup_controller_->RowWidthWithoutText(0));
334 EXPECT_EQ(base_size + subtext_increase,
335 autofill_popup_controller_->RowWidthWithoutText(1));
336 EXPECT_EQ(base_size + AutofillPopupView::kIconPadding +
337 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
338 IDR_AUTOFILL_CC_AMEX).Width(),
339 autofill_popup_controller_->RowWidthWithoutText(2));
340 EXPECT_EQ(base_size + subtext_increase + AutofillPopupView::kIconPadding +
341 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
342 IDR_AUTOFILL_CC_GENERIC).Width(),
343 autofill_popup_controller_->RowWidthWithoutText(3));
346 TEST_F(AutofillPopupControllerUnitTest, UpdateDataListValues) {
347 std::vector<base::string16> items;
348 items.push_back(base::string16());
349 std::vector<int> ids;
350 ids.push_back(1);
352 autofill_popup_controller_->Show(items, items, items, ids);
354 EXPECT_EQ(items, autofill_popup_controller_->names());
355 EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
357 // Add one data list entry.
358 std::vector<base::string16> data_list_values;
359 data_list_values.push_back(ASCIIToUTF16("data list value 1"));
361 autofill_popup_controller_->UpdateDataListValues(data_list_values,
362 data_list_values);
364 // Update the expected values.
365 items.insert(items.begin(), data_list_values[0]);
366 items.insert(items.begin() + 1, base::string16());
367 ids.insert(ids.begin(), POPUP_ITEM_ID_DATALIST_ENTRY);
368 ids.insert(ids.begin() + 1, POPUP_ITEM_ID_SEPARATOR);
370 EXPECT_EQ(items, autofill_popup_controller_->names());
371 EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
373 // Add two data list entries (which should replace the current one).
374 data_list_values.push_back(ASCIIToUTF16("data list value 2"));
376 autofill_popup_controller_->UpdateDataListValues(data_list_values,
377 data_list_values);
379 // Update the expected values.
380 items.insert(items.begin() + 1, data_list_values[1]);
381 ids.insert(ids.begin(), POPUP_ITEM_ID_DATALIST_ENTRY);
383 EXPECT_EQ(items, autofill_popup_controller_->names());
384 EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
386 // Clear all data list values.
387 data_list_values.clear();
389 autofill_popup_controller_->UpdateDataListValues(data_list_values,
390 data_list_values);
392 items.clear();
393 items.push_back(base::string16());
394 ids.clear();
395 ids.push_back(1);
397 EXPECT_EQ(items, autofill_popup_controller_->names());
398 EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
401 TEST_F(AutofillPopupControllerUnitTest, PopupsWithOnlyDataLists) {
402 // Create the popup with a single datalist element.
403 std::vector<base::string16> items;
404 items.push_back(base::string16());
405 std::vector<int> ids;
406 ids.push_back(POPUP_ITEM_ID_DATALIST_ENTRY);
408 autofill_popup_controller_->Show(items, items, items, ids);
410 EXPECT_EQ(items, autofill_popup_controller_->names());
411 EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
413 // Replace the datalist element with a new one.
414 std::vector<base::string16> data_list_values;
415 data_list_values.push_back(ASCIIToUTF16("data list value 1"));
417 autofill_popup_controller_->UpdateDataListValues(data_list_values,
418 data_list_values);
420 EXPECT_EQ(data_list_values, autofill_popup_controller_->names());
421 // The id value should stay the same.
422 EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
424 // Clear datalist values and check that the popup becomes hidden.
425 EXPECT_CALL(*autofill_popup_controller_, Hide());
426 data_list_values.clear();
427 autofill_popup_controller_->UpdateDataListValues(data_list_values,
428 data_list_values);
431 TEST_F(AutofillPopupControllerUnitTest, GetOrCreate) {
432 ContentAutofillDriver* driver =
433 ContentAutofillDriver::FromWebContents(web_contents());
434 MockAutofillExternalDelegate delegate(driver->autofill_manager(), driver);
436 WeakPtr<AutofillPopupControllerImpl> controller =
437 AutofillPopupControllerImpl::GetOrCreate(
438 WeakPtr<AutofillPopupControllerImpl>(), delegate.GetWeakPtr(),
439 NULL, NULL, gfx::Rect(), base::i18n::UNKNOWN_DIRECTION);
440 EXPECT_TRUE(controller.get());
442 controller->Hide();
444 controller = AutofillPopupControllerImpl::GetOrCreate(
445 WeakPtr<AutofillPopupControllerImpl>(), delegate.GetWeakPtr(),
446 NULL, NULL, gfx::Rect(), base::i18n::UNKNOWN_DIRECTION);
447 EXPECT_TRUE(controller.get());
449 WeakPtr<AutofillPopupControllerImpl> controller2 =
450 AutofillPopupControllerImpl::GetOrCreate(controller,
451 delegate.GetWeakPtr(),
452 NULL,
453 NULL,
454 gfx::Rect(),
455 base::i18n::UNKNOWN_DIRECTION);
456 EXPECT_EQ(controller.get(), controller2.get());
457 controller->Hide();
459 testing::NiceMock<TestAutofillPopupController>* test_controller =
460 new testing::NiceMock<TestAutofillPopupController>(delegate.GetWeakPtr(),
461 gfx::Rect());
462 EXPECT_CALL(*test_controller, Hide());
464 gfx::RectF bounds(0.f, 0.f, 1.f, 2.f);
465 base::WeakPtr<AutofillPopupControllerImpl> controller3 =
466 AutofillPopupControllerImpl::GetOrCreate(
467 test_controller->GetWeakPtr(),
468 delegate.GetWeakPtr(),
469 NULL,
470 NULL,
471 bounds,
472 base::i18n::UNKNOWN_DIRECTION);
473 EXPECT_EQ(
474 bounds,
475 static_cast<AutofillPopupController*>(controller3.get())->
476 element_bounds());
477 controller3->Hide();
479 // Hide the test_controller to delete it.
480 test_controller->DoHide();
483 TEST_F(AutofillPopupControllerUnitTest, ProperlyResetController) {
484 std::vector<base::string16> names(2);
485 std::vector<int> ids(2);
486 popup_controller()->SetValues(names, names, names, ids);
487 popup_controller()->SetSelectedLine(0);
489 // Now show a new popup with the same controller, but with fewer items.
490 WeakPtr<AutofillPopupControllerImpl> controller =
491 AutofillPopupControllerImpl::GetOrCreate(
492 popup_controller()->GetWeakPtr(),
493 delegate()->GetWeakPtr(),
494 NULL,
495 NULL,
496 gfx::Rect(),
497 base::i18n::UNKNOWN_DIRECTION);
498 EXPECT_NE(0, controller->selected_line());
499 EXPECT_TRUE(controller->names().empty());
502 #if !defined(OS_ANDROID)
503 TEST_F(AutofillPopupControllerUnitTest, ElideText) {
504 std::vector<base::string16> names;
505 names.push_back(ASCIIToUTF16("Text that will need to be trimmed"));
506 names.push_back(ASCIIToUTF16("Untrimmed"));
508 std::vector<base::string16> subtexts;
509 subtexts.push_back(ASCIIToUTF16("Label that will be trimmed"));
510 subtexts.push_back(ASCIIToUTF16("Untrimmed"));
512 std::vector<base::string16> icons(2, ASCIIToUTF16("genericCC"));
513 std::vector<int> autofill_ids(2, 0);
515 // Show the popup once so we can easily generate the size it needs.
516 autofill_popup_controller_->Show(names, subtexts, icons, autofill_ids);
518 // Ensure the popup will be too small to display all of the first row.
519 int popup_max_width =
520 gfx::GetStringWidth(
521 names[0], autofill_popup_controller_->GetNameFontListForRow(0)) +
522 gfx::GetStringWidth(
523 subtexts[0], autofill_popup_controller_->subtext_font_list()) - 25;
524 gfx::Rect popup_bounds = gfx::Rect(0, 0, popup_max_width, 0);
525 autofill_popup_controller_->set_display(gfx::Display(0, popup_bounds));
527 autofill_popup_controller_->Show(names, subtexts, icons, autofill_ids);
529 // The first element was long so it should have been trimmed.
530 EXPECT_NE(names[0], autofill_popup_controller_->names()[0]);
531 EXPECT_NE(subtexts[0], autofill_popup_controller_->subtexts()[0]);
533 // The second element was shorter so it should be unchanged.
534 EXPECT_EQ(names[1], autofill_popup_controller_->names()[1]);
535 EXPECT_EQ(subtexts[1], autofill_popup_controller_->subtexts()[1]);
537 #endif
539 } // namespace autofill