summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/import/test
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/import/test')
-rw-r--r--comm/mailnews/import/test/moz.build6
-rw-r--r--comm/mailnews/import/test/unit/head_import.js23
-rw-r--r--comm/mailnews/import/test/unit/resources/AB_README39
-rw-r--r--comm/mailnews/import/test/unit/resources/WindowsLiveMail/MicrosoftCommunities/account{2E23}.oeaccountbin0 -> 698 bytes
-rw-r--r--comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallimap/donhallimap{testimap}.oeaccountbin0 -> 4454 bytes
-rw-r--r--comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallnntp/donhallnntp{testnntp}.oeaccountbin0 -> 2728 bytes
-rw-r--r--comm/mailnews/import/test/unit/resources/WindowsLiveMail/news.mozilla.org/account{B3B3}.oeaccountbin0 -> 960 bytes
-rw-r--r--comm/mailnews/import/test/unit/resources/WindowsLiveMail/pop3.test.test/account{D244}.oeaccountbin0 -> 1478 bytes
-rw-r--r--comm/mailnews/import/test/unit/resources/addressbook.json170
-rw-r--r--comm/mailnews/import/test/unit/resources/basic_addressbook.csv2
-rw-r--r--comm/mailnews/import/test/unit/resources/basic_csv_addressbook.csv3
-rw-r--r--comm/mailnews/import/test/unit/resources/basic_ldif_addressbook.ldif45
-rw-r--r--comm/mailnews/import/test/unit/resources/basic_vcard_addressbook.vcf12
-rw-r--r--comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186e.bab26
-rw-r--r--comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186f.bab13
-rw-r--r--comm/mailnews/import/test/unit/resources/becky/addressbooks/do_not_import_this.nobab12
-rw-r--r--comm/mailnews/import/test/unit/resources/becky/filters/IFilter.def23
-rw-r--r--comm/mailnews/import/test/unit/resources/becky/filters/OFilter.def22
-rw-r--r--comm/mailnews/import/test/unit/resources/bug_263304.ldif7
-rw-r--r--comm/mailnews/import/test/unit/resources/csv_no_header.csv2
-rw-r--r--comm/mailnews/import/test/unit/resources/csv_semicolon.csv3
-rw-r--r--comm/mailnews/import/test/unit/resources/dos_vcard_addressbook.vcf6
-rw-r--r--comm/mailnews/import/test/unit/resources/emptylines_vcard_addressbook.vcf18
-rw-r--r--comm/mailnews/import/test/unit/resources/import_helper.js665
-rw-r--r--comm/mailnews/import/test/unit/resources/mock_windows_reg_factory.js84
-rw-r--r--comm/mailnews/import/test/unit/resources/quote.csv2
-rw-r--r--comm/mailnews/import/test/unit/resources/shiftjis_addressbook.csv2
-rw-r--r--comm/mailnews/import/test/unit/resources/tab_comma_mixed.csv4
-rw-r--r--comm/mailnews/import/test/unit/resources/utf16_addressbook.csvbin0 -> 1006 bytes
-rw-r--r--comm/mailnews/import/test/unit/test_AddrBookFileImporter.js130
-rw-r--r--comm/mailnews/import/test/unit/test_ThunderbirdProfileImporter.js288
-rw-r--r--comm/mailnews/import/test/unit/test_becky_addressbook.js59
-rw-r--r--comm/mailnews/import/test/unit/test_becky_filters.js41
-rw-r--r--comm/mailnews/import/test/unit/test_bug_263304.js25
-rw-r--r--comm/mailnews/import/test/unit/test_bug_437556.js23
-rw-r--r--comm/mailnews/import/test/unit/test_csv_GetSample.js15
-rw-r--r--comm/mailnews/import/test/unit/test_csv_import.js23
-rw-r--r--comm/mailnews/import/test/unit/test_csv_import_quote.js11
-rw-r--r--comm/mailnews/import/test/unit/test_ldif_import.js27
-rw-r--r--comm/mailnews/import/test/unit/test_outlook_settings.js158
-rw-r--r--comm/mailnews/import/test/unit/test_shiftjis_csv.js20
-rw-r--r--comm/mailnews/import/test/unit/test_utf16_csv.js20
-rw-r--r--comm/mailnews/import/test/unit/test_vcard_import.js34
-rw-r--r--comm/mailnews/import/test/unit/test_winmail.js178
-rw-r--r--comm/mailnews/import/test/unit/xpcshell.ini26
45 files changed, 2267 insertions, 0 deletions
diff --git a/comm/mailnews/import/test/moz.build b/comm/mailnews/import/test/moz.build
new file mode 100644
index 0000000000..6b37fdbe09
--- /dev/null
+++ b/comm/mailnews/import/test/moz.build
@@ -0,0 +1,6 @@
+# vim: set filetype=python:
+# 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/.
+
+XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.ini"]
diff --git a/comm/mailnews/import/test/unit/head_import.js b/comm/mailnews/import/test/unit/head_import.js
new file mode 100644
index 0000000000..19be6a2662
--- /dev/null
+++ b/comm/mailnews/import/test/unit/head_import.js
@@ -0,0 +1,23 @@
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+var { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+var CC = Components.Constructor;
+
+// Ensure the profile directory is set up
+do_get_profile();
+
+// Import the required setup scripts.
+/* import-globals-from ../../../test/resources/abSetup.js */
+load("../../../resources/abSetup.js");
+
+// Import the script with basic import functions
+/* import-globals-from resources/import_helper.js */
+load("resources/import_helper.js");
+
+registerCleanupFunction(function () {
+ load("../../../resources/mailShutdown.js");
+});
diff --git a/comm/mailnews/import/test/unit/resources/AB_README b/comm/mailnews/import/test/unit/resources/AB_README
new file mode 100644
index 0000000000..3cbeb09508
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/AB_README
@@ -0,0 +1,39 @@
+To test importing an address book, make a new file in the
+/import/test/unit directory with the prefix test_ in the filename
+(ex. test_ldif_import.js).
+
+It should have a function named run_test with no parameters. If you are using
+import_helper.js, which is already imported, you must at least get the file
+to import and make a new AbImportHelper object with at least the file and type
+of import. Call the beginImport method on the object when you are ready to
+start the import.
+
+If you would like the results of the import checked, make sure to update
+addressbook.json. This file is read by import_helper.js to compare the address
+book cards imported to an array of "cards" in in this file. When making a new
+import, first chose a name for the array (like basic_addressbook) to store the
+cards that should be in the newly-imported address book. The properties and
+values of each object in the array should identical to the properties and values
+of the newly-imported card(s) and the cards themselves need to be in the
+expected order. If a card to be imported does not have a property, do not
+include it in the JSON card. Multiple types of imports can be tested with one
+array, as only the supported attributes are checked.
+
+You will also need to give the AbImportHelper constructor two additional
+parameters: the name the imported address book will have (the filename without
+the extension) and the name you chose for the JSON object.
+
+Here is a sample LDIF unit test that doesn't check the results:
+function run_test()
+{
+ var file = do_get_file("resources/basic_ldif_addressbook.ldif");
+ new AbImportHelper(file, "Text file").beginImport();
+}
+
+Here is a sample CSV unit test that checks the results:
+function run_test()
+{
+ var file = do_get_file("resources/basic_csv_addressbook.csv");
+ new AbImportHelper(file, "Text file", "basic_csv_addressbook",
+ "basic_addressbook").beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/resources/WindowsLiveMail/MicrosoftCommunities/account{2E23}.oeaccount b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/MicrosoftCommunities/account{2E23}.oeaccount
new file mode 100644
index 0000000000..b1b278658a
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/MicrosoftCommunities/account{2E23}.oeaccount
Binary files differ
diff --git a/comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallimap/donhallimap{testimap}.oeaccount b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallimap/donhallimap{testimap}.oeaccount
new file mode 100644
index 0000000000..c23cf25d17
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallimap/donhallimap{testimap}.oeaccount
Binary files differ
diff --git a/comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallnntp/donhallnntp{testnntp}.oeaccount b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallnntp/donhallnntp{testnntp}.oeaccount
new file mode 100644
index 0000000000..65872dcdbe
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/donhallnntp/donhallnntp{testnntp}.oeaccount
Binary files differ
diff --git a/comm/mailnews/import/test/unit/resources/WindowsLiveMail/news.mozilla.org/account{B3B3}.oeaccount b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/news.mozilla.org/account{B3B3}.oeaccount
new file mode 100644
index 0000000000..f17de718ae
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/news.mozilla.org/account{B3B3}.oeaccount
Binary files differ
diff --git a/comm/mailnews/import/test/unit/resources/WindowsLiveMail/pop3.test.test/account{D244}.oeaccount b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/pop3.test.test/account{D244}.oeaccount
new file mode 100644
index 0000000000..5ec08c4945
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/WindowsLiveMail/pop3.test.test/account{D244}.oeaccount
Binary files differ
diff --git a/comm/mailnews/import/test/unit/resources/addressbook.json b/comm/mailnews/import/test/unit/resources/addressbook.json
new file mode 100644
index 0000000000..c9545d3027
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/addressbook.json
@@ -0,0 +1,170 @@
+{
+ "basic_addressbook": [
+ {
+ "DisplayName": "Display Name",
+ "PrimaryEmail": "primaryemail@host.invalid",
+ "FirstName": "First",
+ "LastName": "Last",
+ "NickName": "Nickname",
+ "SecondEmail": "secondemail@host.invalid",
+ "_AimScreenName": "screenname",
+ "LastModifiedDate": 1213818826,
+ "_vCard": [
+ "VERSION:4.0",
+ "FN:Display Name",
+ "EMAIL;PREF=1:primaryemail@host.invalid",
+ "EMAIL:secondemail@host.invalid",
+ "NICKNAME:Nickname",
+ "NOTE:Notes line 1\\nNotes line 2\\nNotes line 3\\nNotes line 4",
+ "ORG:Organization Name;Department",
+ "TITLE:Job Title",
+ "BDAY;VALUE=DATE:19000102",
+ "N:Last;First;;;",
+ "ADR;TYPE=home:;Home Address Line 2;Home Address Line 1;Home City;Home State",
+ " ;Home Zip;Home Country",
+ "ADR;TYPE=work:;Work Address Line 2;Work Address Line 1;Work City;Work State",
+ " ;Work Zip;Work Country",
+ "TEL;TYPE=home;VALUE=TEXT:234-567-8901",
+ "TEL;TYPE=work;VALUE=TEXT:123-456-7890",
+ "TEL;TYPE=fax;VALUE=TEXT:345-678-9012",
+ "TEL;TYPE=pager;VALUE=TEXT:456-789-0123",
+ "TEL;TYPE=cell;VALUE=TEXT:567-890-1234",
+ "URL;TYPE=work;VALUE=URL:http://127.0.0.1",
+ "URL;TYPE=home;VALUE=URL:http://localhost",
+ "X-CUSTOM1;VALUE=TEXT:Custom Field 1",
+ "X-CUSTOM2;VALUE=TEXT:Custom Field 2",
+ "X-CUSTOM3;VALUE=TEXT:Custom Field 3",
+ "X-CUSTOM4;VALUE=TEXT:Custom Field 4",
+ "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ ]
+ }
+ ],
+ "bug_263304": [
+ {
+ "DisplayName": "Display Name",
+ "PrimaryEmail": "primaryemail@host.invalid",
+ "_vCard": [
+ "VERSION:4.0",
+ "FN:Display Name",
+ "EMAIL;PREF=1:primaryemail@host.invalid",
+ "URL;TYPE=work;VALUE=URL:http://127.0.0.1",
+ "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ ]
+ }
+ ],
+ "utf16_csv": [
+ {
+ "DisplayName": "John Doe",
+ "PrimaryEmail": "johndoe@host.invalid",
+ "FirstName": "John",
+ "LastName": "Doe"
+ }
+ ],
+ "shiftjis_csv": [
+ {
+ "DisplayName": "名無しの権兵衛",
+ "PrimaryEmail": "名無しの権兵衛@host.invalid"
+ }
+ ],
+ "quote_csv": [
+ {
+ "DisplayName": "Acer America",
+ "_vCard": [
+ "VERSION:4.0",
+ "FN:Acer America",
+ "ORG:Acer America;",
+ "TEL;TYPE=work;VALUE=TEXT:(800) 000-0000",
+ "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ ]
+ }
+ ],
+ "vcard_import": [
+ {
+ "DisplayName": "John Doe",
+ "FirstName": "John",
+ "LastName": "Doe",
+ "PrimaryEmail": "john.doe@genericemail.invalid"
+ },
+ {
+ "DisplayName": "Jane Doe",
+ "FirstName": "Jane",
+ "LastName": "Doe",
+ "PrimaryEmail": "jane.doe@genericemail.invalid"
+ }
+ ],
+ "dos_vcard_import": [
+ {
+ "DisplayName": "Name Surname",
+ "FirstName": "Name",
+ "LastName": "Surname",
+ "PrimaryEmail": "example@gmail.com"
+ }
+ ],
+ "csv_import": [
+ {
+ "DisplayName": "John Doe",
+ "FirstName": "John",
+ "LastName": "Doe",
+ "PrimaryEmail": "john@doe.invalid"
+ },
+ {
+ "DisplayName": "Jane Doe",
+ "FirstName": "Jane",
+ "LastName": "Doe",
+ "PrimaryEmail": "jane@doe.invalid"
+ }
+ ],
+ "becky_addressbook": [
+ {
+ "DisplayName": "The first man",
+ "PrimaryEmail": "first@host.invalid",
+ "_vCard": [
+ "VERSION:3.0",
+ "FN:The first man",
+ "ORG:Organization;Post;",
+ "X-BECKY-IMAGE:0",
+ "N:The nick name of the first man",
+ "TEL;TYPE=HOME:11-1111-1111",
+ "TEL;TYPE=WORK:22-2222-2222",
+ "TEL;TYPE=CELL:333-3333-3333",
+ "EMAIL;TYPE=INTERNET:first@host.invalid",
+ "NOTE:This is a note.",
+ "UID:4E4D17E8.0043655C"
+ ]
+ },
+ {
+ "DisplayName": "The second man",
+ "PrimaryEmail": "second@host.invalid",
+ "_vCard": [
+ "VERSION:3.0",
+ "FN:The second man",
+ "ORG:Organization;post;",
+ "X-BECKY-IMAGE:0",
+ "N:The nick name of the second man",
+ "TEL;TYPE=HOME:44-4444-4444",
+ "TEL;TYPE=WORK:55-5555-5555",
+ "TEL;TYPE=CELL:666-6666-6666",
+ "EMAIL;TYPE=INTERNET:second@host.invalid",
+ "NOTE:This is a note.",
+ "UID:4EBBF6FE.00AC632B"
+ ]
+ },
+ {
+ "DisplayName": "The third man",
+ "PrimaryEmail": "third@host.invalid",
+ "_vCard": [
+ "VERSION:3.0",
+ "FN:The third man",
+ "ORG:Organization;post;",
+ "X-BECKY-IMAGE:0",
+ "N:The third man",
+ "TEL;TYPE=HOME:77-7777-7777",
+ "TEL;TYPE=WORK:88-8888-8888",
+ "TEL;TYPE=CELL:999-9999-9999",
+ "EMAIL;TYPE=INTERNET:third@host.invalid",
+ "NOTE:This is a note.",
+ "UID:4E57AB44.0001D53E"
+ ]
+ }
+ ]
+}
diff --git a/comm/mailnews/import/test/unit/resources/basic_addressbook.csv b/comm/mailnews/import/test/unit/resources/basic_addressbook.csv
new file mode 100644
index 0000000000..5d97d36f17
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/basic_addressbook.csv
@@ -0,0 +1,2 @@
+First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes,Screen Name,
+John,Doe,John Doe,,johndoe@host.invalid,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
diff --git a/comm/mailnews/import/test/unit/resources/basic_csv_addressbook.csv b/comm/mailnews/import/test/unit/resources/basic_csv_addressbook.csv
new file mode 100644
index 0000000000..d4ecd1a308
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/basic_csv_addressbook.csv
@@ -0,0 +1,3 @@
+First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes,Screen Name
+John,Doe,John Doe,,john@doe.invalid,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+Jane,Doe,Jane Doe,,jane@doe.invalid,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
diff --git a/comm/mailnews/import/test/unit/resources/basic_ldif_addressbook.ldif b/comm/mailnews/import/test/unit/resources/basic_ldif_addressbook.ldif
new file mode 100644
index 0000000000..cf8ebab355
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/basic_ldif_addressbook.ldif
@@ -0,0 +1,45 @@
+dn: cn=Display Name,mail=primaryemail@host.invalid
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+objectclass: mozillaAbPersonAlpha
+givenName: First
+sn: Last
+cn: Display Name
+mozillaNickname: Nickname
+mail: primaryemail@host.invalid
+mozillaSecondEmail: secondemail@host.invalid
+nsAIMid: screenname
+mozillaUseHtmlMail: true
+modifytimestamp: 1213818826
+telephoneNumber: 123-456-7890
+homePhone: 234-567-8901
+fax: 345-678-9012
+pager: 456-789-0123
+mobile: 567-890-1234
+mozillaHomeStreet: Home Address Line 1
+mozillaHomeStreet2: Home Address Line 2
+mozillaHomeLocalityName: Home City
+mozillaHomeState: Home State
+mozillaHomePostalCode: Home Zip
+mozillaHomeCountryName: Home Country
+street: Work Address Line 1
+mozillaWorkStreet2: Work Address Line 2
+l: Work City
+st: Work State
+postalCode: Work Zip
+c: Work Country
+title: Job Title
+ou: Department
+o: Organization Name
+mozillaWorkUrl: http://127.0.0.1
+mozillaHomeUrl: http://localhost
+birthyear: 1900
+birthmonth: 1
+birthday: 2
+mozillaCustom1: Custom Field 1
+mozillaCustom2: Custom Field 2
+mozillaCustom3: Custom Field 3
+mozillaCustom4: Custom Field 4
+description:: Tm90ZXMgbGluZSAxCk5vdGVzIGxpbmUgMgpOb3RlcyBsaW5lIDMKTm90ZXMgbGluZSA0
diff --git a/comm/mailnews/import/test/unit/resources/basic_vcard_addressbook.vcf b/comm/mailnews/import/test/unit/resources/basic_vcard_addressbook.vcf
new file mode 100644
index 0000000000..7232bd6f23
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/basic_vcard_addressbook.vcf
@@ -0,0 +1,12 @@
+BEGIN:VCARD
+VERSION:2.1
+FN:John Doe
+N:Doe;John;;;
+EMAIL;TYPE=INTERNET:john.doe@genericemail.invalid
+END:VCARD
+BEGIN:VCARD
+VERSION:2.1
+FN:Jane Doe
+N:Doe;Jane;;;
+EMAIL;TYPE=INTERNET:jane.doe@genericemail.invalid
+END:VCARD
diff --git a/comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186e.bab b/comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186e.bab
new file mode 100644
index 0000000000..2b7e4de7e9
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186e.bab
@@ -0,0 +1,26 @@
+BEGIN:VCARD
+VERSION:3.0
+UID:4E4D17E8.0043655C
+FN:The first man
+ORG:Organization;Post;
+X-BECKY-IMAGE:0
+N:The nick name of the first man
+TEL;TYPE=HOME:11-1111-1111
+TEL;TYPE=WORK:22-2222-2222
+TEL;TYPE=CELL:333-3333-3333
+EMAIL;TYPE=INTERNET;PREF:first@host.invalid
+NOTE;ENCODING=QUOTED-PRINTABLE:This is a note.
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+UID:4EBBF6FE.00AC632B
+FN:The second man
+ORG:Organization;post;
+X-BECKY-IMAGE:0
+N:The nick name of the second man
+TEL;TYPE=HOME:44-4444-4444
+TEL;TYPE=WORK:55-5555-5555
+TEL;TYPE=CELL:666-6666-6666
+EMAIL;TYPE=INTERNET;PREF:second@host.invalid
+NOTE;ENCODING=QUOTED-PRINTABLE:This is a note.
+END:VCARD
diff --git a/comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186f.bab b/comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186f.bab
new file mode 100644
index 0000000000..13df134ef8
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/becky/addressbooks/4e4d186f.bab
@@ -0,0 +1,13 @@
+BEGIN:VCARD
+VERSION:3.0
+UID:4E57AB44.0001D53E
+FN:The third man
+ORG:Organization;post;
+X-BECKY-IMAGE:0
+N:The third man
+TEL;TYPE=HOME:77-7777-7777
+TEL;TYPE=WORK:88-8888-8888
+TEL;TYPE=CELL:999-9999-9999
+EMAIL;TYPE=INTERNET;PREF:third@host.invalid
+NOTE;ENCODING=QUOTED-PRINTABLE:This is a note.
+END:VCARD
diff --git a/comm/mailnews/import/test/unit/resources/becky/addressbooks/do_not_import_this.nobab b/comm/mailnews/import/test/unit/resources/becky/addressbooks/do_not_import_this.nobab
new file mode 100644
index 0000000000..3a49cbfbf7
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/becky/addressbooks/do_not_import_this.nobab
@@ -0,0 +1,12 @@
+BEGIN:VCARD
+UID:4E4D17E8.0043655C
+FN:Nobody
+ORG:Organization;post;
+X-BECKY-IMAGE:0
+N:Nobody
+TEL;HOME:00-0000-0000
+TEL;WORK:11-1111-1111
+TEL;CELL:090-0000-0000
+EMAIL;PREF:nobody@example.com
+NOTE;ENCODING=QUOTED-PRINTABLE:This is a note.
+END:VCARD
diff --git a/comm/mailnews/import/test/unit/resources/becky/filters/IFilter.def b/comm/mailnews/import/test/unit/resources/becky/filters/IFilter.def
new file mode 100644
index 0000000000..0777e163c1
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/becky/filters/IFilter.def
@@ -0,0 +1,23 @@
+Version=1
+AutoSorting=1
+OnlyRead=0
+OnlyOneFolder=1
+:Begin ""
+!M:11111111.mb\!!!!Inbox\Sub11_OR_12\
+@0:Subject:Subject11 O I
+@0:Subject:Subject12 O I
+$O:Sort=1
+:End ""
+:Begin ""
+!M:11111111.mb\!!!!Inbox\From11_OR_12\
+@0:From:From11@example.com O I
+@0:From:From12@example.com O I
+$O:Sort=1
+:End ""
+:Begin ""
+!M:11111111.mb\!!!!Inbox\Sub12+From11\
+@0:Subject:Subject12 O I
+@1:From:From11@example.com O I
+$O:Sort=1
+$X:disabled
+:End ""
diff --git a/comm/mailnews/import/test/unit/resources/becky/filters/OFilter.def b/comm/mailnews/import/test/unit/resources/becky/filters/OFilter.def
new file mode 100644
index 0000000000..bf7d184ff5
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/becky/filters/OFilter.def
@@ -0,0 +1,22 @@
+Version=1
+AutoSorting=1
+OnlyRead=0
+OnlyOneFolder=1
+:Begin ""
+!M:11111111.mb\!!!!Outbox\!!!Sent\Sub21_OR_22\
+@0:Subject:Subject21 O IT
+@0:Subject:Subject22 O IT
+$O:Sort=1
+:End ""
+:Begin ""
+!M:11111111.mb\!!!!Outbox\!!!Sent\To21_OR_22\
+@0:To:To21@example.com O I
+@0:To:To22@example.com O I
+$O:Sort=1
+:End ""
+:Begin ""
+!M:11111111.mb\!!!!Outbox\!!!Sent\To21\
+@0:To:To21@example.com O I
+$O:Sort=1
+$X:disabled
+:End ""
diff --git a/comm/mailnews/import/test/unit/resources/bug_263304.ldif b/comm/mailnews/import/test/unit/resources/bug_263304.ldif
new file mode 100644
index 0000000000..3e4e34ee0f
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/bug_263304.ldif
@@ -0,0 +1,7 @@
+dn: cn=Display Name,mail=primaryemail@host.invalid
+objectclass: top
+objectclass: person
+objectclass: inetOrgPerson
+cn: Display Name
+mail: primaryemail@host.invalid
+labeledURI: http://127.0.0.1 label
diff --git a/comm/mailnews/import/test/unit/resources/csv_no_header.csv b/comm/mailnews/import/test/unit/resources/csv_no_header.csv
new file mode 100644
index 0000000000..f017ec3f7d
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/csv_no_header.csv
@@ -0,0 +1,2 @@
+John Doe,John,Doe,john@doe.invalid
+Jane Doe,Jane,Doe,jane@doe.invalid
diff --git a/comm/mailnews/import/test/unit/resources/csv_semicolon.csv b/comm/mailnews/import/test/unit/resources/csv_semicolon.csv
new file mode 100644
index 0000000000..6323d439ee
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/csv_semicolon.csv
@@ -0,0 +1,3 @@
+Display Name;First Name;Last Name;Primary Email
+John Doe;John;Doe;john@doe.invalid
+Jane Doe;Jane;Doe;jane@doe.invalid
diff --git a/comm/mailnews/import/test/unit/resources/dos_vcard_addressbook.vcf b/comm/mailnews/import/test/unit/resources/dos_vcard_addressbook.vcf
new file mode 100644
index 0000000000..722bebc137
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/dos_vcard_addressbook.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Surname;Name;;;
+FN:Name Surname
+EMAIL;type=INTERNET;type=HOME:example@gmail.com
+END:VCARD
diff --git a/comm/mailnews/import/test/unit/resources/emptylines_vcard_addressbook.vcf b/comm/mailnews/import/test/unit/resources/emptylines_vcard_addressbook.vcf
new file mode 100644
index 0000000000..2f67c61dfe
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/emptylines_vcard_addressbook.vcf
@@ -0,0 +1,18 @@
+
+
+BEGIN:VCARD
+VERSION:2.1
+FN:John Doe
+N:Doe;John;;;
+EMAIL;TYPE=INTERNET:john.doe@genericemail.invalid
+END:VCARD
+
+
+BEGIN:VCARD
+VERSION:2.1
+FN:Jane Doe
+N:Doe;Jane;;;
+EMAIL;TYPE=INTERNET:jane.doe@genericemail.invalid
+END:VCARD
+
+
diff --git a/comm/mailnews/import/test/unit/resources/import_helper.js b/comm/mailnews/import/test/unit/resources/import_helper.js
new file mode 100644
index 0000000000..e689547377
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/import_helper.js
@@ -0,0 +1,665 @@
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+// used by checkProgress to periodically check the progress of the import
+var gGenericImportHelper;
+/**
+ * GenericImportHelper
+ * The parent class of AbImportHelper, MailImportHelper, SettingsImportHelper
+ * and FiltersImportHelper.
+ *
+ * @param aModuleType The type of import module. Should be addressbook or mail.
+ * @param aModuleSearchString
+ * The string to search the module names for, such as
+ * "Text file" to find the import module for comma-separated
+ * value, LDIF, and tab-delimited files.
+ * @param aFile An instance of nsIFile to import.
+ *
+ * @class
+ * @class
+ */
+function GenericImportHelper(aModuleType, aModuleSearchString, aFile) {
+ gGenericImportHelper = null;
+ if (!["addressbook", "mail", "settings", "filters"].includes(aModuleType)) {
+ do_throw("Unexpected type passed to the GenericImportHelper constructor");
+ }
+ this.mModuleType = aModuleType;
+ this.mModuleSearchString = aModuleSearchString;
+ this.mInterface = this._findInterface();
+ Assert.ok(this.mInterface !== null);
+
+ this.mFile = aFile; // checked in the beginImport method
+}
+
+GenericImportHelper.prototype = {
+ interfaceType: Ci.nsIImportGeneric,
+ /**
+ * GenericImportHelper.beginImport
+ * Imports the given address book export or mail data and invoke
+ * checkProgress of child class to check the data,
+ */
+ beginImport() {
+ Assert.ok(this.mFile instanceof Ci.nsIFile && this.mFile.exists());
+
+ if (this.mModuleType == "addressbook") {
+ this.mInterface.SetData("addressLocation", this.mFile);
+ } else if (this.mModuleType == "mail") {
+ this.mInterface.SetData("mailLocation", this.mFile);
+ }
+
+ Assert.ok(this.mInterface.WantsProgress());
+ const error = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+ Assert.ok(this.mInterface.BeginImport(null, error));
+ Assert.equal(error.data, "");
+ do_test_pending();
+ this.checkProgress();
+ },
+ /**
+ * GenericImportHelper.getInterface
+ *
+ * @returns An nsIImportGeneric import interface.
+ */
+ getInterface() {
+ return this.mInterface;
+ },
+
+ _findInterface() {
+ var importService = Cc["@mozilla.org/import/import-service;1"].getService(
+ Ci.nsIImportService
+ );
+ var count = importService.GetModuleCount(this.mModuleType);
+
+ // Iterate through each import module until the one being searched for is
+ // found and then return the ImportInterface of that module
+ for (var i = 0; i < count; i++) {
+ // Check if the current module fits the search string gets the interface
+ if (
+ importService
+ .GetModuleName(this.mModuleType, i)
+ .includes(this.mModuleSearchString)
+ ) {
+ return importService
+ .GetModule(this.mModuleType, i)
+ .GetImportInterface(this.mModuleType)
+ .QueryInterface(this.interfaceType);
+ }
+ }
+ return null; // it wasn't found
+ },
+ /**
+ * GenericImportHelper.checkProgress
+ * Checks the progress of an import every 200 milliseconds until it is
+ * complete. Checks the test results if there is an original address book,
+ * otherwise evaluates the optional command, or calls do_test_finished().
+ */
+ checkProgress() {
+ Assert.ok(
+ this.mInterface && this.mInterface instanceof Ci.nsIImportGeneric
+ );
+ Assert.ok(this.mInterface.ContinueImport());
+ // if the import isn't done, check again in 200 milliseconds.
+ if (this.mInterface.GetProgress() != 100) {
+ // use the helper object to check the progress of the import after 200 ms
+ gGenericImportHelper = this;
+ do_timeout(200, function () {
+ gGenericImportHelper.checkProgress();
+ });
+ } else {
+ // if it is done, check the results or finish the test.
+ this.checkResults();
+ do_test_finished();
+ }
+ },
+
+ /**
+ * GenericImportHelper.checkResults
+ * Checks the results of the import.
+ * Child class should implement this method.
+ */
+ checkResults() {},
+};
+
+/**
+ * AbImportHelper
+ * A helper for Address Book imports. To use, supply at least the file and type.
+ * If you would like the results checked, add a new array in the addressbook
+ * JSON file in the resources folder and supply aAbName and aJsonName.
+ * See AB_README for more information.
+ *
+ * @param aFile An instance of nsIAbFile to import.
+ * @param aModuleSearchString
+ * The string to search the module names for, such as
+ * "Text file" to find the import module for comma-separated
+ * value, LDIF, and tab-delimited files.
+ * Optional parameters: Include if you would like the import checked.
+ * @param aAbName The name the address book will have (the filename without
+ * the extension).
+ * @param aJsonName The name of the array in addressbook.json with the cards
+ * to compare with the imported cards.
+ * @class
+ * @class
+ */
+function AbImportHelper(aFile, aModuleSearchString, aAbName, aJsonName) {
+ GenericImportHelper.call(this, "addressbook", aModuleSearchString, aFile);
+
+ this.mAbName = aAbName;
+ /* Attribute notes: The attributes listed in the declaration below are
+ * supported by all three text export/import types.
+ * The following are not supported: anniversaryYear, anniversaryMonth,
+ * anniversaryDay, popularityIndex, isMailList, mailListURI, lastModifiedDate.
+ */
+ var supportedAttributes = [
+ "FirstName",
+ "LastName",
+ "DisplayName",
+ "NickName",
+ "PrimaryEmail",
+ "SecondEmail",
+ "WorkPhone",
+ "HomePhone",
+ "FaxNumber",
+ "PagerNumber",
+ "CellularNumber",
+ "HomeAddress",
+ "HomeAddress2",
+ "HomeCity",
+ "HomeState",
+ "HomeZipCode",
+ "HomeCountry",
+ "WorkAddress",
+ "WorkAddress2",
+ "WorkCity",
+ "WorkState",
+ "WorkZipCode",
+ "WorkCountry",
+ "JobTitle",
+ "Department",
+ "Company",
+ "BirthYear",
+ "BirthMonth",
+ "BirthDay",
+ "WebPage1",
+ "WebPage2",
+ "Custom1",
+ "Custom2",
+ "Custom3",
+ "Custom4",
+ "Notes",
+ "_AimScreenName",
+ "_vCard",
+ ];
+
+ // get the extra attributes supported for the given type of import
+ if (this.mFile.leafName.toLowerCase().endsWith(".ldif")) {
+ this.mSupportedAttributes = supportedAttributes;
+ } else if (this.mFile.leafName.toLowerCase().endsWith(".csv")) {
+ this.mSupportedAttributes = supportedAttributes;
+ this.setFieldMap(this.getDefaultFieldMap(true));
+ } else if (this.mFile.leafName.toLowerCase().endsWith(".vcf")) {
+ this.mSupportedAttributes = supportedAttributes;
+ }
+
+ // get the "cards" from the JSON file, if necessary
+ if (aJsonName) {
+ this.mJsonCards = this.getJsonCards(aJsonName);
+ }
+}
+
+AbImportHelper.prototype = {
+ __proto__: GenericImportHelper.prototype,
+ /**
+ * AbImportHelper.getDefaultFieldMap
+ * Returns the default field map.
+ *
+ * @param aSkipFirstRecord True if the first record of the text file should
+ * be skipped.
+ * @returns A default field map.
+ */
+ getDefaultFieldMap(aSkipFirstRecord) {
+ var importService = Cc["@mozilla.org/import/import-service;1"].getService(
+ Ci.nsIImportService
+ );
+ var fieldMap = importService.CreateNewFieldMap();
+
+ fieldMap.DefaultFieldMap(fieldMap.numMozFields);
+ this.mInterface
+ .GetData("addressInterface")
+ .QueryInterface(Ci.nsIImportAddressBooks)
+ .InitFieldMap(fieldMap);
+ fieldMap.skipFirstRecord = aSkipFirstRecord;
+
+ return fieldMap;
+ },
+
+ /**
+ * AbImportHelper.setFieldMap
+ * Set the field map.
+ *
+ * @param aFieldMap The field map used for address book import.
+ */
+ setFieldMap(aFieldMap) {
+ this.mInterface.SetData("fieldMap", aFieldMap);
+ },
+
+ /**
+ * AbImportHelper.setAddressLocation
+ * Set the the location of the address book.
+ *
+ * @param aLocation The location of the source address book.
+ */
+ setAddressBookLocation(aLocation) {
+ this.mInterface.SetData("addressLocation", aLocation);
+ },
+
+ /**
+ * AbImportHelper.setAddressDestination
+ * Set the the destination of the address book.
+ *
+ * @param aDestination URI of destination address book or null if
+ * new address books will be created.
+ */
+ setAddressDestination(aDestination) {
+ this.mInterface.SetData("addressDestination", aDestination);
+ },
+
+ /**
+ * AbImportHelper.checkResults
+ * Checks the results of the import.
+ * Ensures the an address book was created, then compares the supported
+ * attributes of each card with the card(s) in the JSON array.
+ * Calls do_test_finished() when done
+ */
+ checkResults() {
+ if (!this.mJsonCards) {
+ do_throw("The address book must be setup before checking results");
+ }
+ // When do_test_pending() was called and there is an error the test hangs.
+ // This try/catch block will catch any errors and call do_throw() with the
+ // error to throw the error and avoid the hang.
+ try {
+ // make sure an address book was created
+ var newAb = this.getAbByName(this.mAbName);
+ Assert.ok(newAb !== null);
+ Assert.ok(newAb.QueryInterface(Ci.nsIAbDirectory));
+ // get the imported card(s) and check each one
+ var count = 0;
+ for (let importedCard of newAb.childCards) {
+ this.compareCards(this.mJsonCards[count], importedCard);
+ count++;
+ }
+ // make sure there are the same number of cards in the address book and
+ // the JSON array
+ Assert.equal(count, this.mJsonCards.length);
+ do_test_finished();
+ } catch (e) {
+ do_throw(e);
+ }
+ },
+ /**
+ * AbImportHelper.getAbByName
+ * Returns the Address Book (if any) with the given name.
+ *
+ * @param aName The name of the Address Book to find.
+ * @returns An nsIAbDirectory, if found.
+ * null if the requested Address Book could not be found.
+ */
+ getAbByName(aName) {
+ Assert.ok(aName && aName.length > 0);
+
+ for (let data of MailServices.ab.directories) {
+ if (data.dirName == aName) {
+ return data;
+ }
+ }
+ return null;
+ },
+ /**
+ * AbImportHelper.compareCards
+ * Compares a JSON "card" with an imported card and throws an error if the
+ * values of a supported attribute are different.
+ *
+ * @param aJsonCard The object decoded from addressbook.json.
+ * @param aCard The imported card to compare with.
+ */
+ compareCards(aJsonCard, aCard) {
+ for (let [key, value] of Object.entries(aJsonCard)) {
+ if (!this.mSupportedAttributes.includes(key)) {
+ continue;
+ }
+ if (key == "_vCard") {
+ equal(
+ aCard
+ .getProperty(key, "")
+ .replace(
+ /UID:[a-f0-9-]{36}/i,
+ "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ ),
+ `BEGIN:VCARD\r\n${value.join("\r\n")}\r\nEND:VCARD\r\n`,
+ "_vCard should be correct"
+ );
+ } else {
+ equal(aCard.getProperty(key, ""), value, `${key} should be correct`);
+ }
+ }
+ },
+ /**
+ * AbImportHelper.getJsonCards
+ * Gets an array of "cards" from the JSON file addressbook.json located in the
+ * mailnews/import/test/resources folder. The array should contain objects
+ * with the expected properties and values of the cards in the imported
+ * address book.
+ * See addressbook.json for an example and AB_README for more details.
+ *
+ * @param aName The name of the array in addressbook.json.
+ * @returns An array of "cards".
+ */
+ getJsonCards(aName) {
+ if (!aName) {
+ do_throw("Error - getJSONAb requires an address book name");
+ }
+ var file = do_get_file("resources/addressbook.json");
+ if (!file || !file.exists() || !file.isFile()) {
+ do_throw("Unable to get JSON file");
+ }
+
+ var fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
+ Ci.nsIFileInputStream
+ );
+ fis.init(file, 0x01, 0o444, 0);
+ var istream = Cc[
+ "@mozilla.org/intl/converter-input-stream;1"
+ ].createInstance(Ci.nsIConverterInputStream);
+ var replacementChar =
+ Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
+ istream.init(fis, "UTF-8", 1024, replacementChar);
+ var json = "";
+ var str = {};
+ // get the entire file into the json string
+ while (istream.readString(4096, str) != 0) {
+ json += str.value;
+ }
+ // close the input streams
+ istream.close();
+ fis.close();
+ // decode the JSON and get the array of cards
+ var arr = JSON.parse(json)[aName];
+ Assert.ok(arr && arr.length > 0);
+ return arr;
+ },
+
+ setSupportedAttributes(attributes) {
+ this.mSupportedAttributes = attributes;
+ },
+};
+
+/**
+ * MailImportHelper
+ * A helper for mail imports.
+ *
+ * @param aFile An instance of nsIFile to import.
+ * @param aModuleSearchString
+ * The string to search the module names for, such as
+ * "Outlook Express", etc.
+ * @param aExpected An instance of nsIFile to compare with the imported
+ * folders.
+ *
+ * @class
+ * @class
+ */
+function MailImportHelper(aFile, aModuleSearchString, aExpected) {
+ GenericImportHelper.call(this, "mail", aModuleSearchString, aFile);
+ this.mExpected = aExpected;
+}
+
+MailImportHelper.prototype = {
+ __proto__: GenericImportHelper.prototype,
+ interfaceType: Ci.nsIImportGeneric,
+ _checkEqualFolder(expectedFolder, actualFolder) {
+ Assert.equal(expectedFolder.leafName, actualFolder.name);
+
+ let expectedSubFolders = [];
+ for (let entry of expectedFolder.directoryEntries) {
+ if (entry.isDirectory()) {
+ expectedSubFolders.push(entry);
+ }
+ }
+ let actualSubFolders = actualFolder.subFolders;
+ Assert.equal(expectedSubFolders.length, actualSubFolders.length);
+ for (let i = 0; i < expectedSubFolders.length; i++) {
+ this._checkEqualFolder(expectedSubFolders[i], actualSubFolders[i]);
+ }
+ },
+
+ checkResults() {
+ let rootFolder = MailServices.accounts.localFoldersServer.rootFolder;
+ Assert.ok(rootFolder.containsChildNamed(this.mFile.leafName));
+ let importedFolder = rootFolder.getChildNamed(this.mFile.leafName);
+ Assert.notEqual(importedFolder, null);
+
+ this._checkEqualFolder(this.mExpected, importedFolder);
+ },
+};
+
+/**
+ * SettingsImportHelper
+ * A helper for settings imports.
+ *
+ * @param aFile An instance of nsIFile to import, can be null.
+ * @param aModuleSearchString
+ * The string to search the module names for, such as
+ * "Outlook Express", etc.
+ * @param aExpected An array of object which has incomingServer, identity
+ * and smtpSever to compare with imported nsIMsgAccount.
+ *
+ * @class
+ * @class
+ */
+function SettingsImportHelper(aFile, aModuleSearchString, aExpected) {
+ GenericImportHelper.call(this, "settings", aModuleSearchString, aFile);
+ this.mExpected = aExpected;
+}
+
+SettingsImportHelper.prototype = {
+ __proto__: GenericImportHelper.prototype,
+ interfaceType: Ci.nsIImportSettings,
+ /**
+ * SettingsImportHelper.beginImport
+ * Imports settings from a specific file or auto-located if the file is null,
+ * and compare the import results with the expected array.
+ */
+ beginImport() {
+ this._ensureNoAccounts();
+ if (this.mFile) {
+ this.mInterface.SetLocation(this.mFile);
+ } else {
+ Assert.equal(true, this.mInterface.AutoLocate({}, {}));
+ }
+ Assert.equal(true, this.mInterface.Import({}));
+ this.checkResults();
+ },
+
+ _ensureNoAccounts() {
+ for (let account of MailServices.accounts.accounts) {
+ MailServices.accounts.removeAccount(account);
+ }
+ },
+
+ _checkSmtpServer(expected, actual) {
+ Assert.equal(expected.port, actual.port);
+ Assert.equal(expected.username, actual.username);
+ Assert.equal(expected.authMethod, actual.authMethod);
+ Assert.equal(expected.socketType, actual.socketType);
+ },
+
+ _checkIdentity(expected, actual) {
+ Assert.equal(expected.fullName, actual.fullName);
+ Assert.equal(expected.email, actual.email);
+ Assert.equal(expected.replyTo, actual.replyTo);
+ Assert.equal(expected.organization, actual.organization);
+ },
+
+ _checkPop3IncomingServer(expected, actual) {
+ Assert.equal(expected.leaveMessagesOnServer, actual.leaveMessagesOnServer);
+ Assert.equal(
+ expected.deleteMailLeftOnServer,
+ actual.deleteMailLeftOnServer
+ );
+ Assert.equal(expected.deleteByAgeFromServer, actual.deleteByAgeFromServer);
+ Assert.equal(
+ expected.numDaysToLeaveOnServer,
+ actual.numDaysToLeaveOnServer
+ );
+ },
+
+ _checkIncomingServer(expected, actual) {
+ Assert.equal(expected.type, actual.type);
+ Assert.equal(expected.port, actual.port);
+ Assert.equal(expected.username, actual.username);
+ Assert.equal(expected.isSecure, actual.isSecure);
+ Assert.equal(expected.hostName, actual.hostName);
+ Assert.equal(expected.prettyName, actual.prettyName);
+ Assert.equal(expected.authMethod, actual.authMethod);
+ Assert.equal(expected.socketType, actual.socketType);
+ Assert.equal(expected.doBiff, actual.doBiff);
+ Assert.equal(expected.biffMinutes, actual.biffMinutes);
+
+ if (expected.type == "pop3") {
+ this._checkPop3IncomingServer(
+ expected,
+ actual.QueryInterface(Ci.nsIPop3IncomingServer)
+ );
+ }
+ },
+
+ _checkAccount(expected, actual) {
+ this._checkIncomingServer(expected.incomingServer, actual.incomingServer);
+
+ Assert.equal(1, actual.identities.length);
+ let actualIdentity = actual.identities[0];
+ this._checkIdentity(expected.identity, actualIdentity);
+
+ if (expected.incomingServer.type != "nntp") {
+ let actualSmtpServer = MailServices.smtp.getServerByKey(
+ actualIdentity.smtpServerKey
+ );
+ this._checkSmtpServer(expected.smtpServer, actualSmtpServer);
+ }
+ },
+
+ _isLocalMailAccount(account) {
+ return (
+ account.incomingServer.type == "none" &&
+ account.incomingServer.username == "nobody" &&
+ account.incomingServer.hostName == "Local Folders"
+ );
+ },
+
+ _findExpectedAccount(account) {
+ return this.mExpected.filter(function (expectedAccount) {
+ return (
+ expectedAccount.incomingServer.type == account.incomingServer.type &&
+ expectedAccount.incomingServer.username ==
+ account.incomingServer.username &&
+ expectedAccount.incomingServer.hostName ==
+ account.incomingServer.hostName
+ );
+ });
+ },
+
+ checkResults() {
+ for (let actualAccount of MailServices.accounts.accounts) {
+ if (this._isLocalMailAccount(actualAccount)) {
+ continue;
+ }
+ let expectedAccounts = this._findExpectedAccount(actualAccount);
+ Assert.notEqual(null, expectedAccounts);
+ Assert.equal(1, expectedAccounts.length);
+ this._checkAccount(expectedAccounts[0], actualAccount);
+ }
+ },
+};
+
+/**
+ * FiltersImportHelper
+ * A helper for filter imports.
+ *
+ * @param aFile An instance of nsIFile to import.
+ * @param aModuleSearchString
+ * The string to search the module names for, such as
+ * "Outlook Express", etc.
+ * @param aExpected The number of filters that should exist after import.
+ *
+ * @class
+ * @class
+ */
+function FiltersImportHelper(aFile, aModuleSearchString, aExpected) {
+ GenericImportHelper.call(this, "filters", aModuleSearchString, aFile);
+ this.mExpected = aExpected;
+}
+
+FiltersImportHelper.prototype = {
+ __proto__: GenericImportHelper.prototype,
+ interfaceType: Ci.nsIImportFilters,
+
+ /**
+ * FiltersImportHelper.beginImport
+ * Imports filters from a specific file/folder or auto-located if the file is null,
+ * and compare the import results with the expected array.
+ */
+ beginImport() {
+ if (this.mFile) {
+ this.mInterface.SetLocation(this.mFile);
+ } else {
+ Assert.equal(true, this.mInterface.AutoLocate({}, {}));
+ }
+ Assert.equal(true, this.mInterface.Import({}));
+ this.checkResults();
+ },
+
+ _loopOverFilters(aFilterList, aCondition) {
+ let result = 0;
+ for (let i = 0; i < aFilterList.filterCount; i++) {
+ let filter = aFilterList.getFilterAt(i);
+ if (aCondition(filter)) {
+ result++;
+ }
+ }
+ return result;
+ },
+
+ checkResults() {
+ let expected = this.mExpected;
+ let server = MailServices.accounts.localFoldersServer;
+ let filterList = server.getFilterList(null);
+ if ("count" in expected) {
+ Assert.equal(filterList.filterCount, expected.count);
+ }
+ if ("enabled" in expected) {
+ Assert.equal(
+ this._loopOverFilters(filterList, f => f.enabled),
+ expected.enabled
+ );
+ }
+ if ("incoming" in expected) {
+ Assert.equal(
+ this._loopOverFilters(
+ filterList,
+ f => f.filterType & Ci.nsMsgFilterType.InboxRule
+ ),
+ expected.incoming
+ );
+ }
+ if ("outgoing" in expected) {
+ Assert.equal(
+ this._loopOverFilters(
+ filterList,
+ f => f.filterType & Ci.nsMsgFilterType.PostOutgoing
+ ),
+ expected.outgoing
+ );
+ }
+ },
+};
diff --git a/comm/mailnews/import/test/unit/resources/mock_windows_reg_factory.js b/comm/mailnews/import/test/unit/resources/mock_windows_reg_factory.js
new file mode 100644
index 0000000000..19583d5007
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/mock_windows_reg_factory.js
@@ -0,0 +1,84 @@
+var { MockRegistrar } = ChromeUtils.importESModule(
+ "resource://testing-common/MockRegistrar.sys.mjs"
+);
+
+var gCid;
+
+function MockWindowsRegKey(registryData) {
+ this._registryData = registryData;
+}
+
+MockWindowsRegKey.prototype = {
+ QueryInterface: ChromeUtils.generateQI(["nsIWindowsRegKey"]),
+
+ open(aRootKey, aRelPath, aMode) {
+ if (!this._registryData[aRelPath]) {
+ throw Components.Exception("", Cr.NS_ERROR_FAILURE);
+ }
+ this._keyPath = aRelPath;
+ },
+
+ close() {},
+
+ openChild(aRelPath, aMode) {
+ if (
+ !this._registryData[this._keyPath] ||
+ !this._registryData[this._keyPath][aRelPath]
+ ) {
+ throw Components.Exception("", Cr.NS_ERROR_FAILURE);
+ }
+
+ let child = new MockWindowsRegKey({});
+ let newKeyPath = this._keyPath + "\\" + aRelPath;
+ child._keyPath = newKeyPath;
+ child._registryData[newKeyPath] =
+ this._registryData[this._keyPath][aRelPath];
+ return child;
+ },
+
+ get childCount() {
+ return Object.keys(this._registryData[this._keyPath]).length;
+ },
+
+ getChildName(aIndex) {
+ let keys = Object.keys(this._registryData[this._keyPath]);
+ let keyAtIndex = keys[aIndex];
+ if (!keyAtIndex) {
+ throw Components.Exception("", Cr.NS_ERROR_FAILURE);
+ }
+
+ return keyAtIndex;
+ },
+
+ _readValue(aName) {
+ if (
+ !this._registryData[this._keyPath] ||
+ !this._registryData[this._keyPath][aName]
+ ) {
+ throw Components.Exception("", Cr.NS_ERROR_FAILURE);
+ }
+
+ return this._registryData[this._keyPath][aName];
+ },
+
+ readIntValue(aName) {
+ return this._readValue(aName);
+ },
+
+ readStringValue(aName) {
+ return this._readValue(aName);
+ },
+};
+
+/* exported setup_mock_registry, teardown_mock_registry */
+function setup_mock_registry(mockRegistry) {
+ gCid = MockRegistrar.register(
+ "@mozilla.org/windows-registry-key;1",
+ MockWindowsRegKey,
+ [mockRegistry]
+ );
+}
+
+function teardown_mock_registry() {
+ MockRegistrar.unregister(gCid);
+}
diff --git a/comm/mailnews/import/test/unit/resources/quote.csv b/comm/mailnews/import/test/unit/resources/quote.csv
new file mode 100644
index 0000000000..d508eac33c
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/quote.csv
@@ -0,0 +1,2 @@
+First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Screen Name,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes
+,,"Acer America",,,,,"(800) 000-0000","","","","","","","","","","","","","","","","",,,"Acer America",,,,,,,,,,
diff --git a/comm/mailnews/import/test/unit/resources/shiftjis_addressbook.csv b/comm/mailnews/import/test/unit/resources/shiftjis_addressbook.csv
new file mode 100644
index 0000000000..31467dd42f
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/shiftjis_addressbook.csv
@@ -0,0 +1,2 @@
+First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes,Screen Name,
+q,,̌q,,̌q@host.invalid,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
diff --git a/comm/mailnews/import/test/unit/resources/tab_comma_mixed.csv b/comm/mailnews/import/test/unit/resources/tab_comma_mixed.csv
new file mode 100644
index 0000000000..804a330e22
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/tab_comma_mixed.csv
@@ -0,0 +1,4 @@
+1,1,1,1,1@host.invalid,,,,,,,,,,,,,,,,,,,,,
+2 2 2 2 2@host.invalid
+3 3 3 3 3@host.invalid
+4 4 4 4 4@host.invalid
diff --git a/comm/mailnews/import/test/unit/resources/utf16_addressbook.csv b/comm/mailnews/import/test/unit/resources/utf16_addressbook.csv
new file mode 100644
index 0000000000..e22a64b187
--- /dev/null
+++ b/comm/mailnews/import/test/unit/resources/utf16_addressbook.csv
Binary files differ
diff --git a/comm/mailnews/import/test/unit/test_AddrBookFileImporter.js b/comm/mailnews/import/test/unit/test_AddrBookFileImporter.js
new file mode 100644
index 0000000000..2ba696d1ed
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_AddrBookFileImporter.js
@@ -0,0 +1,130 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+var { AddrBookFileImporter } = ChromeUtils.import(
+ "resource:///modules/AddrBookFileImporter.jsm"
+);
+
+/**
+ * Create a temporary address book, import a source file into it, then test the
+ * cards are correct.
+ *
+ * @param {string} type - A source file type supported by AddrBookFileImporter.
+ * @param {string} filePath - The path of a source file.
+ * @param {string} refDataKey - The key of an object in addressbook.json.
+ * @param {string[]} [csvFieldMap] - Map of CSV fields to address book fields.
+ */
+async function test_importAbFile(type, filePath, refDataKey, csvFieldMap) {
+ // Create an address book and init the importer.
+ let dirId = MailServices.ab.newAddressBook(
+ `tmp-${type}`,
+ "",
+ Ci.nsIAbManager.JS_DIRECTORY_TYPE
+ );
+ let targetDir = MailServices.ab.getDirectoryFromId(dirId);
+ let importer = new AddrBookFileImporter(type);
+
+ // Start importing.
+ let sourceFile = do_get_file(filePath);
+ if (type == "csv") {
+ let unmatched = await importer.parseCsvFile(sourceFile);
+ if (unmatched.length) {
+ importer.setCsvFields(csvFieldMap);
+ }
+ }
+ await importer.startImport(sourceFile, targetDir);
+
+ // Read in the reference data.
+ let refFile = do_get_file("resources/addressbook.json");
+ let refData = JSON.parse(await IOUtils.readUTF8(refFile.path))[refDataKey];
+
+ // Compare with the reference data.
+ for (let i = 0; i < refData.length; i++) {
+ let card = targetDir.childCards[i];
+ for (let [key, value] of Object.entries(refData[i])) {
+ if (key == "LastModifiedDate") {
+ continue;
+ }
+ if (key == "_vCard") {
+ equal(
+ card
+ .getProperty(key, "")
+ .replace(
+ /UID:[a-f0-9-]{36}/i,
+ "UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ ),
+ `BEGIN:VCARD\r\n${value.join("\r\n")}\r\nEND:VCARD\r\n`,
+ "_vCard should be correct"
+ );
+ } else {
+ equal(card.getProperty(key, ""), value, `${key} should be correct`);
+ }
+ }
+ }
+}
+
+/** Test importing .csv file works. */
+add_task(async function test_importCsvFile() {
+ // A comma separated file.
+ await test_importAbFile(
+ "csv",
+ "resources/basic_csv_addressbook.csv",
+ "csv_import"
+ );
+
+ // A semicolon separated file.
+ await test_importAbFile("csv", "resources/csv_semicolon.csv", "csv_import");
+
+ // A comma separated file without header row.
+ Services.prefs.setBoolPref("mail.import.csv.skipfirstrow", false);
+ await test_importAbFile("csv", "resources/csv_no_header.csv", "csv_import", [
+ 2, // DisplayName
+ 0, // FirstName
+ 1, // LastName
+ 4, // PrimaryEmail
+ ]);
+ Services.prefs.clearUserPref("mail.import.csv.skipfirstrow");
+
+ // A comma separated file with some fields containing quotes.
+ await test_importAbFile("csv", "resources/quote.csv", "quote_csv");
+
+ // Non-UTF8 csv file.
+ await test_importAbFile(
+ "csv",
+ "resources/shiftjis_addressbook.csv",
+ "shiftjis_csv"
+ );
+ await test_importAbFile(
+ "csv",
+ "resources/utf16_addressbook.csv",
+ "utf16_csv"
+ );
+});
+
+/** Test importing .vcf file works. */
+add_task(async function test_importVCardFile() {
+ return test_importAbFile(
+ "vcard",
+ "resources/basic_vcard_addressbook.vcf",
+ "vcard_import"
+ );
+});
+
+/** Test importing .vcf file with \r\r\n as line breaks works. */
+add_task(async function test_importDosVCardFile() {
+ return test_importAbFile(
+ "vcard",
+ "resources/dos_vcard_addressbook.vcf",
+ "dos_vcard_import"
+ );
+});
+
+/** Test importing .ldif file works. */
+add_task(async function test_importLdifFile() {
+ return test_importAbFile(
+ "ldif",
+ "resources/basic_ldif_addressbook.ldif",
+ "basic_addressbook"
+ );
+});
diff --git a/comm/mailnews/import/test/unit/test_ThunderbirdProfileImporter.js b/comm/mailnews/import/test/unit/test_ThunderbirdProfileImporter.js
new file mode 100644
index 0000000000..f89a8ca2a3
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_ThunderbirdProfileImporter.js
@@ -0,0 +1,288 @@
+/*
+ * 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 https://mozilla.org/MPL/2.0/.
+ */
+
+// It is necessary to manually disable `xpc::IsInAutomation` since
+// `resetPrefs` will flip the preference to re-enable `once`-synced
+// preference change assertions, and also change the value of those
+// preferences.
+Services.prefs.setBoolPref(
+ "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
+ false
+);
+
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+var { ThunderbirdProfileImporter } = ChromeUtils.import(
+ "resource:///modules/ThunderbirdProfileImporter.jsm"
+);
+
+let tmpProfileDir;
+registerCleanupFunction(() => {
+ tmpProfileDir?.remove(true);
+});
+
+/**
+ * Create a temporary dir to use as the source profile dir. Write a prefs.js
+ * into it.
+ *
+ * @param {Array<[string, string]>} prefs - An array of tuples, each tuple is
+ * a pref represented as [prefName, prefValue].
+ */
+async function createTmpProfileWithPrefs(prefs) {
+ tmpProfileDir?.remove(true);
+
+ // Create a temporary dir.
+ tmpProfileDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ tmpProfileDir.append("profile-tmp");
+ tmpProfileDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ info(`Created a temporary profile at ${tmpProfileDir.path}`);
+
+ // Write prefs to prefs.js.
+ let prefsFile = tmpProfileDir.clone();
+ prefsFile.append("prefs.js");
+ let prefsContent = prefs
+ .map(([name, value]) => {
+ let prefValue = typeof value == "string" ? `"${value}"` : value;
+ return `user_pref("${name}", ${prefValue});`;
+ })
+ .join("\n");
+ return IOUtils.writeUTF8(prefsFile.path, prefsContent);
+}
+
+/**
+ * Construct a temporary profile dir with prefs, import into the current
+ * profile, then check the values of prefs related to mail accounts.
+ */
+add_task(async function test_importAccountsIntoEmptyProfile() {
+ equal(
+ Services.prefs.getCharPref("mail.accountmanager.accounts"),
+ "",
+ "Should have no accounts at first"
+ );
+ let charPrefs = [
+ ["mail.smtpserver.smtp1.username", "smtp-user-1"],
+ ["mail.smtpserver.smtp3.username", "smtp-user-2"],
+ ["mail.smtpservers", "smtp1,smtp3"],
+ ["mail.identity.id1.smtpServer", "smtp3"],
+ ["mail.identity.id3.fullName", "id-name-2"],
+ ["mail.identity.id4.stmpServer", "smtp1"],
+ ["mail.server.server2.type", "none"],
+ ["mail.server.server6.type", "imap"],
+ ["mail.server.server7.type", "pop3"],
+ ["mail.account.account2.server", "server2"],
+ ["mail.account.account3.server", "server6"],
+ ["mail.account.account3.identities", "id1,id3"],
+ ["mail.account.account4.server", "server7"],
+ ["mail.accountmanager.accounts", "account3,account4,account2"],
+ ];
+ await createTmpProfileWithPrefs(charPrefs);
+
+ let importer = new ThunderbirdProfileImporter();
+
+ await importer.startImport(tmpProfileDir, importer.SUPPORTED_ITEMS);
+ // Server/identity/account keys should be changed and remapped correctly after
+ // import.
+ let expectedCharPrefs = [
+ ["mail.smtpserver.smtp1.username", "smtp-user-1"],
+ ["mail.smtpserver.smtp2.username", "smtp-user-2"],
+ ["mail.smtpservers", "smtp1,smtp2"],
+ ["mail.identity.id1.smtpServer", "smtp2"],
+ ["mail.identity.id2.fullName", "id-name-2"],
+ ["mail.identity.id3.stmpServer", "smtp1"],
+ ["mail.server.server1.type", "none"],
+ ["mail.server.server2.type", "imap"],
+ ["mail.server.server3.type", "pop3"],
+ ["mail.account.account1.server", "server1"],
+ ["mail.account.account2.server", "server2"],
+ ["mail.account.account2.identities", "id1,id2"],
+ ["mail.account.account3.server", "server3"],
+ ["mail.accountmanager.accounts", "account2,account3,account1"],
+ ];
+ for (let [name, value] of expectedCharPrefs) {
+ equal(
+ Services.prefs.getCharPref(name, ""),
+ value,
+ `${name} should be correct`
+ );
+ }
+
+ // Remove all the prefs to do the next test.
+ Services.prefs.resetPrefs();
+
+ equal(
+ Services.prefs.getCharPref("mail.accountmanager.accounts"),
+ "",
+ "Should have no accounts after resetPrefs"
+ );
+ await importer.startImport(tmpProfileDir, {
+ ...importer.SUPPORTED_ITEMS,
+ accounts: false,
+ mailMessages: false, // If true, Local Folders is created
+ });
+ equal(
+ Services.prefs.getCharPref("mail.accountmanager.accounts"),
+ "",
+ "Should still have no accounts without importing accounts"
+ );
+
+ Services.prefs.resetPrefs();
+});
+
+/**
+ * Test that importing a server without directory works. A server without
+ * directory can happen after clicking a news url.
+ */
+add_task(async function test_serverWithoutDirectory() {
+ let prefs = [
+ ["mail.server.server1.type", "nntp"],
+ ["mail.server.server1.hostname", "news.invalid"],
+ ];
+ await createTmpProfileWithPrefs(prefs);
+
+ let importer = new ThunderbirdProfileImporter();
+ await importer.startImport(tmpProfileDir, importer.SUPPORTED_ITEMS);
+ for (let [name, value] of prefs) {
+ equal(
+ Services.prefs.getCharPref(name, ""),
+ value,
+ `${name} should be correct`
+ );
+ }
+});
+
+/**
+ * Test that when the source profile and current profile each has Local Folders,
+ * the source Local Folders will be merged into the current Local Folders.
+ */
+add_task(async function test_mergeLocalFolders() {
+ let prefs = [
+ ["mail.smtpserver.smtp1.username", "smtp-user-1"],
+ ["mail.smtpservers", "smtp1"],
+ ["mail.identity.id1.smtpServer", "smtp1"],
+ ["mail.server.server2.type", "none"],
+ ["mail.server.server2.directory-rel", "[ProfD]Mail/Local Folders"],
+ ["mail.server.server2.hostname", "Local Folders"],
+ ["mail.server.server3.type", "imap"],
+ ["mail.account.account2.server", "server2"],
+ ["mail.account.account3.server", "server3"],
+ ["mail.account.account3.identities", "id1"],
+ ["mail.accountmanager.accounts", "account3,account2"],
+ ["mail.accountmanager.localfoldersserver", "server2"],
+ ];
+ await createTmpProfileWithPrefs(prefs);
+
+ // Create a physical file in tmpProfileDir.
+ let sourceLocalFolder = tmpProfileDir.clone();
+ sourceLocalFolder.append("Mail");
+ sourceLocalFolder.append("Local Folders");
+ sourceLocalFolder.append("folder-xpcshell");
+ sourceLocalFolder.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
+
+ // Create Local Folders in the current profile.
+ MailServices.accounts.createLocalMailAccount();
+
+ let importer = new ThunderbirdProfileImporter();
+ await importer.startImport(tmpProfileDir, importer.SUPPORTED_ITEMS);
+
+ // Test that sub msg folders are created in the current Local Folders.
+ let localFolders = MailServices.accounts.localFoldersServer.rootMsgFolder;
+ ok(localFolders.containsChildNamed("Local Folders"));
+ let msgFolder = localFolders.getChildNamed("Local Folders");
+ ok(msgFolder.containsChildNamed("folder-xpcshell"));
+
+ // Test that folder-xpcshell is copied into current Local Folders.
+ let importedFolder = localFolders.filePath;
+ importedFolder.append("Local Folders.sbd");
+ importedFolder.append("folder-xpcshell");
+ ok(importedFolder.exists(), "Source Local Folders should be merged in.");
+});
+
+/**
+ * Test that calendars can be correctly imported.
+ */
+add_task(async function test_importCalendars() {
+ // Set sortOrder to contain a fake calendar id.
+ Services.prefs.setCharPref("calendar.list.sortOrder", "uuid-x");
+
+ let prefs = [
+ ["calendar.registry.uuid-1.name", "Home"],
+ ["calendar.registry.uuid-1.type", "Storage"],
+ ["calendar.registry.uuid-3.name", "cal1"],
+ ["calendar.registry.uuid-3.type", "caldav"],
+ ["calendar.list.sortOrder", "uuid-1 uuid-3"],
+ ];
+
+ await createTmpProfileWithPrefs(prefs);
+
+ let importer = new ThunderbirdProfileImporter();
+
+ await importer.startImport(tmpProfileDir, { calendars: true });
+
+ // Test calendar.registry.* are imported correctly.
+ for (let [name, value] of prefs.slice(0, -1)) {
+ equal(
+ Services.prefs.getCharPref(name, ""),
+ value,
+ `${name} should be correct`
+ );
+ }
+
+ // Test calendar.list.sortOrder has merged ids.
+ equal(
+ Services.prefs.getCharPref("calendar.list.sortOrder"),
+ "uuid-x uuid-1 uuid-3",
+ "calendar.list.sortOrder should be correct"
+ );
+
+ Services.prefs.resetPrefs();
+});
+
+/**
+ * Test that tags can be correctly imported.
+ */
+add_task(async function test_importTags() {
+ let prefs = [
+ ["mailnews.tags.$label1.color", "#CC0011"],
+ ["mailnews.tags.$label1.tag", "tag1"],
+ ["mailnews.tags.$label2.color", "#CC0022"],
+ ["mailnews.tags.$label2.tag", "tag2"],
+ ];
+ await createTmpProfileWithPrefs(prefs);
+
+ let importer = new ThunderbirdProfileImporter();
+ await importer.startImport(tmpProfileDir, importer.SUPPORTED_ITEMS);
+
+ // Test mailnews.tags.* are imported because existing tags are in default state.
+ for (let [name, value] of prefs) {
+ equal(
+ Services.prefs.getCharPref(name, ""),
+ value,
+ `${name} should be correct`
+ );
+ }
+
+ let prefs2 = [
+ ["mailnews.tags.$label1.color", "#DD0011"],
+ ["mailnews.tags.$label1.tag", "tag11"],
+ ["mailnews.tags.$label2.color", "#DD0022"],
+ ["mailnews.tags.$label2.tag", "tag22"],
+ ["mailnews.tags.$tag3.color", "#DD0033"],
+ ["mailnews.tags.$tag3.tag", "tag3"],
+ ];
+ await createTmpProfileWithPrefs(prefs2);
+
+ await importer.startImport(tmpProfileDir, importer.SUPPORTED_ITEMS);
+
+ // $label1 and $label2 should not be imported, only $tag3 should be imported.
+ for (let [name, value] of [...prefs, ...prefs2.slice(4)]) {
+ equal(
+ Services.prefs.getCharPref(name, ""),
+ value,
+ `${name} should be correct`
+ );
+ }
+});
diff --git a/comm/mailnews/import/test/unit/test_becky_addressbook.js b/comm/mailnews/import/test/unit/test_becky_addressbook.js
new file mode 100644
index 0000000000..c4d4528e32
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_becky_addressbook.js
@@ -0,0 +1,59 @@
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ let file = do_get_file("resources/becky/addressbooks");
+ let helper = new AbImportHelper(
+ file,
+ "Becky!",
+ "addressbooks",
+ "becky_addressbook"
+ );
+ let vcfSupportedAttributes = [
+ "FirstName",
+ "LastName",
+ "DisplayName",
+ "NickName",
+ "PrimaryEmail",
+ "SecondEmail",
+ "WorkPhone",
+ "HomePhone",
+ "FaxNumber",
+ "PagerNumber",
+ "CellularNumber",
+ "HomeAddress",
+ "HomeAddress2",
+ "HomeCity",
+ "HomeState",
+ "HomeZipCode",
+ "HomeCountry",
+ "WorkAddress",
+ "WorkAddress2",
+ "WorkCity",
+ "WorkState",
+ "WorkZipCode",
+ "WorkCountry",
+ "JobTitle",
+ "Department",
+ "Company",
+ "BirthYear",
+ "BirthMonth",
+ "BirthDay",
+ "WebPage1",
+ "WebPage2",
+ "Custom1",
+ "Custom2",
+ "Custom3",
+ "Custom4",
+ "Notes",
+ "_AimScreenName",
+ "_vCard",
+ ];
+ helper.setSupportedAttributes(vcfSupportedAttributes);
+ helper.beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_becky_filters.js b/comm/mailnews/import/test/unit/test_becky_filters.js
new file mode 100644
index 0000000000..5af6483071
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_becky_filters.js
@@ -0,0 +1,41 @@
+const { localAccountUtils } = ChromeUtils.import(
+ "resource://testing-common/mailnews/LocalAccountUtils.jsm"
+);
+
+function run_test() {
+ localAccountUtils.loadLocalMailAccount();
+
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ // Import incoming filters.
+ let file = do_get_file("resources/becky/filters/IFilter.def");
+ let helper1 = new FiltersImportHelper(file, "Becky!", {
+ count: 3,
+ enabled: 2,
+ incoming: 3,
+ outgoing: 0,
+ });
+ helper1.beginImport();
+
+ // Import outgoing filters.
+ file = do_get_file("resources/becky/filters/OFilter.def");
+ let helper2 = new FiltersImportHelper(file, "Becky!", {
+ count: 6,
+ enabled: 4,
+ incoming: 3,
+ outgoing: 3,
+ });
+ helper2.beginImport();
+
+ // Import both filter types automatically.
+ file = do_get_file("resources/becky/filters");
+ let helper3 = new FiltersImportHelper(file, "Becky!", {
+ count: 12,
+ enabled: 8,
+ incoming: 6,
+ outgoing: 6,
+ });
+ helper3.beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_bug_263304.js b/comm/mailnews/import/test/unit/test_bug_263304.js
new file mode 100644
index 0000000000..7089c0a4c2
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_bug_263304.js
@@ -0,0 +1,25 @@
+/**
+ * Tests importing an address book export in the LDAP data interchange format
+ * (LDIF) with a labeledURI and checks the accuracy of the imported contact.
+ *
+ * This test checks for the following bug:
+ * - Bug 264405: The Address Book doesn't show the LDAP-field "labeledURI"
+ * as Website
+ */
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ var file = do_get_file("resources/bug_263304.ldif");
+ new AbImportHelper(
+ file,
+ "Text file",
+ "bug_263304",
+ "bug_263304"
+ ).beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_bug_437556.js b/comm/mailnews/import/test/unit/test_bug_437556.js
new file mode 100644
index 0000000000..284309a2dc
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_bug_437556.js
@@ -0,0 +1,23 @@
+/**
+ * Test for a regression of Bug 437556: mailnews crashes while importing an
+ * address book if a field map is required but not set.
+ */
+function run_test() {
+ var file = do_get_file("resources/basic_addressbook.csv");
+ var errorStr = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+ // get the Address Book text import interface and make sure it succeeded
+ var helper = new AbImportHelper(file, "Text file");
+ helper.setFieldMap(null);
+ helper.setAddressBookLocation(file);
+
+ var abInterface = helper.getInterface();
+ Assert.notEqual(abInterface, null);
+ // prepare to start the import
+ Assert.ok(abInterface.WantsProgress());
+ // start the import
+ // BeginImport should return false and log an error if the fieldMap isn't set
+ Assert.ok(!abInterface.BeginImport(null, errorStr));
+ Assert.notEqual(errorStr, "");
+}
diff --git a/comm/mailnews/import/test/unit/test_csv_GetSample.js b/comm/mailnews/import/test/unit/test_csv_GetSample.js
new file mode 100644
index 0000000000..3c401391e0
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_csv_GetSample.js
@@ -0,0 +1,15 @@
+function run_test() {
+ var file = do_get_file("resources/tab_comma_mixed.csv");
+ var helper = new AbImportHelper(file, "Text file");
+ var genericInterface = helper.getInterface();
+ Assert.notEqual(genericInterface, null);
+ let abInterface = genericInterface
+ .GetData("addressInterface")
+ .QueryInterface(Ci.nsIImportAddressBooks);
+ abInterface.SetSampleLocation(file);
+ let recordExists = {};
+
+ let sampleData = abInterface.GetSampleData(3, recordExists);
+ Assert.ok(recordExists.value);
+ Assert.equal(sampleData, "4\n4\n4\n4\n4@host.invalid");
+}
diff --git a/comm/mailnews/import/test/unit/test_csv_import.js b/comm/mailnews/import/test/unit/test_csv_import.js
new file mode 100644
index 0000000000..df53525de9
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_csv_import.js
@@ -0,0 +1,23 @@
+/**
+ * Tests importing an address book export in the LDAP data interchange (LDIF)
+ * format and checks the accuracy of the imported address book's cards.
+ * The current export contains only one card with most fields full.
+ *
+ * This test also checks for the following bugs:
+ * -Bug 439819: LDIF import does not include mozillahomestreet.
+ * -Bug 182128: Edit Card, Notes on several lines appear on one after
+ * export/import in text format *(only tests the import).
+ */
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ let file = do_get_file("resources/basic_csv_addressbook.csv");
+ new AbImportHelper(
+ file,
+ "csv",
+ "basic_csv_addressbook",
+ "csv_import"
+ ).beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_csv_import_quote.js b/comm/mailnews/import/test/unit/test_csv_import_quote.js
new file mode 100644
index 0000000000..67b469bac5
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_csv_import_quote.js
@@ -0,0 +1,11 @@
+/**
+ * Tests importing quoted csv address books.
+ */
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ let file = do_get_file("resources/quote.csv");
+ new AbImportHelper(file, "csv", "quote", "quote_csv").beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_ldif_import.js b/comm/mailnews/import/test/unit/test_ldif_import.js
new file mode 100644
index 0000000000..48be83c27b
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_ldif_import.js
@@ -0,0 +1,27 @@
+/**
+ * Tests importing an address book export in the LDAP data interchange (LDIF)
+ * format and checks the accuracy of the imported address book's cards.
+ * The current export contains only one card with most fields full.
+ *
+ * This test also checks for the following bugs:
+ * -Bug 439819: LDIF import does not include mozillahomestreet.
+ * -Bug 182128: Edit Card, Notes on several lines appear on one after
+ * export/import in text format *(only tests the import).
+ */
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ var file = do_get_file("resources/basic_ldif_addressbook.ldif");
+ new AbImportHelper(
+ file,
+ "Text file",
+ "basic_ldif_addressbook",
+ "basic_addressbook"
+ ).beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_outlook_settings.js b/comm/mailnews/import/test/unit/test_outlook_settings.js
new file mode 100644
index 0000000000..0f0313dcad
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_outlook_settings.js
@@ -0,0 +1,158 @@
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+/* import-globals-from resources/mock_windows_reg_factory.js */
+load("resources/mock_windows_reg_factory.js");
+
+function POP3Account() {}
+
+POP3Account.prototype = {
+ "Account Name": "POP3 Account Name",
+ "POP3 Server": "pop.host.invalid",
+ "POP3 User Name": "pop3user",
+ "Leave Mail On Server": 1,
+ "SMTP Server": "smtp.host.invalid",
+ "SMTP Display Name": "SMTP Display Name",
+ "SMTP Email Address": "pop3user@host.invalid",
+ "SMTP Reply To Email Address": "pop3user@host.invalid",
+ "SMTP Organization Name": "SMTP Organization Name",
+ "SMTP User Name": "smtpuser",
+};
+
+function IMAPAccount() {}
+
+IMAPAccount.prototype = {
+ "Account Name": "IMAP Account Name",
+ "IMAP Server": "imap.host.invalid",
+ "IMAP User Name": "imapuser",
+ "SMTP Server": "smtp.host.invalid",
+ "SMTP Display Name": "SMTP Display Name",
+ "SMTP Email Address": "imapuser@host.invalid",
+ "SMTP Reply To Email Address": "imapuser@host.invalid",
+ "SMTP Organization Name": "SMTP Organization Name",
+ "SMTP User Name": "smtpuser",
+};
+
+/* Outlook 98 */
+function Outlook98Registry(defaultAccount) {
+ this._defaultAccount = defaultAccount;
+}
+
+Outlook98Registry.prototype = {
+ get "Software\\Microsoft\\Office\\8.0\\Outlook\\OMI Account Manager"() {
+ return {
+ "Default Mail Account": "00000001",
+ "00000001": this._defaultAccount,
+ };
+ },
+};
+
+/* Outlook 2003 - */
+function Outlook2003Registry(defaultAccount) {
+ this._defaultAccount = defaultAccount;
+}
+
+Outlook2003Registry.prototype = {
+ get "Software\\Microsoft\\Office\\Outlook\\OMI Account Manager"() {
+ return {
+ "Default Mail Account": "00000001",
+ "00000001": this._defaultAccount,
+ };
+ },
+};
+
+var expectedPop3Account = {
+ incomingServer: {
+ prettyName: "POP3 Account Name",
+ type: "pop3",
+ hostName: "pop.host.invalid",
+ username: "pop3user",
+ leaveMessagesOnServer: true,
+
+ // These are account default values, not imported from Outlook.
+ // They should probably be omitted, but the check functions in
+ // import_helper.js expect to find them.
+ deleteMailLeftOnServer: false,
+ deleteByAgeFromServer: false,
+ numDaysToLeaveOnServer: 7,
+ port: 110,
+ isSecure: false,
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ socketType: Ci.nsMsgSocketType.plain,
+ doBiff: true,
+ biffMinutes: 10,
+ },
+ identity: {
+ fullName: "SMTP Display Name",
+ email: "pop3user@host.invalid",
+ replyTo: "pop3user@host.invalid",
+ organization: "SMTP Organization Name",
+ },
+ smtpServer: {
+ hostname: "smtp.host.invalid",
+ username: "smtpuser",
+ port: 0, // default port
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ socketType: Ci.nsMsgSocketType.plain,
+ },
+};
+
+var expectedImapAccount = {
+ incomingServer: {
+ prettyName: "IMAP Account Name",
+ type: "imap",
+ hostName: "imap.host.invalid",
+ username: "imapuser",
+
+ // These are account default values, not imported from Outlook.
+ // They should probably be omitted, but the check functions in
+ // import_helper.js expect to find them.
+ port: 143,
+ isSecure: false,
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ socketType: Ci.nsMsgSocketType.plain,
+ doBiff: true,
+ biffMinutes: 10,
+ },
+ identity: {
+ fullName: "SMTP Display Name",
+ email: "imapuser@host.invalid",
+ replyTo: "imapuser@host.invalid",
+ organization: "SMTP Organization Name",
+ },
+ smtpServer: {
+ hostname: "smtp.host.invalid",
+ username: "smtpuser",
+ port: 0, // default port
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ socketType: Ci.nsMsgSocketType.plain,
+ },
+};
+
+function teardown() {
+ for (let server of MailServices.smtp.servers) {
+ MailServices.smtp.deleteServer(server);
+ }
+
+ teardown_mock_registry();
+}
+
+function _test(registry, expectedAccount) {
+ try {
+ setup_mock_registry(registry);
+ new SettingsImportHelper(null, "Outlook", [expectedAccount]).beginImport();
+ } catch (e) {
+ teardown();
+ do_throw(e);
+ }
+ teardown();
+}
+
+function run_test() {
+ _test(new Outlook2003Registry(new POP3Account()), expectedPop3Account);
+ _test(new Outlook2003Registry(new IMAPAccount()), expectedImapAccount);
+
+ _test(new Outlook98Registry(new POP3Account()), expectedPop3Account);
+ _test(new Outlook98Registry(new IMAPAccount()), expectedImapAccount);
+}
diff --git a/comm/mailnews/import/test/unit/test_shiftjis_csv.js b/comm/mailnews/import/test/unit/test_shiftjis_csv.js
new file mode 100644
index 0000000000..bd4416a09a
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_shiftjis_csv.js
@@ -0,0 +1,20 @@
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ let file = do_get_file("resources/shiftjis_addressbook.csv");
+ let helper = new AbImportHelper(
+ file,
+ "csv",
+ "shiftjis_addressbook",
+ "shiftjis_csv"
+ );
+
+ helper.setFieldMap(helper.getDefaultFieldMap(true));
+ helper.beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_utf16_csv.js b/comm/mailnews/import/test/unit/test_utf16_csv.js
new file mode 100644
index 0000000000..cf64e72c0a
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_utf16_csv.js
@@ -0,0 +1,20 @@
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ let file = do_get_file("resources/utf16_addressbook.csv");
+ let helper = new AbImportHelper(
+ file,
+ "csv",
+ "utf16_addressbook",
+ "utf16_csv"
+ );
+
+ helper.setFieldMap(helper.getDefaultFieldMap(true));
+ helper.beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_vcard_import.js b/comm/mailnews/import/test/unit/test_vcard_import.js
new file mode 100644
index 0000000000..9ba0c5511a
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_vcard_import.js
@@ -0,0 +1,34 @@
+/**
+ * Tests importing an address book export in the LDAP data interchange (LDIF)
+ * format and checks the accuracy of the imported address book's cards.
+ * The current export contains only one card with most fields full.
+ *
+ * This test also checks for the following bugs:
+ * -Bug 439819: LDIF import does not include mozillahomestreet.
+ * -Bug 182128: Edit Card, Notes on several lines appear on one after
+ * export/import in text format *(only tests the import).
+ */
+function run_test() {
+ // Due to the import code using nsIAbManager off the main thread, we need
+ // to ensure that it is initialized before we start the main test.
+ MailServices.ab;
+
+ // test regular import (e.g. from file exported by another mail client)
+ let file = do_get_file("resources/basic_vcard_addressbook.vcf");
+ new AbImportHelper(
+ file,
+ "vcf",
+ "basic_vcard_addressbook",
+ "vcard_import"
+ ).beginImport();
+
+ // test import against file with extra newlines (e.g. as copy-pasted by
+ // hand, a relatively unlikely but still reasonable use case to cover)
+ file = do_get_file("resources/emptylines_vcard_addressbook.vcf");
+ new AbImportHelper(
+ file,
+ "vcf",
+ "emptylines_vcard_addressbook",
+ "vcard_import"
+ ).beginImport();
+}
diff --git a/comm/mailnews/import/test/unit/test_winmail.js b/comm/mailnews/import/test/unit/test_winmail.js
new file mode 100644
index 0000000000..73de9a1451
--- /dev/null
+++ b/comm/mailnews/import/test/unit/test_winmail.js
@@ -0,0 +1,178 @@
+/**
+ * Basic tests for importing accounts of Windows Live Mail.
+ */
+
+/* import-globals-from resources/mock_windows_reg_factory.js */
+load("resources/mock_windows_reg_factory.js");
+
+var expectedPop3TestTestAccount = {
+ incomingServer: {
+ type: "pop3",
+ hostName: "pop3.test.test",
+ prettyName: "testpopaccountname",
+ port: 110,
+ socketType: 0,
+ doBiff: true,
+ biffMinutes: 2,
+ isSecure: false,
+ username: "testpopusername",
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ leaveMessagesOnServer: false,
+ deleteMailLeftOnServer: false,
+ deleteByAgeFromServer: false,
+ numDaysToLeaveOnServer: 7,
+ },
+ identity: {
+ fullName: "popdisplayname",
+ organization: "",
+ email: "testpop@invalid.invalid",
+ },
+ smtpServer: {
+ hostname: "smtp.pop.test",
+ port: 0, // default port
+ username: "",
+ authMethod: Ci.nsMsgAuthMethod.none,
+ socketType: 0,
+ },
+};
+
+var expectedNewsMozillaOrgAccount = {
+ incomingServer: {
+ type: "nntp",
+ hostName: "testnews.mozilla.org",
+ prettyName: "accountnamemozillanews",
+ port: 119,
+ username: "",
+ socketType: 0,
+ isSecure: false,
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ doBiff: false,
+ biffMinutes: 10, // default value
+ },
+ identity: {
+ fullName: "test",
+ organization: "",
+ email: "mozillanews@invalid.invalid",
+ },
+};
+
+var expectedMicrosoftCommunitiesAccount = {
+ incomingServer: {
+ type: "nntp",
+ hostName: "testmsnews.microsoft.invalid",
+ prettyName: "Microsoft Communities Test",
+ port: 119,
+ username: "",
+ socketType: 0,
+ isSecure: false,
+ authMethod: Ci.nsMsgAuthMethod.passwordCleartext,
+ doBiff: false,
+ biffMinutes: 10, // default value
+ },
+ identity: {
+ fullName: "",
+ organization: "",
+ },
+};
+
+var expectedDonHallNntpAccount = {
+ incomingServer: {
+ type: "nntp",
+ hostName: "news.wingtiptoys.invalid",
+ prettyName: "donhallnntp",
+ port: 563,
+ username: "don",
+ isSecure: false,
+ authMethod: Ci.nsMsgAuthMethod.secure,
+ socketType: 0,
+ doBiff: false,
+ biffMinutes: 10, // default value
+ },
+ identity: {
+ fullName: "Don Hall",
+ organization: "Wingtip Toys",
+ email: "don@wingtiptoys.invalid",
+ replyTo: "don@wingtiptoys.invalid",
+ },
+};
+
+var expectedDonHallImapAccount = {
+ incomingServer: {
+ type: "imap",
+ hostName: "mail.wingtiptoys.invalid",
+ prettyName: "donhallimap",
+ port: 993,
+ isSecure: true,
+ doBiff: true,
+ biffMinutes: 2,
+ username: "don",
+ authMethod: Ci.nsMsgAuthMethod.secure,
+ socketType: Ci.nsMsgSocketType.SSL,
+ },
+ identity: {
+ fullName: "Don Hall",
+ organization: "Wingtip Toys",
+ email: "don@wingtiptoys.invalid",
+ replyTo: "don@wingtiptoys.invalid",
+ },
+ smtpServer: {
+ hostname: "smtp.wingtiptoys.invalid",
+ username: "don",
+ port: 25,
+ socketType: Ci.nsMsgSocketType.SSL,
+ authMethod: Ci.nsMsgAuthMethod.secure,
+ },
+};
+
+var expectedAccounts = [
+ expectedPop3TestTestAccount,
+ expectedNewsMozillaOrgAccount,
+ expectedMicrosoftCommunitiesAccount,
+ expectedDonHallNntpAccount,
+ expectedDonHallImapAccount,
+];
+
+function WinLiveMailRegistry(rootPath) {
+ this._rootPath = rootPath;
+}
+
+WinLiveMailRegistry.prototype = {
+ get "Software\\Microsoft\\Windows Live Mail"() {
+ return {
+ "Default Mail Account": "fill in mail account",
+ "Default News Account": "fill in news account",
+ "Store Root": this._rootPath,
+ mail: {
+ "Poll For Mail": 120000,
+ },
+ };
+ },
+};
+
+function _test(registry) {
+ try {
+ setup_mock_registry(registry);
+ new SettingsImportHelper(
+ null,
+ "Windows Live Mail",
+ expectedAccounts
+ ).beginImport();
+ } catch (e) {
+ teardown();
+ do_throw(e);
+ }
+ teardown();
+}
+
+function teardown() {
+ for (let server of MailServices.smtp.servers) {
+ MailServices.smtp.deleteServer(server);
+ }
+
+ teardown_mock_registry();
+}
+
+function run_test() {
+ let root = do_get_file("resources/WindowsLiveMail");
+ _test(new WinLiveMailRegistry(root.path));
+}
diff --git a/comm/mailnews/import/test/unit/xpcshell.ini b/comm/mailnews/import/test/unit/xpcshell.ini
new file mode 100644
index 0000000000..891ba63d96
--- /dev/null
+++ b/comm/mailnews/import/test/unit/xpcshell.ini
@@ -0,0 +1,26 @@
+[DEFAULT]
+head = head_import.js
+tail =
+support-files = resources/*
+
+[test_AddrBookFileImporter.js]
+[test_bug_263304.js]
+[test_bug_437556.js]
+[test_csv_GetSample.js]
+[test_becky_addressbook.js]
+run-if = os == 'win'
+tags = vcard
+[test_becky_filters.js]
+run-if = os == 'win'
+[test_csv_import.js]
+[test_csv_import_quote.js]
+[test_ldif_import.js]
+[test_outlook_settings.js]
+run-if = os == 'win'
+[test_shiftjis_csv.js]
+[test_ThunderbirdProfileImporter.js]
+[test_utf16_csv.js]
+[test_vcard_import.js]
+tags = vcard
+[test_winmail.js]
+run-if = os == 'win'