File: autofill_uitest_util.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (175 lines) | stat: -rw-r--r-- 7,780 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autofill/autofill_uitest_util.h"

#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/run_until.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/core/browser/data_manager/payments/payments_data_manager_test_api.h"
#include "components/autofill/core/browser/data_manager/personal_data_manager.h"
#include "components/autofill/core/browser/data_manager/personal_data_manager_observer.h"
#include "components/autofill/core/browser/data_manager/personal_data_manager_test_utils.h"
#include "components/autofill/core/browser/data_model/addresses/autofill_i18n_api.h"
#include "components/autofill/core/browser/data_model/addresses/autofill_profile.h"
#include "components/autofill/core/browser/data_model/payments/credit_card.h"
#include "components/autofill/core/browser/foundations/autofill_manager.h"
#include "components/autofill/core/browser/foundations/browser_autofill_manager.h"
#include "components/autofill/core/browser/foundations/browser_autofill_manager_test_api.h"
#include "components/autofill/core/browser/foundations/test_autofill_manager_waiter.h"
#include "components/autofill/core/browser/ui/autofill_external_delegate.h"
#include "components/autofill/core/browser/ui/test_autofill_external_delegate.h"
#include "components/autofill/core/common/autofill_test_utils.h"
#include "components/autofill/core/common/form_data_test_api.h"
#include "components/autofill/core/common/form_field_data.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace autofill {

using ::testing::AssertionResult;

static PersonalDataManager* GetPersonalDataManager(Profile* profile) {
  return PersonalDataManagerFactory::GetForBrowserContext(profile);
}

void AddTestProfile(Profile* base_profile, const AutofillProfile& profile) {
  PersonalDataManager* pdm = GetPersonalDataManager(base_profile);
  PersonalDataChangedWaiter waiter(*pdm);
  pdm->address_data_manager().AddProfile(profile);
  std::move(waiter).Wait();
}

void AddTestCreditCard(Profile* base_profile, const CreditCard& card) {
  PersonalDataManager* pdm = GetPersonalDataManager(base_profile);
  PersonalDataChangedWaiter waiter(*pdm);
  pdm->payments_data_manager().AddCreditCard(card);
  std::move(waiter).Wait();
}

void AddTestServerCreditCard(Profile* base_profile, const CreditCard& card) {
  PersonalDataManager* pdm = GetPersonalDataManager(base_profile);
  PersonalDataChangedWaiter waiter(*pdm);
  test_api(pdm->payments_data_manager()).AddServerCreditCard(card);
  std::move(waiter).Wait();
}

void AddTestAutofillData(Profile* base_profile,
                         const AutofillProfile& profile,
                         const CreditCard& card) {
  AddTestProfile(base_profile, profile);
  AddTestCreditCard(base_profile, card);
}

void WaitForPersonalDataChange(Profile* base_profile) {
  PersonalDataChangedWaiter(*GetPersonalDataManager(base_profile)).Wait();
}

void WaitForPersonalDataManagerToBeLoaded(Profile* base_profile) {
  PersonalDataManager* pdm =
      PersonalDataManagerFactory::GetForBrowserContext(base_profile);
  while (!pdm->IsDataLoaded())
    WaitForPersonalDataChange(base_profile);
}

[[nodiscard]] AssertionResult GenerateTestAutofillPopup(
    ContentAutofillDriver& driver,
    Profile* profile,
    bool expect_popup_to_be_shown,
    gfx::RectF element_bounds) {
  ChromeAutofillClient& client =
      static_cast<ChromeAutofillClient&>(driver.GetAutofillClient());
  // It can happen that the window is resized immediately after showing the
  // popup, resulting in the popup to be hidden. If `expect_popup_to_be_shown`
  // is true, the tests assume that the popup will be shown by the end of this
  // function. Not keeping the popup open for testing can result in the popup
  // being randomly hidden and in breaking this assumption. This causes
  // flakiness.
  client.SetKeepPopupOpenForTesting(true);

  FormFieldData field = test::CreateTestFormField(
      "Full name", "name", "", FormControlType::kInputText, "name");
  field.set_is_focusable(true);
  field.set_should_autocomplete(true);
  field.set_bounds(element_bounds);
  FormData form;
  form.set_url(GURL("https://foo.com/bar"));
  form.set_fields({field});

  // Not adding a profile would result in `AskForValuesToFill()` not finding any
  // suggestions and hiding the Autofill Popup.
  // Note: The popup is only shown later in this function. But, without an
  // Autofill Profile, a sequence of nested asynchronous tasks posted on both
  // database and UI threads would result (sometimes) in `AskForValuesToFill()`
  // triggering the hiding of the Autofill Popup when
  // `base::RunLoop().RunUntilIdle()` is called at the end of this function.
  AutofillProfile autofill_profile(
      i18n_model_definition::kLegacyHierarchyCountryCode);
  autofill_profile.SetRawInfo(NAME_FULL, u"John Doe");
  AddTestProfile(profile, autofill_profile);

  TestAutofillManagerSingleEventWaiter wait_for_ask_for_values_to_fill(
      driver.GetAutofillManager(),
      &AutofillManager::Observer::OnAfterAskForValuesToFill);
  gfx::PointF p = element_bounds.origin();
  driver.renderer_events().AskForValuesToFill(
      form, form.fields().front().renderer_id(),
      /*caret_bounds=*/gfx::Rect(gfx::Point(p.x(), p.y()), gfx::Size(0, 10)),
      AutofillSuggestionTriggerSource::kFormControlElementClicked,
      /*password_request=*/std::nullopt);
  if (AssertionResult a = std::move(wait_for_ask_for_values_to_fill).Wait();
      !a) {
    return a << " " << __func__ << "(): "
             << "TestAutofillManagerSingleEventWaiter assertion failed";
  }
  if (driver.GetAutofillManager().form_structures().size() != 1u) {
    return testing::AssertionFailure()
           << " " << __func__
           << "(): driver.GetAutofillManager().form_structures().size() != 1u";
  }

  // `form.host_frame` and `form.url` have only been set by
  // ContentAutofillDriver::AskForValuesToFill().
  form = driver.GetAutofillManager()
             .form_structures()
             .begin()
             ->second->ToFormData();

  std::vector<Suggestion> suggestions = {Suggestion(u"John Doe")};
  TestAutofillExternalDelegate* delegate =
      static_cast<TestAutofillExternalDelegate*>(
          test_api(
              static_cast<BrowserAutofillManager&>(driver.GetAutofillManager()))
              .external_delegate());

  // Showing the Autofill Popup is an asynchronous task.
  if (expect_popup_to_be_shown) {
    // `base::RunLoop().RunUntilIdle()` can cause flakiness when waiting for the
    // popup to be shown.
    if (!base::test::RunUntil([&] { return !delegate->popup_hidden(); })) {
      return testing::AssertionFailure()
             << " " << __func__ << "(): Showing the autofill popup timed out.";
    }
  } else {
    // `base::test::RunUntil()` cannot be used to wait for something not to
    // happen (i.e. for the popup not to be shown).
    base::RunLoop().RunUntilIdle();
    if (!delegate->popup_hidden()) {
      return testing::AssertionFailure()
             << " " << __func__
             << "(): Expected the autofill popup to be hidden, but it is not.";
    }
  }

  // Allow the popup to be hidden. Tests sometimes use this function to create a
  // popup, and then the tests try to hide it.
  client.SetKeepPopupOpenForTesting(false);
  return testing::AssertionSuccess();
}

}  // namespace autofill