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 #include "components/autofill/core/browser/form_parsing/address_field.h"
6
7 #include <memory>
8 #include <vector>
9
10 #include "base/macros.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "components/autofill/core/browser/autofill_field.h"
16 #include "components/autofill/core/browser/form_parsing/autofill_scanner.h"
17 #include "components/autofill/core/browser/pattern_provider/test_pattern_provider.h"
18 #include "components/autofill/core/common/autofill_features.h"
19 #include "components/autofill/core/common/form_field_data.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using base::ASCIIToUTF16;
23
24 namespace autofill {
25
26 class AddressFieldTest : public testing::Test {
27 public:
28 AddressFieldTest() = default;
29 AddressFieldTest(const AddressFieldTest&) = delete;
30 AddressFieldTest& operator=(const AddressFieldTest&) = delete;
31
32 protected:
33 // Downcast for tests.
Parse(AutofillScanner * scanner)34 static std::unique_ptr<AddressField> Parse(AutofillScanner* scanner) {
35 // An empty page_language means the language is unknown and patterns of all
36 // languages are used.
37 std::unique_ptr<FormField> field =
38 AddressField::Parse(scanner, /*page_language=*/"", nullptr);
39 return std::unique_ptr<AddressField>(
40 static_cast<AddressField*>(field.release()));
41 }
42
43 std::vector<std::unique_ptr<AutofillField>> list_;
44 std::unique_ptr<AddressField> field_;
45 FieldCandidatesMap field_candidates_map_;
46
47 // RAII object to mock the the PatternProvider.
48 TestPatternProvider test_pattern_provider_;
49 };
50
TEST_F(AddressFieldTest,Empty)51 TEST_F(AddressFieldTest, Empty) {
52 AutofillScanner scanner(list_);
53 field_ = Parse(&scanner);
54 ASSERT_EQ(nullptr, field_.get());
55 }
56
TEST_F(AddressFieldTest,NonParse)57 TEST_F(AddressFieldTest, NonParse) {
58 list_.push_back(std::make_unique<AutofillField>());
59 AutofillScanner scanner(list_);
60 field_ = Parse(&scanner);
61 ASSERT_EQ(nullptr, field_.get());
62 }
63
TEST_F(AddressFieldTest,ParseOneLineAddress)64 TEST_F(AddressFieldTest, ParseOneLineAddress) {
65 FormFieldData field;
66 field.form_control_type = "text";
67
68 field.label = ASCIIToUTF16("Address");
69 field.name = ASCIIToUTF16("address");
70 list_.push_back(
71 std::make_unique<AutofillField>(field, ASCIIToUTF16("addr1")));
72
73 AutofillScanner scanner(list_);
74 field_ = Parse(&scanner);
75 ASSERT_NE(nullptr, field_.get());
76 field_->AddClassificationsForTesting(&field_candidates_map_);
77 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr1")) !=
78 field_candidates_map_.end());
79 EXPECT_EQ(ADDRESS_HOME_LINE1,
80 field_candidates_map_[ASCIIToUTF16("addr1")].BestHeuristicType());
81 }
82
TEST_F(AddressFieldTest,ParseTwoLineAddress)83 TEST_F(AddressFieldTest, ParseTwoLineAddress) {
84 FormFieldData field;
85 field.form_control_type = "text";
86
87 field.label = ASCIIToUTF16("Address");
88 field.name = ASCIIToUTF16("address");
89 list_.push_back(
90 std::make_unique<AutofillField>(field, ASCIIToUTF16("addr1")));
91
92 field.label = base::string16();
93 field.name = ASCIIToUTF16("address2");
94 list_.push_back(
95 std::make_unique<AutofillField>(field, ASCIIToUTF16("addr2")));
96
97 AutofillScanner scanner(list_);
98 field_ = Parse(&scanner);
99 ASSERT_NE(nullptr, field_.get());
100 field_->AddClassificationsForTesting(&field_candidates_map_);
101 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr1")) !=
102 field_candidates_map_.end());
103 EXPECT_EQ(ADDRESS_HOME_LINE1,
104 field_candidates_map_[ASCIIToUTF16("addr1")].BestHeuristicType());
105 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr2")) !=
106 field_candidates_map_.end());
107 EXPECT_EQ(ADDRESS_HOME_LINE2,
108 field_candidates_map_[ASCIIToUTF16("addr2")].BestHeuristicType());
109 }
110
TEST_F(AddressFieldTest,ParseThreeLineAddress)111 TEST_F(AddressFieldTest, ParseThreeLineAddress) {
112 FormFieldData field;
113 field.form_control_type = "text";
114
115 field.label = ASCIIToUTF16("Address Line1");
116 field.name = ASCIIToUTF16("Address1");
117 list_.push_back(
118 std::make_unique<AutofillField>(field, ASCIIToUTF16("addr1")));
119
120 field.label = ASCIIToUTF16("Address Line2");
121 field.name = ASCIIToUTF16("Address2");
122 list_.push_back(
123 std::make_unique<AutofillField>(field, ASCIIToUTF16("addr2")));
124
125 field.label = ASCIIToUTF16("Address Line3");
126 field.name = ASCIIToUTF16("Address3");
127 list_.push_back(
128 std::make_unique<AutofillField>(field, ASCIIToUTF16("addr3")));
129
130 AutofillScanner scanner(list_);
131 field_ = Parse(&scanner);
132 ASSERT_NE(nullptr, field_.get());
133 field_->AddClassificationsForTesting(&field_candidates_map_);
134 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr1")) !=
135 field_candidates_map_.end());
136 EXPECT_EQ(ADDRESS_HOME_LINE1,
137 field_candidates_map_[ASCIIToUTF16("addr1")].BestHeuristicType());
138 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr2")) !=
139 field_candidates_map_.end());
140 EXPECT_EQ(ADDRESS_HOME_LINE2,
141 field_candidates_map_[ASCIIToUTF16("addr2")].BestHeuristicType());
142 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr3")) !=
143 field_candidates_map_.end());
144 EXPECT_EQ(ADDRESS_HOME_LINE3,
145 field_candidates_map_[ASCIIToUTF16("addr3")].BestHeuristicType());
146 }
147
TEST_F(AddressFieldTest,ParseStreetAddressFromTextArea)148 TEST_F(AddressFieldTest, ParseStreetAddressFromTextArea) {
149 FormFieldData field;
150 field.form_control_type = "textarea";
151
152 field.label = ASCIIToUTF16("Address");
153 field.name = ASCIIToUTF16("address");
154 list_.push_back(std::make_unique<AutofillField>(field, ASCIIToUTF16("addr")));
155
156 AutofillScanner scanner(list_);
157 field_ = Parse(&scanner);
158 ASSERT_NE(nullptr, field_.get());
159 field_->AddClassificationsForTesting(&field_candidates_map_);
160 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("addr")) !=
161 field_candidates_map_.end());
162 EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
163 field_candidates_map_[ASCIIToUTF16("addr")].BestHeuristicType());
164 }
165
166 // Tests that fields are classified as |ADDRESS_HOME_STREET_NAME| and
167 // |ADDRESS_HOME_HOUSE_NUMBER| when they are labeled accordingly and
168 // both are present.
TEST_F(AddressFieldTest,ParseStreetNameAndHouseNumber)169 TEST_F(AddressFieldTest, ParseStreetNameAndHouseNumber) {
170 // TODO(crbug.com/1125978): Remove once launched.
171 base::test::ScopedFeatureList enabled;
172 enabled.InitAndEnableFeature(
173 features::kAutofillEnableSupportForMoreStructureInAddresses);
174
175 FormFieldData field;
176 field.form_control_type = "text";
177
178 field.label = ASCIIToUTF16("Street");
179 field.name = ASCIIToUTF16("street");
180 list_.push_back(
181 std::make_unique<AutofillField>(field, ASCIIToUTF16("street")));
182
183 field.label = ASCIIToUTF16("House number");
184 field.name = ASCIIToUTF16("house-number");
185 list_.push_back(
186 std::make_unique<AutofillField>(field, ASCIIToUTF16("house")));
187
188 AutofillScanner scanner(list_);
189 field_ = Parse(&scanner);
190 ASSERT_NE(nullptr, field_.get());
191 field_->AddClassificationsForTesting(&field_candidates_map_);
192
193 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("street")) !=
194 field_candidates_map_.end());
195 EXPECT_EQ(ADDRESS_HOME_STREET_NAME,
196 field_candidates_map_[ASCIIToUTF16("street")].BestHeuristicType());
197
198 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("house")) !=
199 field_candidates_map_.end());
200 EXPECT_EQ(ADDRESS_HOME_HOUSE_NUMBER,
201 field_candidates_map_[ASCIIToUTF16("house")].BestHeuristicType());
202 }
203
204 // Tests that the field is not classified as |ADDRESS_HOME_STREET_NAME| when
205 // it is labeled accordingly but adjacent field classified as
206 // |ADDRESS_HOME_HOUSE_NUMBER| is absent.
TEST_F(AddressFieldTest,NotParseStreetNameWithoutHouseNumber)207 TEST_F(AddressFieldTest, NotParseStreetNameWithoutHouseNumber) {
208 // TODO(crbug.com/1125978): Remove once launched.
209 base::test::ScopedFeatureList enabled;
210 enabled.InitAndEnableFeature(
211 features::kAutofillEnableSupportForMoreStructureInAddresses);
212
213 FormFieldData field;
214 field.form_control_type = "text";
215
216 field.label = ASCIIToUTF16("Street");
217 field.name = ASCIIToUTF16("street");
218 list_.push_back(
219 std::make_unique<AutofillField>(field, ASCIIToUTF16("street")));
220
221 AutofillScanner scanner(list_);
222 field_ = Parse(&scanner);
223
224 if (!field_.get())
225 return;
226 field_->AddClassificationsForTesting(&field_candidates_map_);
227 if (field_candidates_map_.empty())
228 return;
229
230 EXPECT_NE(ADDRESS_HOME_STREET_NAME,
231 field_candidates_map_[ASCIIToUTF16("street")].BestHeuristicType());
232 }
233
234 // Tests that the field is not classified as |ADDRESS_HOME_HOUSE_NUMBER| when
235 // it is labeled accordingly but adjacent field classified as
236 // |ADDRESS_HOME_STREET_NAME| is absent.
TEST_F(AddressFieldTest,NotParseHouseNumberWithoutStreetName)237 TEST_F(AddressFieldTest, NotParseHouseNumberWithoutStreetName) {
238 // TODO(crbug.com/1125978): Remove once launched.
239 base::test::ScopedFeatureList enabled;
240 enabled.InitAndEnableFeature(
241 features::kAutofillEnableSupportForMoreStructureInAddresses);
242
243 FormFieldData field;
244 field.form_control_type = "text";
245
246 field.label = ASCIIToUTF16("House number");
247 field.name = ASCIIToUTF16("house-number");
248 list_.push_back(
249 std::make_unique<AutofillField>(field, ASCIIToUTF16("house")));
250
251 AutofillScanner scanner(list_);
252 field_ = Parse(&scanner);
253
254 if (!field_.get())
255 return;
256 field_->AddClassificationsForTesting(&field_candidates_map_);
257 if (field_candidates_map_.empty())
258 return;
259
260 EXPECT_NE(ADDRESS_HOME_HOUSE_NUMBER,
261 field_candidates_map_[ASCIIToUTF16("house")].BestHeuristicType());
262 }
263
TEST_F(AddressFieldTest,ParseCity)264 TEST_F(AddressFieldTest, ParseCity) {
265 FormFieldData field;
266 field.form_control_type = "text";
267
268 field.label = ASCIIToUTF16("City");
269 field.name = ASCIIToUTF16("city");
270 list_.push_back(
271 std::make_unique<AutofillField>(field, ASCIIToUTF16("city1")));
272
273 AutofillScanner scanner(list_);
274 field_ = Parse(&scanner);
275 ASSERT_NE(nullptr, field_.get());
276 field_->AddClassificationsForTesting(&field_candidates_map_);
277 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("city1")) !=
278 field_candidates_map_.end());
279 EXPECT_EQ(ADDRESS_HOME_CITY,
280 field_candidates_map_[ASCIIToUTF16("city1")].BestHeuristicType());
281 }
282
TEST_F(AddressFieldTest,ParseState)283 TEST_F(AddressFieldTest, ParseState) {
284 FormFieldData field;
285 field.form_control_type = "text";
286
287 field.label = ASCIIToUTF16("State");
288 field.name = ASCIIToUTF16("state");
289 list_.push_back(
290 std::make_unique<AutofillField>(field, ASCIIToUTF16("state1")));
291
292 AutofillScanner scanner(list_);
293 field_ = Parse(&scanner);
294 ASSERT_NE(nullptr, field_.get());
295 field_->AddClassificationsForTesting(&field_candidates_map_);
296 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("state1")) !=
297 field_candidates_map_.end());
298 EXPECT_EQ(ADDRESS_HOME_STATE,
299 field_candidates_map_[ASCIIToUTF16("state1")].BestHeuristicType());
300 }
301
TEST_F(AddressFieldTest,ParseZip)302 TEST_F(AddressFieldTest, ParseZip) {
303 FormFieldData field;
304 field.form_control_type = "text";
305
306 field.label = ASCIIToUTF16("Zip");
307 field.name = ASCIIToUTF16("zip");
308 list_.push_back(std::make_unique<AutofillField>(field, ASCIIToUTF16("zip1")));
309
310 AutofillScanner scanner(list_);
311 field_ = Parse(&scanner);
312 ASSERT_NE(nullptr, field_.get());
313 field_->AddClassificationsForTesting(&field_candidates_map_);
314 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("zip1")) !=
315 field_candidates_map_.end());
316 EXPECT_EQ(ADDRESS_HOME_ZIP,
317 field_candidates_map_[ASCIIToUTF16("zip1")].BestHeuristicType());
318 }
319
TEST_F(AddressFieldTest,ParseStateAndZipOneLabel)320 TEST_F(AddressFieldTest, ParseStateAndZipOneLabel) {
321 FormFieldData field;
322 field.form_control_type = "text";
323
324 field.label = ASCIIToUTF16("State/Province, Zip/Postal Code");
325 field.name = ASCIIToUTF16("state");
326 list_.push_back(
327 std::make_unique<AutofillField>(field, ASCIIToUTF16("state")));
328
329 field.label = ASCIIToUTF16("State/Province, Zip/Postal Code");
330 field.name = ASCIIToUTF16("zip");
331 list_.push_back(std::make_unique<AutofillField>(field, ASCIIToUTF16("zip")));
332
333 AutofillScanner scanner(list_);
334 field_ = Parse(&scanner);
335 ASSERT_NE(nullptr, field_.get());
336 field_->AddClassificationsForTesting(&field_candidates_map_);
337 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("state")) !=
338 field_candidates_map_.end());
339 EXPECT_EQ(ADDRESS_HOME_STATE,
340 field_candidates_map_[ASCIIToUTF16("state")].BestHeuristicType());
341 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("zip")) !=
342 field_candidates_map_.end());
343 EXPECT_EQ(ADDRESS_HOME_ZIP,
344 field_candidates_map_[ASCIIToUTF16("zip")].BestHeuristicType());
345 }
346
TEST_F(AddressFieldTest,ParseCountry)347 TEST_F(AddressFieldTest, ParseCountry) {
348 FormFieldData field;
349 field.form_control_type = "text";
350
351 field.label = ASCIIToUTF16("Country");
352 field.name = ASCIIToUTF16("country");
353 list_.push_back(
354 std::make_unique<AutofillField>(field, ASCIIToUTF16("country1")));
355
356 AutofillScanner scanner(list_);
357 field_ = Parse(&scanner);
358 ASSERT_NE(nullptr, field_.get());
359 field_->AddClassificationsForTesting(&field_candidates_map_);
360 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("country1")) !=
361 field_candidates_map_.end());
362 EXPECT_EQ(
363 ADDRESS_HOME_COUNTRY,
364 field_candidates_map_[ASCIIToUTF16("country1")].BestHeuristicType());
365 }
366
TEST_F(AddressFieldTest,ParseCompany)367 TEST_F(AddressFieldTest, ParseCompany) {
368 FormFieldData field;
369 field.form_control_type = "text";
370
371 field.label = ASCIIToUTF16("Company");
372 field.name = ASCIIToUTF16("company");
373 list_.push_back(
374 std::make_unique<AutofillField>(field, ASCIIToUTF16("company1")));
375
376 AutofillScanner scanner(list_);
377 field_ = Parse(&scanner);
378 ASSERT_NE(nullptr, field_.get());
379 field_->AddClassificationsForTesting(&field_candidates_map_);
380 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("company1")) !=
381 field_candidates_map_.end());
382 EXPECT_EQ(
383 COMPANY_NAME,
384 field_candidates_map_[ASCIIToUTF16("company1")].BestHeuristicType());
385 }
386
387 // Tests that the city, state, country and zip-code fields are correctly
388 // classfied with unambiguous field names and labels.
TEST_F(AddressFieldTest,ParseCityStateCountryZipcodeTogether)389 TEST_F(AddressFieldTest, ParseCityStateCountryZipcodeTogether) {
390 FormFieldData field;
391 field.form_control_type = "text";
392
393 field.label = ASCIIToUTF16("City");
394 field.name = ASCIIToUTF16("city");
395 list_.push_back(
396 std::make_unique<AutofillField>(field, ASCIIToUTF16("city1")));
397
398 field.label = ASCIIToUTF16("State");
399 field.name = ASCIIToUTF16("state");
400 list_.push_back(
401 std::make_unique<AutofillField>(field, ASCIIToUTF16("state1")));
402
403 field.label = ASCIIToUTF16("Country");
404 field.name = ASCIIToUTF16("country");
405 list_.push_back(
406 std::make_unique<AutofillField>(field, ASCIIToUTF16("country1")));
407
408 field.label = ASCIIToUTF16("Zip");
409 field.name = ASCIIToUTF16("zip");
410 list_.push_back(std::make_unique<AutofillField>(field, ASCIIToUTF16("zip1")));
411
412 AutofillScanner scanner(list_);
413 field_ = Parse(&scanner);
414 ASSERT_NE(nullptr, field_.get());
415 field_->AddClassificationsForTesting(&field_candidates_map_);
416
417 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("city1")) !=
418 field_candidates_map_.end());
419 EXPECT_EQ(ADDRESS_HOME_CITY,
420 field_candidates_map_[ASCIIToUTF16("city1")].BestHeuristicType());
421
422 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("state1")) !=
423 field_candidates_map_.end());
424 EXPECT_EQ(ADDRESS_HOME_STATE,
425 field_candidates_map_[ASCIIToUTF16("state1")].BestHeuristicType());
426
427 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("country1")) !=
428 field_candidates_map_.end());
429 EXPECT_EQ(
430 ADDRESS_HOME_COUNTRY,
431 field_candidates_map_[ASCIIToUTF16("country1")].BestHeuristicType());
432
433 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("zip1")) !=
434 field_candidates_map_.end());
435 EXPECT_EQ(ADDRESS_HOME_ZIP,
436 field_candidates_map_[ASCIIToUTF16("zip1")].BestHeuristicType());
437 }
438
439 // Tests that the field is classified as |ADDRESS_HOME_COUNTRY| when the field
440 // label contains 'Region'.
TEST_F(AddressFieldTest,ParseCountryLabelRegion)441 TEST_F(AddressFieldTest, ParseCountryLabelRegion) {
442 FormFieldData field;
443 field.form_control_type = "text";
444
445 field.label = ASCIIToUTF16("Country/Region");
446 field.name = ASCIIToUTF16("country");
447 list_.push_back(
448 std::make_unique<AutofillField>(field, ASCIIToUTF16("country1")));
449
450 AutofillScanner scanner(list_);
451 field_ = Parse(&scanner);
452 ASSERT_NE(nullptr, field_.get());
453 field_->AddClassificationsForTesting(&field_candidates_map_);
454
455 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("country1")) !=
456 field_candidates_map_.end());
457 EXPECT_EQ(
458 ADDRESS_HOME_COUNTRY,
459 field_candidates_map_[ASCIIToUTF16("country1")].BestHeuristicType());
460 }
461
462 // Tests that the field is classified as |ADDRESS_HOME_COUNTRY| when the field
463 // name contains 'region'.
TEST_F(AddressFieldTest,ParseCountryNameRegion)464 TEST_F(AddressFieldTest, ParseCountryNameRegion) {
465 FormFieldData field;
466 field.form_control_type = "text";
467
468 field.label = ASCIIToUTF16("Land");
469 field.name = ASCIIToUTF16("client_region");
470 list_.push_back(
471 std::make_unique<AutofillField>(field, ASCIIToUTF16("country1")));
472
473 AutofillScanner scanner(list_);
474 field_ = Parse(&scanner);
475 ASSERT_NE(nullptr, field_.get());
476 field_->AddClassificationsForTesting(&field_candidates_map_);
477
478 ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("country1")) !=
479 field_candidates_map_.end());
480 EXPECT_EQ(
481 ADDRESS_HOME_COUNTRY,
482 field_candidates_map_[ASCIIToUTF16("country1")].BestHeuristicType());
483 }
484
485 } // namespace autofill
486