diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/addrbook/test/unit/test_vCard.js | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/comm/mailnews/addrbook/test/unit/test_vCard.js b/comm/mailnews/addrbook/test/unit/test_vCard.js new file mode 100644 index 0000000000..328be1c8cd --- /dev/null +++ b/comm/mailnews/addrbook/test/unit/test_vCard.js @@ -0,0 +1,474 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ + +let { VCardProperties, VCardUtils } = ChromeUtils.import( + "resource:///modules/VCardUtils.jsm" +); + +const ANY_UID = "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + +add_task(function testVCardToPropertyMap() { + function check(vCardLine, expectedProps) { + let vCard = `BEGIN:VCARD\r\n${vCardLine}\r\nEND:VCARD\r\n`; + info(vCard); + let properties = VCardProperties.fromVCard(vCard).toPropertyMap(); + // Check that every property in expectedProps is present in `properties`. + // No other property can be present unless it is in `propWhitelist`. + for (let [name, value] of properties) { + if (name in expectedProps) { + Assert.equal(value, expectedProps[name], `expected ${name}`); + delete expectedProps[name]; + } else { + Assert.ok(false, `card should not have property '${name}'`); + } + } + + for (let name of Object.keys(expectedProps)) { + Assert.ok(false, `expected ${name} not found`); + } + } + + // Name + check("N:Last;First", { FirstName: "First", LastName: "Last" }); + check("N:Last;First;;;", { FirstName: "First", LastName: "Last" }); + check("N:Last;First;Middle;Prefix;Suffix", { + FirstName: "First", + LastName: "Last", + AdditionalNames: "Middle", + NamePrefix: "Prefix", + NameSuffix: "Suffix", + }); + check("N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.", { + FirstName: "John", + LastName: "Stevenson", + AdditionalNames: "Philip Paul", + NamePrefix: "Dr.", + NameSuffix: "Jr. M.D. A.C.P.", + }); + + // Address + check( + "ADR:PO Box 3.14;Apartment 4;123 Main Street;Any Town;CA;91921-1234;U.S.A.", + { + WorkPOBox: "PO Box 3.14", + WorkAddress2: "Apartment 4", + WorkAddress: "123 Main Street", + WorkCity: "Any Town", + WorkState: "CA", + WorkZipCode: "91921-1234", + WorkCountry: "U.S.A.", + } + ); + check( + "ADR;TYPE=work:PO Box 3.14;Apartment 4;123 Main Street;Any Town;CA;91921-1234;U.S.A.", + { + WorkPOBox: "PO Box 3.14", + WorkAddress2: "Apartment 4", + WorkAddress: "123 Main Street", + WorkCity: "Any Town", + WorkState: "CA", + WorkZipCode: "91921-1234", + WorkCountry: "U.S.A.", + } + ); + check( + "ADR;TYPE=home:PO Box 3.14;Apartment 4;123 Main Street;Any Town;CA;91921-1234;U.S.A.", + { + HomePOBox: "PO Box 3.14", + HomeAddress2: "Apartment 4", + HomeAddress: "123 Main Street", + HomeCity: "Any Town", + HomeState: "CA", + HomeZipCode: "91921-1234", + HomeCountry: "U.S.A.", + } + ); + + // Phone + check("TEL:11-2358-13-21", { WorkPhone: "11-2358-13-21" }); + check("TEL;TYPE=work:11-2358-13-21", { WorkPhone: "11-2358-13-21" }); + check("TEL;TYPE=home:11-2358-13-21", { HomePhone: "11-2358-13-21" }); + check("TEL;TYPE=cell:11-2358-13-21", { CellularNumber: "11-2358-13-21" }); + check("TEL;TYPE=pager:11-2358-13-21", { PagerNumber: "11-2358-13-21" }); + check("TEL;TYPE=fax:11-2358-13-21", { FaxNumber: "11-2358-13-21" }); + + check("TEL;TYPE=work;PREF:11-2358-13-21", { WorkPhone: "11-2358-13-21" }); + check("TEL;TYPE=work,cell:11-2358-13-21", { WorkPhone: "11-2358-13-21" }); + check("TEL;TYPE=work;TYPE=cell:11-2358-13-21", { + WorkPhone: "11-2358-13-21", + }); + check("TEL;TYPE=work;VALUE=TEXT:11-2358-13-21", { + WorkPhone: "11-2358-13-21", + }); + check("TEL;TYPE=home;VALUE=TEXT:011-2358-13-21", { + HomePhone: "011-2358-13-21", + }); + check( + "TEL;TYPE=work;VALUE=TEXT:11-2358-13-21\r\nTEL;TYPE=home;VALUE=TEXT:011-2358-13-21", + { + WorkPhone: "11-2358-13-21", + HomePhone: "011-2358-13-21", + } + ); + check("TEL;TYPE=cell:11-2358-13-21\r\nTEL;TYPE=cell:011-2358-13-21", { + CellularNumber: "11-2358-13-21", + }); + check("TEL;TYPE=cell;PREF=1:11-2358-13-21\r\nTEL;TYPE=cell:011-2358-13-21", { + CellularNumber: "11-2358-13-21", + }); + check("TEL;TYPE=cell:11-2358-13-21\r\nTEL;TYPE=cell;PREF=1:011-2358-13-21", { + CellularNumber: "011-2358-13-21", + }); + + // Birthday + check("BDAY;VALUE=DATE:19830403", { + BirthDay: "3", + BirthMonth: "4", + BirthYear: "1983", + }); + check("BDAY:--0415", { BirthDay: "15", BirthMonth: "4" }); + check("BDAY:2001", { BirthYear: "2001" }); + check("BDAY:2006-06", { BirthYear: "2006", BirthMonth: "6" }); + check("BDAY:--12", { BirthMonth: "12" }); + check("BDAY:---30", { BirthDay: "30" }); + // These are error cases, testing that it doesn't throw. + check("BDAY;VALUE=DATE:NaN-NaN-NaN", {}); + check("BDAY;VALUE=TEXT:07/07/1949", {}); + + // Anniversary + check("ANNIVERSARY;VALUE=DATE:20041207", { + AnniversaryDay: "7", + AnniversaryMonth: "12", + AnniversaryYear: "2004", + }); + + // Organization: any number of values is valid here. + check("ORG:Acme Widgets, Inc.", { + Company: "Acme Widgets, Inc.", + }); + check("ORG:Acme Widgets, Inc.;Manufacturing", { + Company: "Acme Widgets, Inc.", + Department: "Manufacturing", + }); + check("ORG:Acme Widgets, Inc.;Manufacturing;Thingamies", { + Company: "Acme Widgets, Inc.", + Department: "Manufacturing", + }); + + // URL + // If no type is given assume its WebPage1 (work). + check("URL:https://www.thunderbird.net/", { + WebPage1: "https://www.thunderbird.net/", + }); + + check("URL;TYPE=work:https://developer.thunderbird.net/", { + WebPage1: "https://developer.thunderbird.net/", + }); + + check("URL;TYPE=home:https://addons.thunderbird.net/", { + WebPage2: "https://addons.thunderbird.net/", + }); + + check( + formatVCard` + URL;TYPE=home:https://addons.thunderbird.net/ + URL;TYPE=work:https://developer.thunderbird.net/`, + { + WebPage1: "https://developer.thunderbird.net/", + WebPage2: "https://addons.thunderbird.net/", + } + ); + + // If a URL without a type is given and a Work Web Page do not import the URL without type. + check( + formatVCard` + URL:https://www.thunderbird.net/ + URL;TYPE=home:https://addons.thunderbird.net/ + URL;TYPE=work:https://developer.thunderbird.net/`, + { + WebPage1: "https://developer.thunderbird.net/", + WebPage2: "https://addons.thunderbird.net/", + } + ); + // Email: just to be difficult, email is stored by priority, not type. + check("EMAIL:first@invalid", { PrimaryEmail: "first@invalid" }); + check("EMAIL;PREF=1:first@invalid", { PrimaryEmail: "first@invalid" }); + + check("EMAIL;PREF=1:first@invalid\r\nEMAIL:second@invalid", { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + }); + check("EMAIL:second@invalid\r\nEMAIL;PREF=1:first@invalid", { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + }); + + check("EMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=2:second@invalid", { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + }); + check("EMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=1:first@invalid", { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + }); + + check( + "EMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=3:third@invalid", + { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + } + ); + check( + "EMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=1:first@invalid", + { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + } + ); + check( + "EMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=2:second@invalid", + { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + } + ); + check( + "EMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=1:first@invalid", + { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + } + ); + check( + "EMAIL;PREF=2:second@invalid\r\nEMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=3:third@invalid", + { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + } + ); + check( + "EMAIL;PREF=1:first@invalid\r\nEMAIL;PREF=3:third@invalid\r\nEMAIL;PREF=2:second@invalid", + { + PrimaryEmail: "first@invalid", + SecondEmail: "second@invalid", + } + ); + + // Group-prefixed properties. + check( + formatVCard` + item1.EMAIL:first@invalid + item1.X-ABLabel:First`, + { + PrimaryEmail: "first@invalid", + } + ); + check( + formatVCard` + item1.EMAIL:first@invalid + item1.X-ABLabel:First + item2.EMAIL:second@invalid + item2.X-ABLabel:Second`, + { PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" } + ); + check( + formatVCard` + foo-bar.EMAIL:first@invalid + foo-bar.X-ABLabel:First + EMAIL:second@invalid`, + { PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" } + ); + check( + formatVCard` + EMAIL:first@invalid + abc.EMAIL:second@invalid + abc.X-ABLabel:Second`, + { PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" } + ); + check("xyz.TEL:11-2358-13-21", { WorkPhone: "11-2358-13-21" }); +}); + +add_task(function testAbCardToVCard() { + function check(abCardProps, ...expectedLines) { + let abCard = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance( + Ci.nsIAbCard + ); + for (let [name, value] of Object.entries(abCardProps)) { + if (name == "UID") { + abCard.UID = abCardProps.UID; + continue; + } + abCard.setProperty(name, value); + } + + let vCard = VCardUtils.abCardToVCard(abCard); + info(vCard); + let vCardLines = vCard.split("\r\n"); + if (expectedLines.includes(ANY_UID)) { + for (let i = 0; i < vCardLines.length; i++) { + if (vCardLines[i].startsWith("UID:")) { + vCardLines[i] = ANY_UID; + } + } + } + + for (let line of expectedLines) { + Assert.ok(vCardLines.includes(line), line); + } + } + + // UID + check( + { + UID: "12345678-1234-1234-1234-123456789012", + }, + "UID:12345678-1234-1234-1234-123456789012" + ); + + // Name + check( + { + FirstName: "First", + LastName: "Last", + }, + "N:Last;First;;;", + ANY_UID + ); + check( + { + FirstName: "First", + LastName: "Last", + AdditionalNames: "Middle", + NamePrefix: "Prefix", + NameSuffix: "Suffix", + }, + "N:Last;First;Middle;Prefix;Suffix", + ANY_UID + ); + check( + { + FirstName: "First", + LastName: "Last", + NameSuffix: "Suffix", + }, + "N:Last;First;;;Suffix", + ANY_UID + ); + + // Address + check( + { + WorkAddress: "123 Main Street", + WorkCity: "Any Town", + WorkState: "CA", + WorkZipCode: "91921-1234", + WorkCountry: "U.S.A.", + }, + "ADR:;;123 Main Street;Any Town;CA;91921-1234;U.S.A.", + ANY_UID + ); + check( + { + HomeAddress: "123 Main Street", + HomeCity: "Any Town", + HomeState: "CA", + HomeZipCode: "91921-1234", + HomeCountry: "U.S.A.", + }, + "ADR:;;123 Main Street;Any Town;CA;91921-1234;U.S.A.", + ANY_UID + ); + + // Phone + check( + { + WorkPhone: "11-2358-13-21", + }, + "TEL;VALUE=TEXT:11-2358-13-21", + ANY_UID + ); + check( + { + HomePhone: "011-2358-13-21", + }, + "TEL;VALUE=TEXT:011-2358-13-21", + ANY_UID + ); + check( + { + WorkPhone: "11-2358-13-21", + HomePhone: "011-2358-13-21", + }, + "TEL;TYPE=work;VALUE=TEXT:11-2358-13-21", + "TEL;TYPE=home;VALUE=TEXT:011-2358-13-21", + ANY_UID + ); + + // Birthday + check( + { + BirthDay: "3", + BirthMonth: "4", + BirthYear: "1983", + }, + "BDAY;VALUE=DATE:19830403", + ANY_UID + ); + check( + { + BirthDay: "3", + BirthMonth: "4", + BirthYear: "", // No value. + }, + "BDAY;VALUE=DATE:--0403", + ANY_UID + ); + check( + { + BirthDay: "3", + BirthMonth: "4", + // BirthYear missing altogether. + }, + "BDAY;VALUE=DATE:--0403", + ANY_UID + ); + check( + { + BirthDay: "", // No value. + BirthMonth: "", // No value. + BirthYear: "1983", + }, + "BDAY;VALUE=DATE:1983", + ANY_UID + ); + check( + { + BirthDay: "", // No value. + BirthMonth: "", // No value. + BirthYear: "", // No value. + }, + ANY_UID + ); + + // Anniversary + check( + { + AnniversaryDay: "7", + AnniversaryMonth: "12", + AnniversaryYear: "2004", + }, + "ANNIVERSARY;VALUE=DATE:20041207", + ANY_UID + ); + + // Email + check({ PrimaryEmail: "first@invalid" }, "EMAIL;PREF=1:first@invalid"); + check({ SecondEmail: "second@invalid" }, "EMAIL:second@invalid"); + check( + { PrimaryEmail: "first@invalid", SecondEmail: "second@invalid" }, + "EMAIL;PREF=1:first@invalid", + "EMAIL:second@invalid" + ); +}); |