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