Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: ios/chrome/browser/autofill/autofill_controller_unittest.mm

Issue 2580363002: Upstream Chrome on iOS source code [1/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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 #import "ios/chrome/browser/autofill/autofill_controller.h"
6
7 #include <memory>
8 #include <vector>
9
10 #include "base/guid.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/test/histogram_tester.h"
14 #import "base/test/ios/wait_util.h"
15 #include "components/autofill/core/browser/autofill_manager.h"
16 #include "components/autofill/core/browser/autofill_metrics.h"
17 #include "components/autofill/core/browser/personal_data_manager.h"
18 #include "components/autofill/ios/browser/autofill_driver_ios.h"
19 #import "components/autofill/ios/browser/form_suggestion.h"
20 #include "components/infobars/core/confirm_infobar_delegate.h"
21 #include "components/infobars/core/infobar.h"
22 #include "components/infobars/core/infobar_manager.h"
23 #include "components/keyed_service/core/service_access_type.h"
24 #import "ios/chrome/browser/autofill/autofill_agent.h"
25 #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h"
26 #import "ios/chrome/browser/autofill/form_suggestion_controller.h"
27 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
28 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
29 #import "ios/chrome/browser/ui/autofill/autofill_client_ios.h"
30 #import "ios/chrome/browser/web/chrome_web_test.h"
31 #include "ios/chrome/browser/web_data_service_factory.h"
32 #import "ios/web/public/web_state/web_state.h"
33 #import "testing/gtest_mac.h"
34 #include "ui/base/test/ios/ui_view_test_utils.h"
35
36 #if !defined(__has_feature) || !__has_feature(objc_arc)
37 #error "This file requires ARC support."
38 #endif
39
40 // Real FormSuggestionController is wrapped to register the addition of
41 // suggestions.
42 @interface TestSuggestionController : FormSuggestionController
43
44 @property(nonatomic, copy) NSArray* suggestions;
45 @property(nonatomic, assign) BOOL suggestionRetrievalComplete;
46
47 @end
48
49 @implementation TestSuggestionController
50
51 @synthesize suggestions = _suggestions;
52 @synthesize suggestionRetrievalComplete = _suggestionRetrievalComplete;
53
54 - (void)retrieveSuggestionsForFormNamed:(const std::string&)formName
55 fieldName:(const std::string&)fieldName
56 type:(const std::string&)type
57 webState:(web::WebState*)webState {
58 self.suggestionRetrievalComplete = NO;
59 [super retrieveSuggestionsForFormNamed:formName
60 fieldName:fieldName
61 type:type
62 webState:webState];
63 }
64
65 - (void)updateKeyboardWithSuggestions:(NSArray*)suggestions {
66 self.suggestions = suggestions;
67 self.suggestionRetrievalComplete = YES;
68 }
69
70 - (void)onNoSuggestionsAvailable {
71 self.suggestionRetrievalComplete = YES;
72 };
73
74 @end
75
76 namespace autofill {
77
78 namespace {
79
80 // The profile-type form used by tests.
81 NSString* const kProfileFormHtml =
82 @"<form action='/submit' method='post'>"
83 "Name <input type='text' name='name'>"
84 "Address <input type='text' name='address'>"
85 "City <input type='text' name='city'>"
86 "State <input type='text' name='state'>"
87 "Zip <input type='text' name='zip'>"
88 "<input type='submit' id='submit' value='Submit'>"
89 "</form>";
90
91 // A minimal form with a name.
92 NSString* const kMinimalFormWithNameHtml = @"<form id='form1'>"
93 "<input name='name'>"
94 "<input name='address'>"
95 "<input name='city'>"
96 "</form>";
97
98 // The key/value-type form used by tests.
99 NSString* const kKeyValueFormHtml =
100 @"<form action='/submit' method='post'>"
101 "Greeting <input type='text' name='greeting'>"
102 "Dummy field <input type='text' name='dummy'>"
103 "<input type='submit' id='submit' value='Submit'>"
104 "</form>";
105
106 // The credit card-type form used by tests.
107 NSString* const kCreditCardFormHtml =
108 @"<form action='/submit' method='post'>"
109 "Name on card: <input type='text' name='name'>"
110 "Credit card number: <input type='text' name='CCNo'>"
111 "Expiry Month: <input type='text' name='CCExpiresMonth'>"
112 "Expiry Year: <input type='text' name='CCExpiresYear'>"
113 "<input type='submit' id='submit' value='Submit'>"
114 "</form>";
115
116 // Experiment preference key.
117 NSString* const kAutofillVisible = @"AutofillVisible";
118
119 // FAIL if a field with the supplied |name| and |fieldType| is not present on
120 // the |form|.
121 void CheckField(const FormStructure& form,
122 ServerFieldType fieldType,
123 const char* name) {
124 for (const AutofillField* field : form) {
125 if (field->heuristic_type() == fieldType) {
126 EXPECT_EQ(base::UTF8ToUTF16(name), field->unique_name());
127 return;
128 }
129 }
130 FAIL() << "Missing field " << name;
131 }
132
133 // WebDataServiceConsumer for receving vectors of strings and making them
134 // available to tests.
135 class TestConsumer : public WebDataServiceConsumer {
136 public:
137 void OnWebDataServiceRequestDone(
138 WebDataServiceBase::Handle handle,
139 std::unique_ptr<WDTypedResult> result) override {
140 DCHECK_EQ(result->GetType(), AUTOFILL_VALUE_RESULT);
141 result_ = static_cast<WDResult<std::vector<base::string16>>*>(result.get())
142 ->GetValue();
143 }
144 std::vector<base::string16> result_;
145 };
146
147 // Text fixture to test autofill.
148 class AutofillControllerTest : public ChromeWebTest {
149 public:
150 AutofillControllerTest() = default;
151 ~AutofillControllerTest() override {}
152
153 protected:
154 void SetUp() override;
155 void TearDown() override;
156 void SetUpForSuggestions(NSString* data);
157
158 // Adds key value data to the Personal Data Manager.
159 void SetUpKeyValueData();
160
161 // Blocks until suggestion retrieval has completed.
162 void WaitForSuggestionRetrieval();
163
164 // Fails if the specified metric was not registered the given number of times.
165 void ExpectMetric(const std::string& histogram_name, int sum);
166
167 // Fails if the specified user happiness metric was not registered.
168 void ExpectHappinessMetric(AutofillMetrics::UserHappinessMetric metric);
169
170 TestSuggestionController* suggestion_controller() {
171 return suggestion_controller_;
172 }
173
174 private:
175 // Weak pointer to AutofillAgent, owned by the AutofillController.
176 __weak AutofillAgent* autofill_agent_;
177
178 // Histogram tester for these tests.
179 std::unique_ptr<base::HistogramTester> histogram_tester_;
180
181 // Retrieves suggestions according to form events.
182 TestSuggestionController* suggestion_controller_;
183
184 // Retrieves accessory views according to form events.
185 FormInputAccessoryViewController* accessory_controller_;
186
187 // Manages autofill for a single page.
188 AutofillController* autofill_controller_;
189
190 DISALLOW_COPY_AND_ASSIGN(AutofillControllerTest);
191 };
192
193 void AutofillControllerTest::SetUp() {
194 ChromeWebTest::SetUp();
195
196 // Profile import requires a PersonalDataManager which itself needs the
197 // WebDataService; this is not initialized on a TestChromeBrowserState by
198 // default.
199 chrome_browser_state_->CreateWebDataService();
200 // Enable autofill experiment.
201 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
202 [defaults setBool:YES forKey:kAutofillVisible];
203
204 AutofillAgent* agent =
205 [[AutofillAgent alloc] initWithBrowserState:chrome_browser_state_.get()
206 webState:web_state()];
207 autofill_agent_ = agent;
208 InfoBarManagerImpl::CreateForWebState(web_state());
209 autofill_controller_ = [[AutofillController alloc]
210 initWithBrowserState:chrome_browser_state_.get()
211 webState:web_state()
212 autofillAgent:autofill_agent_
213 passwordGenerationManager:nullptr
214 downloadEnabled:NO];
215 suggestion_controller_ = [[TestSuggestionController alloc]
216 initWithWebState:web_state()
217 providers:@[ [autofill_controller_ suggestionProvider] ]];
218 accessory_controller_ = [[FormInputAccessoryViewController alloc]
219 initWithWebState:web_state()
220 providers:@[ [suggestion_controller_ accessoryViewProvider] ]];
221 histogram_tester_.reset(new base::HistogramTester());
222 }
223
224 void AutofillControllerTest::TearDown() {
225 [autofill_controller_ detachFromWebState];
226 [suggestion_controller_ detachFromWebState];
227
228 ChromeWebTest::TearDown();
229 }
230
231 void AutofillControllerTest::WaitForSuggestionRetrieval() {
232 // Wait for the message queue to ensure that JS events fired in the tests
233 // trigger TestSuggestionController's retrieveSuggestionsForFormNamed: method
234 // and set suggestionRetrievalComplete to NO.
235 WaitForBackgroundTasks();
236
237 // Now we can wait for suggestionRetrievalComplete to be set to YES.
238 WaitForCondition(^bool {
239 return [suggestion_controller() suggestionRetrievalComplete];
240 });
241 }
242
243 void AutofillControllerTest::ExpectMetric(const std::string& histogram_name,
244 int sum) {
245 histogram_tester_->ExpectBucketCount(histogram_name, sum, 1);
246 }
247
248 void AutofillControllerTest::ExpectHappinessMetric(
249 AutofillMetrics::UserHappinessMetric metric) {
250 histogram_tester_->ExpectBucketCount("Autofill.UserHappiness", metric, 1);
251 }
252
253 // Checks that viewing an HTML page containing a form results in the form being
254 // registered as a FormStructure by the AutofillManager.
255 TEST_F(AutofillControllerTest, ReadForm) {
256 AutofillManager* autofill_manager =
257 AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
258 EXPECT_TRUE(autofill_manager->GetFormStructures().empty())
259 << "Forms are registered at beginning";
260 LoadHtml(kProfileFormHtml);
261 const std::vector<std::unique_ptr<FormStructure>>& forms =
262 autofill_manager->GetFormStructures();
263 ASSERT_EQ(1U, forms.size());
264 CheckField(*forms[0], NAME_FULL, "name_1");
265 CheckField(*forms[0], ADDRESS_HOME_LINE1, "address_1");
266 CheckField(*forms[0], ADDRESS_HOME_CITY, "city_1");
267 CheckField(*forms[0], ADDRESS_HOME_STATE, "state_1");
268 CheckField(*forms[0], ADDRESS_HOME_ZIP, "zip_1");
269 ExpectMetric("Autofill.IsEnabled.PageLoad", 1);
270 ExpectHappinessMetric(AutofillMetrics::FORMS_LOADED);
271 };
272
273 // Checks that viewing an HTML page containing a form with an 'id' results in
274 // the form being registered as a FormStructure by the AutofillManager, and the
275 // name is correctly set.
276 TEST_F(AutofillControllerTest, ReadFormName) {
277 AutofillManager* autofill_manager =
278 AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
279 LoadHtml(kMinimalFormWithNameHtml);
280 const std::vector<std::unique_ptr<FormStructure>>& forms =
281 autofill_manager->GetFormStructures();
282 ASSERT_EQ(1U, forms.size());
283 EXPECT_EQ(base::UTF8ToUTF16("form1"), forms[0]->ToFormData().name);
284 };
285
286 // Checks that an HTML page containing a profile-type form which is submitted
287 // with scripts (simulating user form submission) results in a profile being
288 // successfully imported into the PersonalDataManager.
289 TEST_F(AutofillControllerTest, ProfileImport) {
290 AutofillManager* autofill_manager =
291 AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
292 PersonalDataManager* personal_data_manager =
293 autofill_manager->client()->GetPersonalDataManager();
294 // Check there are no registered profiles already.
295 EXPECT_EQ(0U, personal_data_manager->GetProfiles().size());
296 LoadHtml(kProfileFormHtml);
297 ExecuteJavaScript(@"document.forms[0].name.value = 'Homer Simpson'");
298 ExecuteJavaScript(@"document.forms[0].address.value = '123 Main Street'");
299 ExecuteJavaScript(@"document.forms[0].city.value = 'Springfield'");
300 ExecuteJavaScript(@"document.forms[0].state.value = 'IL'");
301 ExecuteJavaScript(@"document.forms[0].zip.value = '55123'");
302 ExecuteJavaScript(@"submit.click()");
303 WaitForCondition(^bool {
304 return personal_data_manager->GetProfiles().size();
305 });
306 const std::vector<AutofillProfile*>& profiles =
307 personal_data_manager->GetProfiles();
308 if (profiles.size() != 1)
309 FAIL() << "Not exactly one profile found after attempted import";
310 const AutofillProfile& profile = *profiles[0];
311 EXPECT_EQ(base::UTF8ToUTF16("Homer Simpson"),
312 profile.GetInfo(AutofillType(NAME_FULL), "en-US"));
313 EXPECT_EQ(base::UTF8ToUTF16("123 Main Street"),
314 profile.GetInfo(AutofillType(ADDRESS_HOME_LINE1), "en-US"));
315 EXPECT_EQ(base::UTF8ToUTF16("Springfield"),
316 profile.GetInfo(AutofillType(ADDRESS_HOME_CITY), "en-US"));
317 EXPECT_EQ(base::UTF8ToUTF16("IL"),
318 profile.GetInfo(AutofillType(ADDRESS_HOME_STATE), "en-US"));
319 EXPECT_EQ(base::UTF8ToUTF16("55123"),
320 profile.GetInfo(AutofillType(ADDRESS_HOME_ZIP), "en-US"));
321 };
322
323 void AutofillControllerTest::SetUpForSuggestions(NSString* data) {
324 AutofillManager* autofill_manager =
325 AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
326 PersonalDataManager* personal_data_manager =
327 autofill_manager->client()->GetPersonalDataManager();
328 AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/");
329 profile.SetRawInfo(NAME_FULL, base::UTF8ToUTF16("Homer Simpson"));
330 profile.SetRawInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("123 Main Street"));
331 profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Springfield"));
332 profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("IL"));
333 profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("55123"));
334 EXPECT_EQ(0U, personal_data_manager->GetProfiles().size());
335 personal_data_manager->SaveImportedProfile(profile);
336 EXPECT_EQ(1U, personal_data_manager->GetProfiles().size());
337 LoadHtml(data);
338 }
339
340 // Checks that focusing on a text element of a profile-type form will result in
341 // suggestions being sent to the AutofillAgent, once data has been loaded into a
342 // test data manager.
343 TEST_F(AutofillControllerTest, ProfileSuggestions) {
344 SetUpForSuggestions(kProfileFormHtml);
345 WaitForBackgroundTasks();
346 ui::test::uiview_utils::ForceViewRendering(web_state()->GetView());
347 ExecuteJavaScript(@"document.forms[0].name.focus()");
348 WaitForSuggestionRetrieval();
349 ExpectMetric("Autofill.AddressSuggestionsCount", 1);
350 ExpectHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);
351 EXPECT_EQ(1U, [suggestion_controller() suggestions].count);
352 FormSuggestion* suggestion = [suggestion_controller() suggestions][0];
353 EXPECT_NSEQ(@"Homer Simpson", suggestion.value);
354 };
355
356 // Tests that the system is able to offer suggestions for an anonymous form when
357 // there is another anonymous form on the page.
358 TEST_F(AutofillControllerTest, ProfileSuggestionsTwoAnonymousForms) {
359 SetUpForSuggestions(
360 [NSString stringWithFormat:@"%@%@", kProfileFormHtml, kProfileFormHtml]);
361 WaitForBackgroundTasks();
362 ui::test::uiview_utils::ForceViewRendering(web_state()->GetView());
363 ExecuteJavaScript(@"document.forms[0].name.focus()");
364 WaitForSuggestionRetrieval();
365 ExpectMetric("Autofill.AddressSuggestionsCount", 1);
366 ExpectHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);
367 EXPECT_EQ(1U, [suggestion_controller() suggestions].count);
368 FormSuggestion* suggestion = [suggestion_controller() suggestions][0];
369 EXPECT_NSEQ(@"Homer Simpson", suggestion.value);
370 };
371
372 // Checks that focusing on a select element in a profile-type form will result
373 // in suggestions being sent to the AutofillAgent, once data has been loaded
374 // into a test data manager.
375 TEST_F(AutofillControllerTest, ProfileSuggestionsFromSelectField) {
376 SetUpForSuggestions(kProfileFormHtml);
377 WaitForBackgroundTasks();
378 ui::test::uiview_utils::ForceViewRendering(web_state()->GetView());
379 ExecuteJavaScript(@"document.forms[0].state.focus()");
380 WaitForSuggestionRetrieval();
381 ExpectMetric("Autofill.AddressSuggestionsCount", 1);
382 ExpectHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);
383 EXPECT_EQ(1U, [suggestion_controller() suggestions].count);
384 FormSuggestion* suggestion = [suggestion_controller() suggestions][0];
385 EXPECT_NSEQ(@"IL", suggestion.value);
386 };
387
388 // Checks that multiple profiles will offer a matching number of suggestions.
389 TEST_F(AutofillControllerTest, MultipleProfileSuggestions) {
390 AutofillManager* autofill_manager =
391 AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
392 PersonalDataManager* personal_data_manager =
393 autofill_manager->client()->GetPersonalDataManager();
394 AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/");
395 profile.SetRawInfo(NAME_FULL, base::UTF8ToUTF16("Homer Simpson"));
396 profile.SetRawInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("123 Main Street"));
397 profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Springfield"));
398 profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("IL"));
399 profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("55123"));
400 EXPECT_EQ(0U, personal_data_manager->GetProfiles().size());
401 personal_data_manager->SaveImportedProfile(profile);
402 EXPECT_EQ(1U, personal_data_manager->GetProfiles().size());
403 AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com/");
404 profile2.SetRawInfo(NAME_FULL, base::UTF8ToUTF16("Larry Page"));
405 profile2.SetRawInfo(ADDRESS_HOME_LINE1,
406 base::UTF8ToUTF16("1600 Amphitheatre Parkway"));
407 profile2.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Mountain View"));
408 profile2.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("CA"));
409 profile2.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("94043"));
410 personal_data_manager->SaveImportedProfile(profile2);
411 EXPECT_EQ(2U, personal_data_manager->GetProfiles().size());
412 LoadHtml(kProfileFormHtml);
413 WaitForBackgroundTasks();
414 ui::test::uiview_utils::ForceViewRendering(web_state()->GetView());
415 ExecuteJavaScript(@"document.forms[0].name.focus()");
416 WaitForSuggestionRetrieval();
417 ExpectMetric("Autofill.AddressSuggestionsCount", 2);
418 ExpectHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);
419 EXPECT_EQ(2U, [suggestion_controller() suggestions].count);
420 }
421
422 // Check that an HTML page containing a key/value type form which is submitted
423 // with scripts (simulating user form submission) results in data being
424 // successfully registered.
425 TEST_F(AutofillControllerTest, KeyValueImport) {
426 LoadHtml(kKeyValueFormHtml);
427 ExecuteJavaScript(@"document.forms[0].greeting.value = 'Hello'");
428 scoped_refptr<AutofillWebDataService> web_data_service =
429 ios::WebDataServiceFactory::GetAutofillWebDataForBrowserState(
430 chrome_browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS);
431 __block TestConsumer consumer;
432 const int limit = 1;
433 web_data_service->GetFormValuesForElementName(
434 base::UTF8ToUTF16("greeting"), base::string16(), limit, &consumer);
435 WaitForBackgroundTasks();
436 // No value should be returned before anything is loaded via form submission.
437 ASSERT_EQ(0U, consumer.result_.size());
438 ExecuteJavaScript(@"submit.click()");
439 WaitForCondition(^bool {
440 web_data_service->GetFormValuesForElementName(
441 base::UTF8ToUTF16("greeting"), base::string16(), limit, &consumer);
442 return consumer.result_.size();
443 });
444 WaitForBackgroundTasks();
445 // One result should be returned, matching the filled value.
446 ASSERT_EQ(1U, consumer.result_.size());
447 EXPECT_EQ(base::UTF8ToUTF16("Hello"), consumer.result_[0]);
448 };
449
450 void AutofillControllerTest::SetUpKeyValueData() {
451 scoped_refptr<AutofillWebDataService> web_data_service =
452 ios::WebDataServiceFactory::GetAutofillWebDataForBrowserState(
453 chrome_browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS);
454 // Load value into database.
455 std::vector<FormFieldData> values;
456 FormFieldData fieldData;
457 fieldData.name = base::UTF8ToUTF16("greeting");
458 fieldData.value = base::UTF8ToUTF16("Bonjour");
459 values.push_back(fieldData);
460 web_data_service->AddFormFields(values);
461 }
462
463 // Checks that focusing on an element of a key/value type form then typing the
464 // first letter of a suggestion will result in suggestions being sent to the
465 // AutofillAgent, once data has been loaded into a test data manager.
466 TEST_F(AutofillControllerTest, KeyValueSuggestions) {
467 SetUpKeyValueData();
468 // Load test page and focus element.
469 LoadHtml(kKeyValueFormHtml);
470 WaitForBackgroundTasks();
471 ExecuteJavaScript(@"document.forms[0].greeting.value='B'");
472 ExecuteJavaScript(@"document.forms[0].greeting.focus()");
473 WaitForSuggestionRetrieval();
474 EXPECT_EQ(1U, [suggestion_controller() suggestions].count);
475 FormSuggestion* suggestion = [suggestion_controller() suggestions][0];
476 EXPECT_NSEQ(@"Bonjour", suggestion.value);
477 };
478
479 // Checks that typing events (simulated in script) result in suggestions. Note
480 // that the field is not explictly focused before typing starts; this can happen
481 // in practice and should not result in a crash or incorrect behavior.
482 TEST_F(AutofillControllerTest, KeyValueTypedSuggestions) {
483 SetUpKeyValueData();
484 LoadHtml(kKeyValueFormHtml);
485 WaitForBackgroundTasks();
486 ExecuteJavaScript(@"document.forms[0].greeting.select()");
487 ExecuteJavaScript(@"event = document.createEvent('TextEvent');");
488 ExecuteJavaScript(
489 @"event.initTextEvent('textInput', true, true, window, 'B');");
490 ExecuteJavaScript(@"document.forms[0].greeting.dispatchEvent(event);");
491 WaitForSuggestionRetrieval();
492 EXPECT_EQ(1U, [suggestion_controller() suggestions].count);
493 FormSuggestion* suggestion = [suggestion_controller() suggestions][0];
494 EXPECT_NSEQ(@"Bonjour", suggestion.value);
495 }
496
497 // Checks that focusing on and typing on one field, then changing focus before
498 // typing again, result in suggestions.
499 TEST_F(AutofillControllerTest, KeyValueFocusChange) {
500 SetUpKeyValueData();
501 LoadHtml(kKeyValueFormHtml);
502
503 // Focus the dummy field and confirm no suggestions are presented.
504 ExecuteJavaScript(@"document.forms[0].dummy.focus()");
505 WaitForSuggestionRetrieval();
506 EXPECT_EQ(0U, [suggestion_controller() suggestions].count);
507
508 // Enter 'B' in the dummy field and confirm no suggestions are presented.
509 ExecuteJavaScript(@"event = document.createEvent('TextEvent');");
510 ExecuteJavaScript(
511 @"event.initTextEvent('textInput', true, true, window, 'B');");
512 ExecuteJavaScript(@"document.forms[0].dummy.dispatchEvent(event);");
513 WaitForSuggestionRetrieval();
514 EXPECT_EQ(0U, [suggestion_controller() suggestions].count);
515
516 // Enter 'B' in the greeting field and confirm that one suggestion ("Bonjour")
517 // is presented.
518 ExecuteJavaScript(@"document.forms[0].greeting.select()");
519 ExecuteJavaScript(@"event = document.createEvent('TextEvent');");
520 ExecuteJavaScript(
521 @"event.initTextEvent('textInput', true, true, window, 'B');");
522 ExecuteJavaScript(@"document.forms[0].greeting.dispatchEvent(event);");
523 WaitForSuggestionRetrieval();
524 EXPECT_EQ(1U, [suggestion_controller() suggestions].count);
525 FormSuggestion* suggestion = [suggestion_controller() suggestions][0];
526 EXPECT_NSEQ(@"Bonjour", suggestion.value);
527 }
528
529 // Checks that focusing on an element of a key/value type form without typing
530 // won't result in suggestions being sent to the AutofillAgent, once data has
531 // been loaded into a test data manager.
532 TEST_F(AutofillControllerTest, NoKeyValueSuggestionsWithoutTyping) {
533 SetUpKeyValueData();
534 // Load test page and focus element.
535 LoadHtml(kKeyValueFormHtml);
536 ExecuteJavaScript(@"document.forms[0].greeting.focus()");
537 WaitForSuggestionRetrieval();
538 EXPECT_EQ(0U, [suggestion_controller() suggestions].count);
539 }
540
541 // Checks that an HTML page containing a credit card-type form which is
542 // submitted with scripts (simulating user form submission) results in a credit
543 // card being successfully imported into the PersonalDataManager.
544 TEST_F(AutofillControllerTest, CreditCardImport) {
545 InfoBarManagerImpl::CreateForWebState(web_state());
546 AutofillManager* autofill_manager =
547 AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
548 PersonalDataManager* personal_data_manager =
549 autofill_manager->client()->GetPersonalDataManager();
550 // Check there are no registered profiles already.
551 EXPECT_EQ(0U, personal_data_manager->GetCreditCards().size());
552 LoadHtml(kCreditCardFormHtml);
553 ExecuteJavaScript(@"document.forms[0].name.value = 'Superman'");
554 ExecuteJavaScript(@"document.forms[0].CCNo.value = '4000-4444-4444-4444'");
555 ExecuteJavaScript(@"document.forms[0].CCExpiresMonth.value = '11'");
556 ExecuteJavaScript(@"document.forms[0].CCExpiresYear.value = '2999'");
557 ExecuteJavaScript(@"submit.click()");
558 infobars::InfoBarManager* infobar_manager =
559 InfoBarManagerImpl::FromWebState(web_state());
560 base::test::ios::WaitUntilCondition(^bool() {
561 return infobar_manager->infobar_count();
562 });
563 ExpectMetric("Autofill.CreditCardInfoBar.Local",
564 AutofillMetrics::INFOBAR_SHOWN);
565 ASSERT_EQ(1U, infobar_manager->infobar_count());
566 infobars::InfoBarDelegate* infobar =
567 infobar_manager->infobar_at(0)->delegate();
568 ConfirmInfoBarDelegate* confirm_infobar = infobar->AsConfirmInfoBarDelegate();
569 confirm_infobar->Accept();
570 const std::vector<CreditCard*>& credit_cards =
571 personal_data_manager->GetCreditCards();
572 ASSERT_EQ(1U, credit_cards.size());
573 const CreditCard& credit_card = *credit_cards[0];
574 EXPECT_EQ(base::UTF8ToUTF16("Superman"),
575 credit_card.GetInfo(AutofillType(CREDIT_CARD_NAME_FULL), "en-US"));
576 EXPECT_EQ(base::UTF8ToUTF16("4000444444444444"),
577 credit_card.GetInfo(AutofillType(CREDIT_CARD_NUMBER), "en-US"));
578 EXPECT_EQ(base::UTF8ToUTF16("11"),
579 credit_card.GetInfo(AutofillType(CREDIT_CARD_EXP_MONTH), "en-US"));
580 EXPECT_EQ(
581 base::UTF8ToUTF16("2999"),
582 credit_card.GetInfo(AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), "en-US"));
583 };
584
585 } // namespace
586
587 } // namespace autofill
OLDNEW
« no previous file with comments | « ios/chrome/browser/autofill/autofill_controller_js_unittest.mm ('k') | ios/chrome/browser/autofill/form_input_egtest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698