File indexing completed on 2024-04-21 03:53:25

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "addressformat.h"
0007 #include "addressformatparser.cpp"
0008 #include "addressformatscript.cpp"
0009 #include "addressformatter.cpp"
0010 
0011 #include <KConfig>
0012 #include <KConfigGroup>
0013 #include <KCountry>
0014 
0015 #include <QObject>
0016 #include <QTest>
0017 
0018 using namespace KContacts;
0019 
0020 void initLocale()
0021 {
0022     qputenv("LANGUAGE", "en_US");
0023     QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
0024 }
0025 
0026 Q_CONSTRUCTOR_FUNCTION(initLocale)
0027 
0028 class AddressFormatTest : public QObject
0029 {
0030     Q_OBJECT
0031 private:
0032     AddressFormat parseFormat(QStringView f, QStringView u, QStringView country)
0033     {
0034         AddressFormat format;
0035         auto fmt = AddressFormatPrivate::get(format);
0036         fmt->upper = AddressFormatParser::parseFields(u);
0037         fmt->elements = AddressFormatParser::parseElements(f);
0038         fmt->country = country.toString();
0039         return format;
0040     }
0041 
0042 private Q_SLOTS:
0043     void testRepostory()
0044     {
0045         auto fmt = AddressFormatRepository::formatForCountry(QStringLiteral("CA"), AddressFormatScriptPreference::Local);
0046         QCOMPARE(fmt.requiredFields(),
0047                  AddressFormatField::StreetAddress | AddressFormatField::Locality | AddressFormatField::PostalCode | AddressFormatField::Region);
0048         QCOMPARE(fmt.upperCaseFields(),
0049                  AddressFormatField::StreetAddress | AddressFormatField::Locality | AddressFormatField::PostalCode | AddressFormatField::Region
0050                      | AddressFormatField::Name | AddressFormatField::Organization | AddressFormatField::Country);
0051         QCOMPARE(fmt.usedFields(),
0052                  AddressFormatField::StreetAddress | AddressFormatField::Locality | AddressFormatField::PostalCode | AddressFormatField::Region
0053                      | AddressFormatField::Name | AddressFormatField::Organization | AddressFormatField::PostOfficeBox);
0054         const auto &elems = fmt.elements();
0055         QCOMPARE(elems.size(), 14);
0056 
0057         QCOMPARE(elems[0].isField(), true);
0058         QCOMPARE(elems[0].field(), AddressFormatField::Name);
0059         QCOMPARE(elems[1].isSeparator(), true);
0060         QCOMPARE(elems[2].isField(), true);
0061         QCOMPARE(elems[2].field(), AddressFormatField::Organization);
0062         QCOMPARE(elems[3].isSeparator(), true);
0063         QCOMPARE(elems[6].isLiteral(), true);
0064         QCOMPARE(elems[6].literal(), QLatin1String("PO BOX "));
0065         QCOMPARE(elems[9].isField(), true);
0066         QCOMPARE(elems[9].field(), AddressFormatField::Locality);
0067         QCOMPARE(elems[10].isLiteral(), true);
0068         QCOMPARE(elems[10].literal(), QLatin1String(" "));
0069         QCOMPARE(elems[11].isField(), true);
0070         QCOMPARE(elems[11].field(), AddressFormatField::Region);
0071         QCOMPARE(elems[12].isLiteral(), true);
0072         QCOMPARE(elems[12].literal(), QLatin1String(" "));
0073         QCOMPARE(elems[13].isField(), true);
0074         QCOMPARE(elems[13].field(), AddressFormatField::PostalCode);
0075 
0076         QVERIFY(!fmt.postalCodeRegularExpression().isEmpty());
0077         QCOMPARE(fmt.country(), QLatin1String("CA"));
0078     }
0079 
0080     void testFormatStyles()
0081     {
0082         Address addr;
0083         addr.setCountry(QStringLiteral("DE"));
0084         addr.setRegion(QStringLiteral("BE"));
0085         addr.setLocality(QStringLiteral("Berlin"));
0086         addr.setPostalCode(QStringLiteral("10969"));
0087         addr.setStreet(QStringLiteral("Prinzenstraße 85 F"));
0088         addr.setExtended(QStringLiteral("East wing"));
0089 
0090         auto fmt = parseFormat(u"%O%n%N%nPostfach %P%n%A%n%Z %C", u"R", u"DE");
0091         auto s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::Postal);
0092         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nEast wing\nPrinzenstraße 85 F\n10969 Berlin\n\nGERMANY"));
0093         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::MultiLineInternational);
0094         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nEast wing\nPrinzenstraße 85 F\n10969 Berlin\nGermany"));
0095         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::MultiLineDomestic);
0096         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nEast wing\nPrinzenstraße 85 F\n10969 Berlin"));
0097         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::SingleLineInternational);
0098         QCOMPARE(s, QStringLiteral("KDE e.V., Dr. Konqi, East wing, Prinzenstraße 85 F, 10969 Berlin, Germany"));
0099         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::SingleLineDomestic);
0100         QCOMPARE(s, QStringLiteral("KDE e.V., Dr. Konqi, East wing, Prinzenstraße 85 F, 10969 Berlin"));
0101         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::GeoUriQuery);
0102         QCOMPARE(s, QStringLiteral("Prinzenstraße 85 F,10969 Berlin,DE"));
0103 
0104         addr.setExtended(QString());
0105         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::Postal);
0106         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nPrinzenstraße 85 F\n10969 Berlin\n\nGERMANY"));
0107         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::MultiLineInternational);
0108         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nPrinzenstraße 85 F\n10969 Berlin\nGermany"));
0109         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::MultiLineDomestic);
0110         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nPrinzenstraße 85 F\n10969 Berlin"));
0111         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::SingleLineInternational);
0112         QCOMPARE(s, QStringLiteral("KDE e.V., Dr. Konqi, Prinzenstraße 85 F, 10969 Berlin, Germany"));
0113         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::SingleLineDomestic);
0114         QCOMPARE(s, QStringLiteral("KDE e.V., Dr. Konqi, Prinzenstraße 85 F, 10969 Berlin"));
0115         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::GeoUriQuery);
0116         QCOMPARE(s, QStringLiteral("Prinzenstraße 85 F,10969 Berlin,DE"));
0117 
0118         addr.setPostOfficeBox(QStringLiteral("42"));
0119         addr.setStreet(QString());
0120         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::Postal);
0121         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nPostfach 42\n10969 Berlin\n\nGERMANY"));
0122         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::MultiLineInternational);
0123         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nPostfach 42\n10969 Berlin\nGermany"));
0124         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::MultiLineDomestic);
0125         QCOMPARE(s, QStringLiteral("KDE e.V.\nDr. Konqi\nPostfach 42\n10969 Berlin"));
0126         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::SingleLineInternational);
0127         QCOMPARE(s, QStringLiteral("KDE e.V., Dr. Konqi, Postfach 42, 10969 Berlin, Germany"));
0128         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::SingleLineDomestic);
0129         QCOMPARE(s, QStringLiteral("KDE e.V., Dr. Konqi, Postfach 42, 10969 Berlin"));
0130         s = AddressFormatter::format(addr, QStringLiteral("Dr. Konqi"), QStringLiteral("KDE e.V."), fmt, AddressFormatStyle::GeoUriQuery);
0131         QCOMPARE(s, QStringLiteral("10969 Berlin,DE"));
0132     }
0133 
0134     void testFormatScript()
0135     {
0136         KContacts::Address address;
0137         address.setCountry(QStringLiteral("JP"));
0138         address.setRegion(QStringLiteral("東京"));
0139         address.setLocality(QStringLiteral("都港区"));
0140         address.setPostalCode(QStringLiteral("106-0047"));
0141         address.setStreet(QStringLiteral("南麻布 4-6-28"));
0142         auto fmt = parseFormat(u"〒%Z%n%S%C%A%n%O%n%N", u"SR", u"JP");
0143         auto s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::SingleLineDomestic);
0144         QCOMPARE(s, QStringLiteral("〒106-0047東京都港区南麻布 4-6-28"));
0145 
0146         address = {};
0147         address.setCountry(QStringLiteral("EG"));
0148         address.setLocality(QStringLiteral("القاهرة"));
0149         address.setStreet(QStringLiteral("2005ج كورنيش النيل، رملة بولاق"));
0150         fmt = parseFormat(u"%N%n%O%n%A%n%C%n%S%n%Z", u"", u"EG");
0151         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::SingleLineDomestic);
0152         QCOMPARE(s, QStringLiteral("2005ج كورنيش النيل، رملة بولاق، القاهرة"));
0153 
0154         address = {};
0155         address.setCountry(QStringLiteral("KR"));
0156         address.setRegion(QStringLiteral("서울특별시"));
0157         address.setLocality(QStringLiteral("중구"));
0158         address.setPostalCode(QStringLiteral("04637"));
0159         address.setStreet(QStringLiteral("한강대로 416"));
0160         fmt = parseFormat(u"%R%n%S %C%D%n%A%n%O%n%N%n%Z", u"Z", u"KR");
0161         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::SingleLineDomestic);
0162         QCOMPARE(s, QStringLiteral("서울특별시 중구 한강대로 416 04637"));
0163         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::MultiLineDomestic);
0164         QCOMPARE(s, QStringLiteral("서울특별시 중구\n한강대로 416\n04637"));
0165         // the weird language mix is because we are in the wrong locale for KR here,
0166         // the important part is that the country is in the front when using Hangul
0167         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::SingleLineInternational);
0168         QCOMPARE(s, QStringLiteral("Korea, Republic of 서울특별시 중구 한강대로 416 04637"));
0169         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::MultiLineInternational);
0170         QCOMPARE(s, QStringLiteral("Korea, Republic of\n서울특별시 중구\n한강대로 416\n04637"));
0171 
0172         // reverse order address lines
0173         address.setExtended(QStringLiteral("서울스퀘어 11층"));
0174         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::SingleLineDomestic);
0175         QCOMPARE(s, QStringLiteral("서울특별시 중구 한강대로 416 서울스퀘어 11층 04637"));
0176         s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::MultiLineDomestic);
0177         QCOMPARE(s, QStringLiteral("서울특별시 중구\n한강대로 416\n서울스퀘어 11층\n04637"));
0178     }
0179 
0180     void testIncompleteAddress()
0181     {
0182         KContacts::Address address;
0183         address.setLocality(QStringLiteral("City"));
0184         address.setPostalCode(QStringLiteral("XX 12345")); // region wrongly part of postal code field
0185 
0186         auto fmt = parseFormat(u"%C, %S %Z", u"", u"US");
0187         auto s = AddressFormatter::format(address, QString(), QString(), fmt, AddressFormatStyle::MultiLineDomestic);
0188         QCOMPARE(s, QLatin1String("City XX 12345"));
0189     }
0190 
0191     void validateRepository()
0192     {
0193         KConfig config(QStringLiteral(":/org.kde.kcontacts/addressformatrc"), KConfig::SimpleConfig);
0194         const auto groups = config.groupList();
0195 
0196         for (const auto &countryCode : groups) {
0197             // qDebug() << countryCode;
0198             QVERIFY(KCountry::fromAlpha2(countryCode).isValid());
0199             const auto group = config.group(countryCode);
0200 
0201             QVERIFY(group.hasKey("AddressFormat"));
0202             const auto upper = AddressFormatParser::parseFields(group.readEntry("Upper"));
0203             const auto required = AddressFormatParser::parseFields(group.readEntry("Required"));
0204 
0205             // TODO can we check all language variants as well?
0206             for (const auto &key : {"AddressFormat", "BusinessAddressFormat", "LatinAddressFormat", "LatinBusinessAddressFormat"}) {
0207                 if (!group.hasKey(key)) {
0208                     continue;
0209                 }
0210                 const auto elems = AddressFormatParser::parseElements(group.readEntry(key, QString()));
0211 
0212                 AddressFormatFields seen = AddressFormatField::NoField;
0213                 for (const auto &elem : elems) {
0214                     if (!elem.isField()) {
0215                         continue;
0216                     }
0217                     QCOMPARE(seen & elem.field() & ~(int)AddressFormatField::SortingCode, 0);
0218                     seen |= elem.field();
0219                 }
0220 
0221                 QCOMPARE(seen & required, required);
0222                 QCOMPARE(seen & upper & ~(int)AddressFormatField::Country, upper & ~(int)AddressFormatField::Country);
0223             }
0224 
0225             const auto zipRegEx = group.readEntry("PostalCodeFormat", QString());
0226             if (!zipRegEx.isEmpty()) {
0227                 QVERIFY(QRegularExpression(zipRegEx).isValid());
0228             }
0229         }
0230     }
0231 };
0232 
0233 QTEST_GUILESS_MAIN(AddressFormatTest)
0234 
0235 #include "addressformattest.moc"