autofill_popup_controller_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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.
4
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/test/base/chrome_render_view_host_test_harness.h"
12#include "chrome/test/base/testing_profile.h"
13#include "components/autofill/content/browser/autofill_driver_impl.h"
14#include "components/autofill/core/browser/autofill_external_delegate.h"
15#include "components/autofill/core/browser/autofill_manager.h"
16#include "components/autofill/core/browser/autofill_test_utils.h"
17#include "components/autofill/core/browser/test_autofill_external_delegate.h"
18#include "components/autofill/core/browser/test_autofill_manager_delegate.h"
19#include "grit/webkit_resources.h"
20#include "testing/gmock/include/gmock/gmock.h"
21#include "testing/gtest/include/gtest/gtest.h"
22#include "third_party/WebKit/public/web/WebAutofillClient.h"
23#include "ui/base/resource/resource_bundle.h"
24#include "ui/gfx/display.h"
25#include "ui/gfx/rect.h"
26
27using ::testing::_;
28using ::testing::AtLeast;
29using ::testing::NiceMock;
30using base::WeakPtr;
31using blink::WebAutofillClient;
32
33namespace autofill {
34namespace {
35
36class MockAutofillExternalDelegate : public AutofillExternalDelegate {
37 public:
38  MockAutofillExternalDelegate(AutofillManager* autofill_manager,
39                               AutofillDriver* autofill_driver)
40      : AutofillExternalDelegate(autofill_manager, autofill_driver) {}
41  virtual ~MockAutofillExternalDelegate() {}
42
43  virtual void DidSelectSuggestion(int identifier) OVERRIDE {}
44  virtual void RemoveSuggestion(const string16& value, int identifier) OVERRIDE
45      {}
46  virtual void ClearPreviewedForm() OVERRIDE {}
47  base::WeakPtr<AutofillExternalDelegate> GetWeakPtr() {
48    return AutofillExternalDelegate::GetWeakPtr();
49  }
50};
51
52class MockAutofillManagerDelegate
53    : public autofill::TestAutofillManagerDelegate {
54 public:
55  MockAutofillManagerDelegate()
56      : prefs_(autofill::test::PrefServiceForTesting()) {
57  }
58  virtual ~MockAutofillManagerDelegate() {}
59
60  virtual PrefService* GetPrefs() OVERRIDE { return prefs_.get(); }
61
62 private:
63  scoped_ptr<PrefService> prefs_;
64
65  DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
66};
67
68class TestAutofillPopupController : public AutofillPopupControllerImpl {
69 public:
70  explicit TestAutofillPopupController(
71      base::WeakPtr<AutofillExternalDelegate> external_delegate,
72      const gfx::RectF& element_bounds)
73      : AutofillPopupControllerImpl(
74            external_delegate, NULL, NULL, element_bounds,
75            base::i18n::UNKNOWN_DIRECTION) {}
76  virtual ~TestAutofillPopupController() {}
77
78  void set_display(const gfx::Display display) {
79    display_ = display;
80  }
81  virtual gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const
82      OVERRIDE {
83    return display_;
84  }
85
86  // Making protected functions public for testing
87  using AutofillPopupControllerImpl::SetPopupBounds;
88  using AutofillPopupControllerImpl::names;
89  using AutofillPopupControllerImpl::subtexts;
90  using AutofillPopupControllerImpl::identifiers;
91  using AutofillPopupControllerImpl::selected_line;
92  using AutofillPopupControllerImpl::SetSelectedLine;
93  using AutofillPopupControllerImpl::SelectNextLine;
94  using AutofillPopupControllerImpl::SelectPreviousLine;
95  using AutofillPopupControllerImpl::RemoveSelectedLine;
96  using AutofillPopupControllerImpl::popup_bounds;
97  using AutofillPopupControllerImpl::element_bounds;
98#if !defined(OS_ANDROID)
99  using AutofillPopupControllerImpl::GetNameFontForRow;
100  using AutofillPopupControllerImpl::subtext_font;
101  using AutofillPopupControllerImpl::RowWidthWithoutText;
102#endif
103  using AutofillPopupControllerImpl::SetValues;
104  using AutofillPopupControllerImpl::GetDesiredPopupWidth;
105  using AutofillPopupControllerImpl::GetDesiredPopupHeight;
106  using AutofillPopupControllerImpl::GetWeakPtr;
107  MOCK_METHOD1(InvalidateRow, void(size_t));
108  MOCK_METHOD0(UpdateBoundsAndRedrawPopup, void());
109  MOCK_METHOD0(Hide, void());
110
111  void DoHide() {
112    AutofillPopupControllerImpl::Hide();
113  }
114
115 private:
116  virtual void ShowView() OVERRIDE {}
117
118  gfx::Display display_;
119};
120
121}  // namespace
122
123class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness {
124 public:
125  AutofillPopupControllerUnitTest()
126      : manager_delegate_(new MockAutofillManagerDelegate()),
127        autofill_popup_controller_(NULL) {}
128  virtual ~AutofillPopupControllerUnitTest() {}
129
130  virtual void SetUp() OVERRIDE {
131    ChromeRenderViewHostTestHarness::SetUp();
132
133    AutofillDriverImpl::CreateForWebContentsAndDelegate(
134        web_contents(),
135        manager_delegate_.get(),
136        "en-US",
137        AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
138    AutofillDriverImpl* driver =
139        AutofillDriverImpl::FromWebContents(web_contents());
140    external_delegate_.reset(
141        new NiceMock<MockAutofillExternalDelegate>(
142            driver->autofill_manager(),
143            driver));
144
145    autofill_popup_controller_ =
146        new testing::NiceMock<TestAutofillPopupController>(
147            external_delegate_->GetWeakPtr(),gfx::Rect());
148  }
149
150  virtual void TearDown() OVERRIDE {
151    // This will make sure the controller and the view (if any) are both
152    // cleaned up.
153    if (autofill_popup_controller_)
154      autofill_popup_controller_->DoHide();
155
156    external_delegate_.reset();
157    ChromeRenderViewHostTestHarness::TearDown();
158  }
159
160  TestAutofillPopupController* popup_controller() {
161    return autofill_popup_controller_;
162  }
163
164  MockAutofillExternalDelegate* delegate() {
165    return external_delegate_.get();
166  }
167
168 protected:
169  scoped_ptr<MockAutofillManagerDelegate> manager_delegate_;
170  scoped_ptr<NiceMock<MockAutofillExternalDelegate> > external_delegate_;
171  testing::NiceMock<TestAutofillPopupController>* autofill_popup_controller_;
172};
173
174TEST_F(AutofillPopupControllerUnitTest, SetBounds) {
175  // Ensure the popup size can be set and causes a redraw.
176  gfx::Rect popup_bounds(10, 10, 100, 100);
177
178  EXPECT_CALL(*autofill_popup_controller_,
179              UpdateBoundsAndRedrawPopup());
180
181  popup_controller()->SetPopupBounds(popup_bounds);
182
183  EXPECT_EQ(popup_bounds, popup_controller()->popup_bounds());
184}
185
186TEST_F(AutofillPopupControllerUnitTest, ChangeSelectedLine) {
187  // Set up the popup.
188  std::vector<string16> names(2, string16());
189  std::vector<int> autofill_ids(2, 0);
190  autofill_popup_controller_->Show(names, names, names, autofill_ids);
191
192  EXPECT_LT(autofill_popup_controller_->selected_line(), 0);
193  // Check that there are at least 2 values so that the first and last selection
194  // are different.
195  EXPECT_GE(2,
196      static_cast<int>(autofill_popup_controller_->subtexts().size()));
197
198  // Test wrapping before the front.
199  autofill_popup_controller_->SelectPreviousLine();
200  EXPECT_EQ(static_cast<int>(
201      autofill_popup_controller_->subtexts().size() - 1),
202      autofill_popup_controller_->selected_line());
203
204  // Test wrapping after the end.
205  autofill_popup_controller_->SelectNextLine();
206  EXPECT_EQ(0, autofill_popup_controller_->selected_line());
207}
208
209TEST_F(AutofillPopupControllerUnitTest, RedrawSelectedLine) {
210  // Set up the popup.
211  std::vector<string16> names(2, string16());
212  std::vector<int> autofill_ids(2, 0);
213  autofill_popup_controller_->Show(names, names, names, autofill_ids);
214
215  // Make sure that when a new line is selected, it is invalidated so it can
216  // be updated to show it is selected.
217  int selected_line = 0;
218  EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
219  autofill_popup_controller_->SetSelectedLine(selected_line);
220
221  // Ensure that the row isn't invalidated if it didn't change.
222  EXPECT_CALL(*autofill_popup_controller_,
223              InvalidateRow(selected_line)).Times(0);
224  autofill_popup_controller_->SetSelectedLine(selected_line);
225
226  // Change back to no selection.
227  EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(selected_line));
228  autofill_popup_controller_->SetSelectedLine(-1);
229}
230
231TEST_F(AutofillPopupControllerUnitTest, RemoveLine) {
232  // Set up the popup.
233  std::vector<string16> names(3, string16());
234  std::vector<int> autofill_ids;
235  autofill_ids.push_back(1);
236  autofill_ids.push_back(1);
237  autofill_ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
238  autofill_popup_controller_->Show(names, names, names, autofill_ids);
239
240  // Generate a popup, so it can be hidden later. It doesn't matter what the
241  // external_delegate thinks is being shown in the process, since we are just
242  // testing the popup here.
243  autofill::GenerateTestAutofillPopup(external_delegate_.get());
244
245  // No line is selected so the removal should fail.
246  EXPECT_FALSE(autofill_popup_controller_->RemoveSelectedLine());
247
248  // Try to remove the last entry and ensure it fails (it is an option).
249  autofill_popup_controller_->SetSelectedLine(
250      autofill_popup_controller_->subtexts().size() - 1);
251  EXPECT_FALSE(autofill_popup_controller_->RemoveSelectedLine());
252  EXPECT_LE(0, autofill_popup_controller_->selected_line());
253
254  // Remove the first entry. The popup should be redrawn since its size has
255  // changed.
256  EXPECT_CALL(*autofill_popup_controller_, UpdateBoundsAndRedrawPopup());
257  autofill_popup_controller_->SetSelectedLine(0);
258  EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
259
260  // Remove the last entry. The popup should then be hidden since there are
261  // no Autofill entries left.
262  EXPECT_CALL(*autofill_popup_controller_, Hide());
263  autofill_popup_controller_->SetSelectedLine(0);
264  EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
265}
266
267TEST_F(AutofillPopupControllerUnitTest, RemoveOnlyLine) {
268  // Set up the popup.
269  std::vector<string16> names(1, string16());
270  std::vector<int> autofill_ids;
271  autofill_ids.push_back(1);
272  autofill_popup_controller_->Show(names, names, names, autofill_ids);
273
274  // Generate a popup.
275  autofill::GenerateTestAutofillPopup(external_delegate_.get());
276
277  // Select the only line.
278  autofill_popup_controller_->SetSelectedLine(0);
279
280  // Remove the only line. There should be no row invalidation and the popup
281  // should then be hidden since there are no Autofill entries left.
282  EXPECT_CALL(*autofill_popup_controller_, Hide());
283  EXPECT_CALL(*autofill_popup_controller_, InvalidateRow(_)).Times(0);
284  EXPECT_TRUE(autofill_popup_controller_->RemoveSelectedLine());
285}
286
287TEST_F(AutofillPopupControllerUnitTest, SkipSeparator) {
288  // Set up the popup.
289  std::vector<string16> names(3, string16());
290  std::vector<int> autofill_ids;
291  autofill_ids.push_back(1);
292  autofill_ids.push_back(WebAutofillClient::MenuItemIDSeparator);
293  autofill_ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
294  autofill_popup_controller_->Show(names, names, names, autofill_ids);
295
296  autofill_popup_controller_->SetSelectedLine(0);
297
298  // Make sure next skips the unselectable separator.
299  autofill_popup_controller_->SelectNextLine();
300  EXPECT_EQ(2, autofill_popup_controller_->selected_line());
301
302  // Make sure previous skips the unselectable separator.
303  autofill_popup_controller_->SelectPreviousLine();
304  EXPECT_EQ(0, autofill_popup_controller_->selected_line());
305}
306
307TEST_F(AutofillPopupControllerUnitTest, RowWidthWithoutText) {
308  std::vector<string16> names(4);
309  std::vector<string16> subtexts(4);
310  std::vector<string16> icons(4);
311  std::vector<int> ids(4);
312
313  // Set up some visible display so the text values are kept.
314  gfx::Display display(0, gfx::Rect(0, 0, 100, 100));
315  autofill_popup_controller_->set_display(display);
316
317  // Give elements 1 and 3 subtexts and elements 2 and 3 icons, to ensure
318  // all combinations of subtexts and icons.
319  subtexts[1] = ASCIIToUTF16("x");
320  subtexts[3] = ASCIIToUTF16("x");
321  icons[2] = ASCIIToUTF16("americanExpressCC");
322  icons[3] = ASCIIToUTF16("genericCC");
323  autofill_popup_controller_->Show(names, subtexts, icons, ids);
324
325  int base_size =
326      AutofillPopupView::kEndPadding * 2 +
327      AutofillPopupView::kBorderThickness * 2;
328  int subtext_increase = AutofillPopupView::kNamePadding;
329
330  EXPECT_EQ(base_size, autofill_popup_controller_->RowWidthWithoutText(0));
331  EXPECT_EQ(base_size + subtext_increase,
332            autofill_popup_controller_->RowWidthWithoutText(1));
333  EXPECT_EQ(base_size + AutofillPopupView::kIconPadding +
334                ui::ResourceBundle::GetSharedInstance().GetImageNamed(
335                    IDR_AUTOFILL_CC_AMEX).Width(),
336            autofill_popup_controller_->RowWidthWithoutText(2));
337  EXPECT_EQ(base_size + subtext_increase + AutofillPopupView::kIconPadding +
338                ui::ResourceBundle::GetSharedInstance().GetImageNamed(
339                    IDR_AUTOFILL_CC_GENERIC).Width(),
340            autofill_popup_controller_->RowWidthWithoutText(3));
341}
342
343TEST_F(AutofillPopupControllerUnitTest, UpdateDataListValues) {
344  std::vector<string16> items;
345  items.push_back(string16());
346  std::vector<int> ids;
347  ids.push_back(1);
348
349  autofill_popup_controller_->Show(items, items, items, ids);
350
351  EXPECT_EQ(items, autofill_popup_controller_->names());
352  EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
353
354  // Add one data list entry.
355  std::vector<string16> data_list_values;
356  data_list_values.push_back(ASCIIToUTF16("data list value 1"));
357
358  autofill_popup_controller_->UpdateDataListValues(data_list_values,
359                                                   data_list_values);
360
361  // Update the expected values.
362  items.insert(items.begin(), data_list_values[0]);
363  items.insert(items.begin() + 1, string16());
364  ids.insert(ids.begin(), WebAutofillClient::MenuItemIDDataListEntry);
365  ids.insert(ids.begin() + 1, WebAutofillClient::MenuItemIDSeparator);
366
367  EXPECT_EQ(items, autofill_popup_controller_->names());
368  EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
369
370  // Add two data list entries (which should replace the current one).
371  data_list_values.push_back(ASCIIToUTF16("data list value 2"));
372
373  autofill_popup_controller_->UpdateDataListValues(data_list_values,
374                                                   data_list_values);
375
376  // Update the expected values.
377  items.insert(items.begin() + 1, data_list_values[1]);
378  ids.insert(ids.begin(), WebAutofillClient::MenuItemIDDataListEntry);
379
380  EXPECT_EQ(items, autofill_popup_controller_->names());
381  EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
382
383  // Clear all data list values.
384  data_list_values.clear();
385
386  autofill_popup_controller_->UpdateDataListValues(data_list_values,
387                                                   data_list_values);
388
389  items.clear();
390  items.push_back(string16());
391  ids.clear();
392  ids.push_back(1);
393
394  EXPECT_EQ(items, autofill_popup_controller_->names());
395  EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
396}
397
398TEST_F(AutofillPopupControllerUnitTest, PopupsWithOnlyDataLists) {
399  // Create the popup with a single datalist element.
400  std::vector<string16> items;
401  items.push_back(string16());
402  std::vector<int> ids;
403  ids.push_back(WebAutofillClient::MenuItemIDDataListEntry);
404
405  autofill_popup_controller_->Show(items, items, items, ids);
406
407  EXPECT_EQ(items, autofill_popup_controller_->names());
408  EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
409
410  // Replace the datalist element with a new one.
411  std::vector<string16> data_list_values;
412  data_list_values.push_back(ASCIIToUTF16("data list value 1"));
413
414  autofill_popup_controller_->UpdateDataListValues(data_list_values,
415                                                   data_list_values);
416
417  EXPECT_EQ(data_list_values, autofill_popup_controller_->names());
418  // The id value should stay the same.
419  EXPECT_EQ(ids, autofill_popup_controller_->identifiers());
420
421  // Clear datalist values and check that the popup becomes hidden.
422  EXPECT_CALL(*autofill_popup_controller_, Hide());
423  data_list_values.clear();
424  autofill_popup_controller_->UpdateDataListValues(data_list_values,
425                                                   data_list_values);
426}
427
428TEST_F(AutofillPopupControllerUnitTest, GetOrCreate) {
429  AutofillDriverImpl* driver =
430      AutofillDriverImpl::FromWebContents(web_contents());
431  MockAutofillExternalDelegate delegate(driver->autofill_manager(), driver);
432
433  WeakPtr<AutofillPopupControllerImpl> controller =
434      AutofillPopupControllerImpl::GetOrCreate(
435          WeakPtr<AutofillPopupControllerImpl>(), delegate.GetWeakPtr(),
436          NULL, NULL, gfx::Rect(), base::i18n::UNKNOWN_DIRECTION);
437  EXPECT_TRUE(controller.get());
438
439  controller->Hide();
440
441  controller = AutofillPopupControllerImpl::GetOrCreate(
442      WeakPtr<AutofillPopupControllerImpl>(), delegate.GetWeakPtr(),
443      NULL, NULL, gfx::Rect(), base::i18n::UNKNOWN_DIRECTION);
444  EXPECT_TRUE(controller.get());
445
446  WeakPtr<AutofillPopupControllerImpl> controller2 =
447      AutofillPopupControllerImpl::GetOrCreate(controller,
448                                               delegate.GetWeakPtr(),
449                                               NULL,
450                                               NULL,
451                                               gfx::Rect(),
452                                               base::i18n::UNKNOWN_DIRECTION);
453  EXPECT_EQ(controller.get(), controller2.get());
454  controller->Hide();
455
456  testing::NiceMock<TestAutofillPopupController>* test_controller =
457      new testing::NiceMock<TestAutofillPopupController>(delegate.GetWeakPtr(),
458                                                         gfx::Rect());
459  EXPECT_CALL(*test_controller, Hide());
460
461  gfx::RectF bounds(0.f, 0.f, 1.f, 2.f);
462  base::WeakPtr<AutofillPopupControllerImpl> controller3 =
463      AutofillPopupControllerImpl::GetOrCreate(
464          test_controller->GetWeakPtr(),
465          delegate.GetWeakPtr(),
466          NULL,
467          NULL,
468          bounds,
469          base::i18n::UNKNOWN_DIRECTION);
470  EXPECT_EQ(
471      bounds,
472      static_cast<AutofillPopupController*>(controller3.get())->
473          element_bounds());
474  controller3->Hide();
475
476  // Hide the test_controller to delete it.
477  test_controller->DoHide();
478}
479
480TEST_F(AutofillPopupControllerUnitTest, ProperlyResetController) {
481  std::vector<string16> names(2);
482  std::vector<int> ids(2);
483  popup_controller()->SetValues(names, names, names, ids);
484  popup_controller()->SetSelectedLine(0);
485
486  // Now show a new popup with the same controller, but with fewer items.
487  WeakPtr<AutofillPopupControllerImpl> controller =
488      AutofillPopupControllerImpl::GetOrCreate(
489          popup_controller()->GetWeakPtr(),
490          delegate()->GetWeakPtr(),
491          NULL,
492          NULL,
493          gfx::Rect(),
494          base::i18n::UNKNOWN_DIRECTION);
495  EXPECT_NE(0, controller->selected_line());
496  EXPECT_TRUE(controller->names().empty());
497}
498
499#if !defined(OS_ANDROID)
500TEST_F(AutofillPopupControllerUnitTest, ElideText) {
501  std::vector<string16> names;
502  names.push_back(ASCIIToUTF16("Text that will need to be trimmed"));
503  names.push_back(ASCIIToUTF16("Untrimmed"));
504
505  std::vector<string16> subtexts;
506  subtexts.push_back(ASCIIToUTF16("Label that will be trimmed"));
507  subtexts.push_back(ASCIIToUTF16("Untrimmed"));
508
509  std::vector<string16> icons(2, ASCIIToUTF16("genericCC"));
510  std::vector<int> autofill_ids(2, 0);
511
512  // Show the popup once so we can easily generate the size it needs.
513  autofill_popup_controller_->Show(names, subtexts, icons, autofill_ids);
514
515  // Ensure the popup will be too small to display all of the first row.
516  int popup_max_width =
517      autofill_popup_controller_->GetNameFontForRow(0).GetStringWidth(
518          names[0]) +
519      autofill_popup_controller_->subtext_font().GetStringWidth(subtexts[0]) -
520      25;
521  gfx::Rect popup_bounds = gfx::Rect(0, 0, popup_max_width, 0);
522  autofill_popup_controller_->set_display(gfx::Display(0, popup_bounds));
523
524  autofill_popup_controller_->Show(names, subtexts, icons, autofill_ids);
525
526  // The first element was long so it should have been trimmed.
527  EXPECT_NE(names[0], autofill_popup_controller_->names()[0]);
528  EXPECT_NE(subtexts[0], autofill_popup_controller_->subtexts()[0]);
529
530  // The second element was shorter so it should be unchanged.
531  EXPECT_EQ(names[1], autofill_popup_controller_->names()[1]);
532  EXPECT_EQ(subtexts[1], autofill_popup_controller_->subtexts()[1]);
533}
534#endif
535
536TEST_F(AutofillPopupControllerUnitTest, GrowPopupInSpace) {
537  std::vector<string16> names(1);
538  std::vector<int> autofill_ids(1, 1);
539
540  // Call Show so that GetDesired...() will be able to provide valid values.
541  autofill_popup_controller_->Show(names, names, names, autofill_ids);
542  int desired_width = autofill_popup_controller_->GetDesiredPopupWidth();
543  int desired_height = autofill_popup_controller_->GetDesiredPopupHeight();
544
545  // Set up the visible screen space.
546  gfx::Display display(0,
547                       gfx::Rect(0, 0, desired_width * 2, desired_height * 2));
548
549  // Store the possible element bounds and the popup bounds they should result
550  // in.
551  std::vector<gfx::RectF> element_bounds;
552  std::vector<gfx::Rect> expected_popup_bounds;
553
554  // The popup grows down and to the right.
555  element_bounds.push_back(gfx::RectF(0, 0, 0, 0));
556  expected_popup_bounds.push_back(
557      gfx::Rect(0, 0, desired_width, desired_height));
558
559  // The popup grows down and to the left.
560  element_bounds.push_back(gfx::RectF(2 * desired_width, 0, 0, 0));
561  expected_popup_bounds.push_back(
562      gfx::Rect(desired_width, 0, desired_width, desired_height));
563
564  // The popup grows up and to the right.
565  element_bounds.push_back(gfx::RectF(0, 2 * desired_height, 0, 0));
566  expected_popup_bounds.push_back(
567      gfx::Rect(0, desired_height, desired_width, desired_height));
568
569  // The popup grows up and to the left.
570  element_bounds.push_back(
571      gfx::RectF(2 * desired_width, 2 * desired_height, 0, 0));
572  expected_popup_bounds.push_back(
573      gfx::Rect(desired_width, desired_height, desired_width, desired_height));
574
575  // The popup would be partial off the top and left side of the screen.
576  element_bounds.push_back(
577      gfx::RectF(-desired_width / 2, -desired_height / 2, 0, 0));
578  expected_popup_bounds.push_back(
579      gfx::Rect(0, 0, desired_width, desired_height));
580
581  // The popup would be partially off the bottom and the right side of
582  // the screen.
583  element_bounds.push_back(
584      gfx::RectF(desired_width * 1.5, desired_height * 1.5, 0, 0));
585  expected_popup_bounds.push_back(
586      gfx::Rect((desired_width + 1) / 2, (desired_height + 1) / 2,
587                desired_width, desired_height));
588
589  for (size_t i = 0; i < element_bounds.size(); ++i) {
590    AutofillDriverImpl* driver =
591        AutofillDriverImpl::FromWebContents(web_contents());
592    NiceMock<MockAutofillExternalDelegate> external_delegate(
593        driver->autofill_manager(), driver);
594    TestAutofillPopupController* autofill_popup_controller =
595        new TestAutofillPopupController(external_delegate.GetWeakPtr(),
596                                        element_bounds[i]);
597
598    autofill_popup_controller->set_display(display);
599    autofill_popup_controller->Show(names, names, names, autofill_ids);
600
601    EXPECT_EQ(expected_popup_bounds[i].ToString(),
602              autofill_popup_controller->popup_bounds().ToString()) <<
603        "Popup bounds failed to match for test " << i;
604
605    // Hide the controller to delete it.
606    autofill_popup_controller->DoHide();
607  }
608}
609
610}  // namespace autofill
611