1// Copyright (C) 2013 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <libaddressinput/localization.h>
16
17#include <libaddressinput/address_data.h>
18#include <libaddressinput/address_field.h>
19#include <libaddressinput/address_problem.h>
20#include <libaddressinput/util/basictypes.h>
21
22#include <string>
23#include <vector>
24
25#include <gtest/gtest.h>
26
27#include "grit.h"
28#include "messages.h"
29
30namespace {
31
32using i18n::addressinput::AddressData;
33using i18n::addressinput::AddressField;
34using i18n::addressinput::INVALID_MESSAGE_ID;
35using i18n::addressinput::Localization;
36
37using i18n::addressinput::COUNTRY;
38using i18n::addressinput::ADMIN_AREA;
39using i18n::addressinput::LOCALITY;
40using i18n::addressinput::DEPENDENT_LOCALITY;
41using i18n::addressinput::SORTING_CODE;
42using i18n::addressinput::POSTAL_CODE;
43using i18n::addressinput::STREET_ADDRESS;
44using i18n::addressinput::ORGANIZATION;
45using i18n::addressinput::RECIPIENT;
46
47using i18n::addressinput::MISSING_REQUIRED_FIELD;
48using i18n::addressinput::UNKNOWN_VALUE;
49using i18n::addressinput::INVALID_FORMAT;
50using i18n::addressinput::MISMATCHING_VALUE;
51using i18n::addressinput::USES_P_O_BOX;
52
53// Tests for Localization object.
54class LocalizationTest : public testing::TestWithParam<int> {
55 protected:
56  LocalizationTest() {}
57  Localization localization_;
58
59 private:
60  DISALLOW_COPY_AND_ASSIGN(LocalizationTest);
61};
62
63// Verifies that a custom message getter can be used.
64static const char kValidMessage[] = "Data";
65std::string GetValidMessage(int message_id) { return kValidMessage; }
66TEST_P(LocalizationTest, ValidStringGetterCanBeUsed) {
67  localization_.SetGetter(&GetValidMessage);
68  EXPECT_EQ(kValidMessage, localization_.GetString(GetParam()));
69}
70
71// Verifies that the default language for messages does not have empty strings.
72TEST_P(LocalizationTest, DefaultStringIsNotEmpty) {
73  EXPECT_FALSE(localization_.GetString(GetParam()).empty());
74}
75
76// Verifies that the messages do not have newlines.
77TEST_P(LocalizationTest, NoNewline) {
78  EXPECT_EQ(std::string::npos, localization_.GetString(GetParam()).find('\n'));
79}
80
81// Verifies that the messages do not have double spaces.
82TEST_P(LocalizationTest, NoDoubleSpace) {
83  EXPECT_EQ(std::string::npos,
84            localization_.GetString(GetParam()).find(std::string(2U, ' ')));
85}
86
87// Tests all message identifiers.
88INSTANTIATE_TEST_CASE_P(
89    AllMessages, LocalizationTest,
90    testing::Values(
91        IDS_LIBADDRESSINPUT_COUNTRY_OR_REGION_LABEL,
92        IDS_LIBADDRESSINPUT_LOCALITY_LABEL,
93        IDS_LIBADDRESSINPUT_ADDRESS_LINE_1_LABEL,
94        IDS_LIBADDRESSINPUT_POSTAL_CODE_LABEL,
95        IDS_LIBADDRESSINPUT_ZIP_CODE_LABEL,
96        IDS_LIBADDRESSINPUT_AREA,
97        IDS_LIBADDRESSINPUT_COUNTY,
98        IDS_LIBADDRESSINPUT_DEPARTMENT,
99        IDS_LIBADDRESSINPUT_DISTRICT,
100        IDS_LIBADDRESSINPUT_DO_SI,
101        IDS_LIBADDRESSINPUT_EMIRATE,
102        IDS_LIBADDRESSINPUT_ISLAND,
103        IDS_LIBADDRESSINPUT_PARISH,
104        IDS_LIBADDRESSINPUT_PREFECTURE,
105        IDS_LIBADDRESSINPUT_PROVINCE,
106        IDS_LIBADDRESSINPUT_STATE,
107        IDS_LIBADDRESSINPUT_ORGANIZATION_LABEL,
108        IDS_LIBADDRESSINPUT_RECIPIENT_LABEL,
109        IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD,
110        IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE_AND_URL,
111        IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE,
112        IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE_AND_URL,
113        IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE,
114        IDS_LIBADDRESSINPUT_UNKNOWN_VALUE,
115        IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE_AND_URL,
116        IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE,
117        IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE,
118        IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE_AND_URL,
119        IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE,
120        IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP,
121        IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE_URL,
122        IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE,
123        IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP_URL,
124        IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP,
125        IDS_LIBADDRESSINPUT_PO_BOX_FORBIDDEN_VALUE));
126
127// Verifies that an invalid message identifier results in an empty string in the
128// default configuration.
129TEST_F(LocalizationTest, InvalidMessageIsEmptyString) {
130  EXPECT_TRUE(localization_.GetString(INVALID_MESSAGE_ID).empty());
131}
132
133TEST(LocalizationGetErrorMessageTest, MissingRequiredPostalCode) {
134  Localization localization;
135  AddressData address;
136  address.region_code = "CH";
137  EXPECT_EQ("You must provide a postal code, for example 2544."
138            " Don't know your postal code? Find it out"
139            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
140            "here</a>.",
141            localization.GetErrorMessage(address, POSTAL_CODE,
142                                         MISSING_REQUIRED_FIELD, true, true));
143  EXPECT_EQ("You must provide a postal code, for example 2544.",
144            localization.GetErrorMessage(address, POSTAL_CODE,
145                                         MISSING_REQUIRED_FIELD, true, false));
146  EXPECT_EQ("You can't leave this empty.",
147            localization.GetErrorMessage(address, POSTAL_CODE,
148                                         MISSING_REQUIRED_FIELD, false, false));
149  EXPECT_EQ("You can't leave this empty.",
150            localization.GetErrorMessage(address, POSTAL_CODE,
151                                         MISSING_REQUIRED_FIELD, false, true));
152}
153
154TEST(LocalizationGetErrorMessageTest, MissingRequiredZipCode) {
155  Localization localization;
156  AddressData address;
157  address.region_code = "US";
158  EXPECT_EQ("You must provide a ZIP code, for example 95014."
159            " Don't know your ZIP code? Find it out"
160            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
161            "input.action\">here</a>.",
162            localization.GetErrorMessage(address, POSTAL_CODE,
163                                         MISSING_REQUIRED_FIELD, true, true));
164  EXPECT_EQ("You must provide a ZIP code, for example 95014.",
165            localization.GetErrorMessage(address, POSTAL_CODE,
166                                         MISSING_REQUIRED_FIELD, true, false));
167  EXPECT_EQ("You can't leave this empty.",
168            localization.GetErrorMessage(address, POSTAL_CODE,
169                                         MISSING_REQUIRED_FIELD, false, false));
170  EXPECT_EQ("You can't leave this empty.",
171            localization.GetErrorMessage(address, POSTAL_CODE,
172            MISSING_REQUIRED_FIELD, false, true));
173}
174
175TEST(LocalizationGetErrorMessageTest, MissingRequiredOtherFields) {
176  Localization localization;
177  AddressData address;
178  address.region_code = "US";
179  std::vector<AddressField> other_fields;
180  other_fields.push_back(COUNTRY);
181  other_fields.push_back(ADMIN_AREA);
182  other_fields.push_back(LOCALITY);
183  other_fields.push_back(DEPENDENT_LOCALITY);
184  other_fields.push_back(SORTING_CODE);
185  other_fields.push_back(STREET_ADDRESS);
186  other_fields.push_back(ORGANIZATION);
187  other_fields.push_back(RECIPIENT);
188  for (std::vector<AddressField>::iterator it = other_fields.begin();
189       it != other_fields.end(); it++) {
190    EXPECT_EQ("You can't leave this empty.",
191              localization.GetErrorMessage(
192                  address, *it, MISSING_REQUIRED_FIELD, true, true));
193    EXPECT_EQ("You can't leave this empty.",
194              localization.GetErrorMessage(
195                  address, *it, MISSING_REQUIRED_FIELD, true, false));
196    EXPECT_EQ("You can't leave this empty.",
197              localization.GetErrorMessage(
198                  address, *it, MISSING_REQUIRED_FIELD, false, false));
199    EXPECT_EQ("You can't leave this empty.",
200              localization.GetErrorMessage(
201                  address, *it, MISSING_REQUIRED_FIELD, false, true));
202  }
203}
204
205TEST(LocalizationGetErrorMessageTest, UnknownValueOtherFields) {
206  Localization localization;
207  AddressData address;
208  address.region_code = "US";
209  address.administrative_area = "bad admin area";
210  address.locality = "bad locality";
211  address.dependent_locality = "bad dependent locality";
212  address.sorting_code = "bad sorting code";
213  std::vector<std::string> address_line;
214  address_line.push_back("bad address line 1");
215  address_line.push_back("bad address line 2");
216  address.address_line = address_line;
217  address.organization = "bad organization";
218  address.recipient = "bad recipient";
219  EXPECT_EQ("US "
220            "is not recognized as a known value for this field.",
221            localization.GetErrorMessage(
222                address, COUNTRY, UNKNOWN_VALUE, true, true));
223  EXPECT_EQ("US "
224            "is not recognized as a known value for this field.",
225            localization.GetErrorMessage(
226                address, COUNTRY, UNKNOWN_VALUE, true, false));
227  EXPECT_EQ("US "
228            "is not recognized as a known value for this field.",
229            localization.GetErrorMessage(
230                address, COUNTRY, UNKNOWN_VALUE, false, false));
231  EXPECT_EQ("US "
232            "is not recognized as a known value for this field.",
233            localization.GetErrorMessage(
234                address, COUNTRY, UNKNOWN_VALUE, false, true));
235  EXPECT_EQ("bad admin area "
236            "is not recognized as a known value for this field.",
237            localization.GetErrorMessage(
238                address, ADMIN_AREA, UNKNOWN_VALUE, true, true));
239  EXPECT_EQ("bad admin area "
240            "is not recognized as a known value for this field.",
241            localization.GetErrorMessage(
242                address, ADMIN_AREA, UNKNOWN_VALUE, true, false));
243  EXPECT_EQ("bad admin area "
244            "is not recognized as a known value for this field.",
245            localization.GetErrorMessage(
246                address, ADMIN_AREA, UNKNOWN_VALUE, false, false));
247  EXPECT_EQ("bad admin area "
248            "is not recognized as a known value for this field.",
249            localization.GetErrorMessage(
250                address, ADMIN_AREA, UNKNOWN_VALUE, false, true));
251  EXPECT_EQ("bad locality "
252            "is not recognized as a known value for this field.",
253            localization.GetErrorMessage(
254                address, LOCALITY, UNKNOWN_VALUE, true, true));
255  EXPECT_EQ("bad locality "
256            "is not recognized as a known value for this field.",
257            localization.GetErrorMessage(
258                address, LOCALITY, UNKNOWN_VALUE, true, false));
259  EXPECT_EQ("bad locality "
260            "is not recognized as a known value for this field.",
261            localization.GetErrorMessage(
262                address, LOCALITY, UNKNOWN_VALUE, false, false));
263  EXPECT_EQ("bad locality "
264            "is not recognized as a known value for this field.",
265            localization.GetErrorMessage(
266                address, LOCALITY, UNKNOWN_VALUE, false, true));
267  EXPECT_EQ("bad dependent locality "
268            "is not recognized as a known value for this field.",
269            localization.GetErrorMessage(
270                address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, true, true));
271  EXPECT_EQ("bad dependent locality "
272            "is not recognized as a known value for this field.",
273            localization.GetErrorMessage(
274                address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, true, false));
275  EXPECT_EQ("bad dependent locality "
276            "is not recognized as a known value for this field.",
277            localization.GetErrorMessage(
278                address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, false, false));
279  EXPECT_EQ("bad dependent locality "
280            "is not recognized as a known value for this field.",
281            localization.GetErrorMessage(
282                address, DEPENDENT_LOCALITY, UNKNOWN_VALUE, false, true));
283  EXPECT_EQ("bad sorting code "
284            "is not recognized as a known value for this field.",
285            localization.GetErrorMessage(
286                address, SORTING_CODE, UNKNOWN_VALUE, true, true));
287  EXPECT_EQ("bad sorting code "
288            "is not recognized as a known value for this field.",
289            localization.GetErrorMessage(
290                address, SORTING_CODE, UNKNOWN_VALUE, true, false));
291  EXPECT_EQ("bad sorting code "
292            "is not recognized as a known value for this field.",
293            localization.GetErrorMessage(
294                address, SORTING_CODE, UNKNOWN_VALUE, false, false));
295  EXPECT_EQ("bad sorting code "
296            "is not recognized as a known value for this field.",
297            localization.GetErrorMessage(
298                address, SORTING_CODE, UNKNOWN_VALUE, false, true));
299  EXPECT_EQ("bad address line 1 "
300            "is not recognized as a known value for this field.",
301            localization.GetErrorMessage(
302                address, STREET_ADDRESS, UNKNOWN_VALUE, true, true));
303  EXPECT_EQ("bad address line 1 "
304            "is not recognized as a known value for this field.",
305            localization.GetErrorMessage(
306                address, STREET_ADDRESS, UNKNOWN_VALUE, true, false));
307  EXPECT_EQ("bad address line 1 "
308            "is not recognized as a known value for this field.",
309            localization.GetErrorMessage(
310                address, STREET_ADDRESS, UNKNOWN_VALUE, false, false));
311  EXPECT_EQ("bad address line 1 "
312            "is not recognized as a known value for this field.",
313            localization.GetErrorMessage(
314                address, STREET_ADDRESS, UNKNOWN_VALUE, false, true));
315  EXPECT_EQ("bad organization "
316            "is not recognized as a known value for this field.",
317            localization.GetErrorMessage(
318                address, ORGANIZATION, UNKNOWN_VALUE, true, true));
319  EXPECT_EQ("bad organization "
320            "is not recognized as a known value for this field.",
321            localization.GetErrorMessage(
322                address, ORGANIZATION, UNKNOWN_VALUE, true, false));
323  EXPECT_EQ("bad organization "
324            "is not recognized as a known value for this field.",
325            localization.GetErrorMessage(
326                address, ORGANIZATION, UNKNOWN_VALUE, false, false));
327  EXPECT_EQ("bad organization "
328            "is not recognized as a known value for this field.",
329            localization.GetErrorMessage(
330                address, ORGANIZATION, UNKNOWN_VALUE, false, true));
331  EXPECT_EQ("bad recipient "
332            "is not recognized as a known value for this field.",
333            localization.GetErrorMessage(
334                address, RECIPIENT, UNKNOWN_VALUE, true, true));
335  EXPECT_EQ("bad recipient "
336            "is not recognized as a known value for this field.",
337            localization.GetErrorMessage(
338                address, RECIPIENT, UNKNOWN_VALUE, true, false));
339  EXPECT_EQ("bad recipient "
340            "is not recognized as a known value for this field.",
341            localization.GetErrorMessage(
342                address, RECIPIENT, UNKNOWN_VALUE, false, false));
343  EXPECT_EQ("bad recipient "
344            "is not recognized as a known value for this field.",
345            localization.GetErrorMessage(
346                address, RECIPIENT, UNKNOWN_VALUE, false, true));
347}
348
349TEST(LocalizationGetErrorMessageTest, InvalidFormatPostalCode) {
350  Localization localization;
351  AddressData address;
352  address.region_code = "CH";
353  EXPECT_EQ("This postal code format is not recognized. Example "
354            "of a valid postal code: 2544."
355            " Don't know your postal code? Find it out"
356            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
357            "here</a>.",
358            localization.GetErrorMessage(address, POSTAL_CODE,
359                                         INVALID_FORMAT, true, true));
360  EXPECT_EQ("This postal code format is not recognized. Example "
361            "of a valid postal code: 2544.",
362            localization.GetErrorMessage(address, POSTAL_CODE,
363                                         INVALID_FORMAT, true, false));
364  EXPECT_EQ("This postal code format is not recognized.",
365            localization.GetErrorMessage(address, POSTAL_CODE,
366                                         INVALID_FORMAT, false, false));
367  EXPECT_EQ("This postal code format is not recognized.",
368            localization.GetErrorMessage(address, POSTAL_CODE,
369                                         INVALID_FORMAT, false, true));
370}
371
372TEST(LocalizationGetErrorMessageTest, InvalidFormatZipCode) {
373  Localization localization;
374  AddressData address;
375  address.region_code = "US";
376  EXPECT_EQ("This ZIP code format is not recognized. Example of "
377            "a valid ZIP code: 95014."
378            " Don't know your ZIP code? Find it out"
379            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
380            "input.action\">here</a>.",
381            localization.GetErrorMessage(address, POSTAL_CODE,
382                                         INVALID_FORMAT, true, true));
383  EXPECT_EQ("This ZIP code format is not recognized. Example of "
384            "a valid ZIP code: 95014.",
385            localization.GetErrorMessage(address, POSTAL_CODE,
386                                         INVALID_FORMAT, true, false));
387  EXPECT_EQ("This ZIP code format is not recognized.",
388            localization.GetErrorMessage(address, POSTAL_CODE,
389                                         INVALID_FORMAT, false, false));
390  EXPECT_EQ("This ZIP code format is not recognized.",
391            localization.GetErrorMessage(address, POSTAL_CODE,
392                                         INVALID_FORMAT, false, true));
393}
394
395TEST(LocalizationGetErrorMessageTest, MismatchingValuePostalCode) {
396  Localization localization;
397  AddressData address;
398  address.region_code = "CH";
399  EXPECT_EQ("This postal code does not appear to match the rest "
400            "of this address."
401            " Don't know your postal code? Find it out"
402            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
403            "here</a>.",
404            localization.GetErrorMessage(address, POSTAL_CODE,
405                                         MISMATCHING_VALUE, true, true));
406  EXPECT_EQ("This postal code does not appear to match the rest "
407            "of this address.",
408            localization.GetErrorMessage(address, POSTAL_CODE,
409                                         MISMATCHING_VALUE, true, false));
410  EXPECT_EQ("This postal code does not appear to match the rest "
411            "of this address.",
412            localization.GetErrorMessage(address, POSTAL_CODE,
413                                         MISMATCHING_VALUE, false, false));
414  EXPECT_EQ("This postal code does not appear to match the rest "
415            "of this address."
416            " Don't know your postal code? Find it out"
417            " <a href=\"http://www.post.ch/db/owa/pv_plz_pack/pr_main\">"
418            "here</a>.",
419            localization.GetErrorMessage(address, POSTAL_CODE,
420                                         MISMATCHING_VALUE, false, true));
421}
422
423TEST(LocalizationGetErrorMessageTest, MismatchingValueZipCode) {
424  Localization localization;
425  AddressData address;
426  address.region_code = "US";
427  EXPECT_EQ("This ZIP code does not appear to match the rest of "
428            "this address."
429            " Don't know your ZIP code? Find it out"
430            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
431            "input.action\">here</a>.",
432            localization.GetErrorMessage(address, POSTAL_CODE,
433                                         MISMATCHING_VALUE, true, true));
434  EXPECT_EQ("This ZIP code does not appear to match the rest of "
435            "this address.",
436            localization.GetErrorMessage(address, POSTAL_CODE,
437                                         MISMATCHING_VALUE, true, false));
438  EXPECT_EQ("This ZIP code does not appear to match the rest of "
439            "this address.",
440            localization.GetErrorMessage(address, POSTAL_CODE,
441                                         MISMATCHING_VALUE, false, false));
442  EXPECT_EQ("This ZIP code does not appear to match the rest of "
443            "this address."
444            " Don't know your ZIP code? Find it out"
445            " <a href=\"https://tools.usps.com/go/ZipLookupAction!"
446            "input.action\">here</a>.",
447            localization.GetErrorMessage(address, POSTAL_CODE,
448                                         MISMATCHING_VALUE, false, true));
449}
450
451TEST(LocalizationGetErrorMessageTest, UsesPOBoxOtherFields) {
452  Localization localization;
453  AddressData address;
454  address.region_code = "US";
455  std::vector<AddressField> other_fields;
456  other_fields.push_back(COUNTRY);
457  other_fields.push_back(ADMIN_AREA);
458  other_fields.push_back(LOCALITY);
459  other_fields.push_back(DEPENDENT_LOCALITY);
460  other_fields.push_back(SORTING_CODE);
461  other_fields.push_back(STREET_ADDRESS);
462  other_fields.push_back(ORGANIZATION);
463  other_fields.push_back(RECIPIENT);
464  for (std::vector<AddressField>::iterator it = other_fields.begin();
465       it != other_fields.end(); it++) {
466    EXPECT_EQ("This address line appears to contain a post "
467              "office box. Please use a street"
468              " or building address.",
469              localization.GetErrorMessage(
470                  address, *it, USES_P_O_BOX, true, true));
471    EXPECT_EQ("This address line appears to contain a post "
472              "office box. Please use a street"
473              " or building address.",
474              localization.GetErrorMessage(
475                  address, *it, USES_P_O_BOX, true, false));
476    EXPECT_EQ("This address line appears to contain a post "
477              "office box. Please use a street"
478              " or building address.",
479              localization.GetErrorMessage(
480                  address, *it, USES_P_O_BOX, false, false));
481    EXPECT_EQ("This address line appears to contain a post "
482              "office box. Please use a street"
483              " or building address.",
484              localization.GetErrorMessage(
485                  address, *it, USES_P_O_BOX, false, true));
486  }
487}
488
489}  // namespace
490