summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/addrbook/test/unit/test_jsaddrbook.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/addrbook/test/unit/test_jsaddrbook.js')
-rw-r--r--comm/mailnews/addrbook/test/unit/test_jsaddrbook.js420
1 files changed, 420 insertions, 0 deletions
diff --git a/comm/mailnews/addrbook/test/unit/test_jsaddrbook.js b/comm/mailnews/addrbook/test/unit/test_jsaddrbook.js
new file mode 100644
index 0000000000..957285bbba
--- /dev/null
+++ b/comm/mailnews/addrbook/test/unit/test_jsaddrbook.js
@@ -0,0 +1,420 @@
+/* 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/. */
+
+"use strict";
+
+var FILE_NAME = "abook-1.sqlite";
+var SCHEME = "jsaddrbook";
+
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+var { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+
+var book, contact, list, listCard;
+var observer = {
+ topics: [
+ "addrbook-directory-created",
+ "addrbook-directory-updated",
+ "addrbook-directory-deleted",
+ "addrbook-contact-created",
+ "addrbook-contact-updated",
+ "addrbook-contact-properties-updated",
+ "addrbook-contact-deleted",
+ "addrbook-list-created",
+ "addrbook-list-updated",
+ "addrbook-list-deleted",
+ "addrbook-list-member-added",
+ "addrbook-list-member-removed",
+ ],
+ setUp() {
+ for (let topic of this.topics) {
+ Services.obs.addObserver(observer, topic);
+ }
+ },
+ cleanUp() {
+ for (let topic of this.topics) {
+ Services.obs.removeObserver(observer, topic);
+ }
+ },
+
+ events: [],
+ observe(subject, topic, data) {
+ this.events.push([topic, subject, data]);
+ },
+ checkEvents(...events) {
+ info(
+ "Actual events: " +
+ JSON.stringify(
+ observer.events.map(e =>
+ e.map(a => {
+ if (a instanceof Ci.nsIAbDirectory) {
+ return `[nsIAbDirectory]`;
+ }
+ if (a instanceof Ci.nsIAbCard) {
+ return `[nsIAbCard]`;
+ }
+ return a;
+ })
+ )
+ )
+ );
+ equal(observer.events.length, events.length);
+
+ let actualEvents = observer.events.slice();
+ observer.events.length = 0;
+
+ for (let j = 0; j < events.length; j++) {
+ let expectedEvent = events[j];
+ let actualEvent = actualEvents[j];
+
+ for (let i = 0; i < expectedEvent.length; i++) {
+ try {
+ expectedEvent[i].QueryInterface(Ci.nsIAbCard);
+ ok(actualEvent[i].equals(expectedEvent[i]));
+ } catch (ex) {
+ if (expectedEvent[i] instanceof Ci.nsIAbDirectory) {
+ equal(actualEvent[i].UID, expectedEvent[i].UID);
+ } else if (expectedEvent[i] === null) {
+ ok(!actualEvent[i]);
+ } else if (expectedEvent[i] !== undefined) {
+ equal(actualEvent[i], expectedEvent[i]);
+ }
+ }
+ }
+ }
+
+ return actualEvents;
+ },
+};
+
+var baseAddressBookCount;
+
+add_setup(function () {
+ let profileDir = do_get_profile();
+ observer.setUp();
+
+ let dirs = MailServices.ab.directories;
+ // On Mac we might be loading the OS X Address Book. If we are, then we
+ // need to take acccount of that here, so that the test still pass on
+ // development machines.
+ if (
+ AppConstants.platform == "macosx" &&
+ dirs[0].URI == "moz-abosxdirectory:///"
+ ) {
+ equal(dirs.length, 3);
+ equal(dirs[1].fileName, kPABData.fileName);
+ equal(dirs[2].fileName, kCABData.fileName);
+ } else {
+ equal(dirs.length, 2);
+ equal(dirs[0].fileName, kPABData.fileName);
+ equal(dirs[1].fileName, kCABData.fileName);
+ }
+ // Also record the address book counts so that we get the expected counts
+ // correct further down in the test.
+ baseAddressBookCount = dirs.length;
+
+ // Check the PAB file was created.
+ let pabFile = profileDir.clone();
+ pabFile.append(kPABData.fileName);
+ ok(pabFile.exists());
+
+ // Check the CAB file was created.
+ let cabFile = profileDir.clone();
+ cabFile.append(kCABData.fileName);
+ ok(cabFile.exists());
+});
+
+add_task(async function createAddressBook() {
+ let dirPrefId = MailServices.ab.newAddressBook(
+ "new book",
+ "",
+ Ci.nsIAbManager.JS_DIRECTORY_TYPE
+ );
+ book = MailServices.ab.getDirectoryFromId(dirPrefId);
+ observer.checkEvents(["addrbook-directory-created", book]);
+
+ // Check nsIAbDirectory properties.
+ ok(!book.readOnly);
+ ok(!book.isRemote);
+ ok(!book.isSecure);
+ equal(book.dirName, "new book");
+ equal(book.dirType, Ci.nsIAbManager.JS_DIRECTORY_TYPE);
+ equal(book.fileName, FILE_NAME);
+ equal(book.UID.length, 36);
+ equal(book.URI, `${SCHEME}://${FILE_NAME}`);
+ equal(book.isMailList, false);
+ equal(book.supportsMailingLists, true);
+ equal(book.dirPrefId, "ldap_2.servers.newbook");
+
+ // Check enumerations.
+ equal(Array.from(book.childNodes).length, 0);
+ equal(Array.from(book.childCards).length, 0);
+
+ // Check prefs.
+ equal(
+ Services.prefs.getStringPref("ldap_2.servers.newbook.description"),
+ "new book"
+ );
+ equal(
+ Services.prefs.getIntPref("ldap_2.servers.newbook.dirType"),
+ Ci.nsIAbManager.JS_DIRECTORY_TYPE
+ );
+ equal(
+ Services.prefs.getStringPref("ldap_2.servers.newbook.filename"),
+ FILE_NAME
+ );
+ equal(Services.prefs.getStringPref("ldap_2.servers.newbook.uid"), book.UID);
+ equal(MailServices.ab.directories.length, baseAddressBookCount + 1);
+
+ // Check the file was created.
+ let dbFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
+ dbFile.append(FILE_NAME);
+ ok(dbFile.exists());
+});
+
+add_task(async function editAddressBook() {
+ book.dirName = "updated book";
+ observer.checkEvents(["addrbook-directory-updated", book, "DirName"]);
+ equal(book.dirName, "updated book");
+ equal(
+ Services.prefs.getStringPref("ldap_2.servers.newbook.description"),
+ "updated book"
+ );
+});
+
+add_task(async function createContact() {
+ contact = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance(
+ Ci.nsIAbCard
+ );
+ contact.displayName = "a new contact";
+ contact.firstName = "new";
+ contact.lastName = "contact";
+ contact.primaryEmail = "test@invalid";
+ contact.setProperty("Foo", "This will be deleted later.");
+ contact = book.addCard(contact);
+ observer.checkEvents(["addrbook-contact-created", contact, book.UID]);
+
+ let cards = book.childCards;
+ equal(cards.length, 1);
+ ok(cards[0].equals(contact));
+
+ // Check nsIAbCard properties.
+ equal(contact.directoryUID, book.UID);
+ equal(contact.UID.length, 36);
+ equal(contact.firstName, "new");
+ equal(contact.lastName, "contact");
+ equal(contact.displayName, "a new contact");
+ equal(contact.primaryEmail, "test@invalid");
+ equal(contact.getProperty("Foo", ""), "This will be deleted later.");
+ equal(contact.isMailList, false);
+ let modifiedDate = parseInt(contact.getProperty("LastModifiedDate", ""), 10);
+ Assert.lessOrEqual(modifiedDate, Date.now() / 1000);
+ Assert.greater(modifiedDate, Date.now() / 1000 - 10);
+
+ // Check nsIAbCard methods.
+ equal(
+ contact.generateName(Ci.nsIAbCard.GENERATE_DISPLAY_NAME),
+ "a new contact"
+ );
+ equal(
+ contact.generateName(Ci.nsIAbCard.GENERATE_LAST_FIRST_ORDER),
+ "contact, new"
+ );
+ equal(
+ contact.generateName(Ci.nsIAbCard.GENERATE_FIRST_LAST_ORDER),
+ "new contact"
+ );
+});
+
+add_task(async function editContact() {
+ contact.firstName = "updated";
+ contact.lastName = "contact";
+ contact.displayName = "updated contact";
+ contact.setProperty("Foo", null);
+ contact.setProperty("Bar1", "a new property");
+ contact.setProperty("Bar2", "");
+ contact.setProperty("LastModifiedDate", 0);
+ book.modifyCard(contact);
+ let [, propertyEvent] = observer.checkEvents(
+ ["addrbook-contact-updated", contact, book.UID],
+ ["addrbook-contact-properties-updated", contact]
+ );
+ Assert.deepEqual(JSON.parse(propertyEvent[2]), {
+ DisplayName: {
+ oldValue: "a new contact",
+ newValue: "updated contact",
+ },
+ Foo: {
+ oldValue: "This will be deleted later.",
+ newValue: null,
+ },
+ Bar1: {
+ oldValue: null,
+ newValue: "a new property",
+ },
+ FirstName: {
+ oldValue: "new",
+ newValue: "updated",
+ },
+ _vCard: {
+ oldValue: formatVCard`
+ BEGIN:VCARD
+ VERSION:4.0
+ FN:a new contact
+ EMAIL;PREF=1:test@invalid
+ N:contact;new;;;
+ UID:${contact.UID}
+ END:VCARD`,
+ newValue: formatVCard`
+ BEGIN:VCARD
+ VERSION:4.0
+ FN:updated contact
+ EMAIL;PREF=1:test@invalid
+ N:contact;updated;;;
+ UID:${contact.UID}
+ END:VCARD`,
+ },
+ });
+ contact = book.childCards[0];
+ equal(contact.firstName, "updated");
+ equal(contact.lastName, "contact");
+ equal(contact.displayName, "updated contact");
+ equal(contact.getProperty("Foo", "empty"), "empty");
+ equal(contact.getProperty("Bar1", ""), "a new property");
+ equal(contact.getProperty("Bar2", "no value"), "no value");
+ let modifiedDate = parseInt(contact.getProperty("LastModifiedDate", ""), 10);
+ Assert.lessOrEqual(modifiedDate, Date.now() / 1000);
+ Assert.greater(modifiedDate, Date.now() / 1000 - 10);
+});
+
+add_task(async function createMailingList() {
+ list = Cc["@mozilla.org/addressbook/directoryproperty;1"].createInstance(
+ Ci.nsIAbDirectory
+ );
+ list.isMailList = true;
+ list.dirName = "new list";
+ list = book.addMailList(list);
+ // Skip checking events temporarily, until listCard is defined.
+
+ // Check enumerations.
+ let childNodes = book.childNodes;
+ equal(childNodes.length, 1);
+ equal(childNodes[0].UID, list.UID); // TODO Object equality doesn't work because of XPCOM.
+ let childCards = book.childCards;
+ equal(childCards.length, 2);
+ if (childCards[0].isMailList) {
+ listCard = childCards[0];
+ ok(childCards[1].equals(contact));
+ } else {
+ ok(childCards[0].equals(contact));
+ listCard = childCards[1];
+ }
+ equal(listCard.UID, list.UID);
+
+ observer.checkEvents(["addrbook-list-created", list, book.UID]);
+
+ // Check nsIAbDirectory properties.
+ equal(list.dirName, "new list");
+ equal(list.UID.length, 36);
+ equal(list.URI, `${SCHEME}://${FILE_NAME}/${list.UID}`);
+ equal(list.isMailList, true);
+ equal(list.supportsMailingLists, false);
+
+ // Check list enumerations.
+ equal(Array.from(list.childNodes).length, 0);
+ equal(Array.from(list.childCards).length, 0);
+
+ // Check nsIAbCard properties.
+ equal(listCard.firstName, "");
+ equal(listCard.lastName, "new list");
+ equal(listCard.primaryEmail, "");
+ equal(listCard.displayName, "new list");
+});
+
+add_task(async function editMailingList() {
+ list.dirName = "updated list";
+ list.editMailListToDatabase(null);
+ observer.checkEvents(["addrbook-list-updated", list, book.UID]);
+ equal("updated list", list.dirName);
+});
+
+add_task(async function addMailingListMember() {
+ list.addCard(contact);
+ observer.checkEvents(["addrbook-list-member-added", contact, list.UID]);
+
+ // Check list enumerations.
+ equal(Array.from(list.childNodes).length, 0);
+ let childCards = list.childCards;
+ equal(childCards.length, 1);
+ ok(childCards[0].equals(contact));
+});
+
+add_task(async function removeMailingListMember() {
+ list.deleteCards([contact]);
+ observer.checkEvents(["addrbook-list-member-removed", contact, list.UID]);
+
+ // Check list enumerations.
+ equal(Array.from(list.childNodes).length, 0);
+ equal(Array.from(list.childCards).length, 0);
+});
+
+add_task(async function deleteMailingList() {
+ book.deleteDirectory(list);
+ observer.checkEvents(["addrbook-list-deleted", list, book.UID]);
+});
+
+add_task(async function deleteContact() {
+ book.deleteCards([contact]);
+ observer.checkEvents(["addrbook-contact-deleted", contact, book.UID]);
+
+ // Check enumerations.
+ equal(Array.from(book.childNodes).length, 0);
+ equal(Array.from(book.childCards).length, 0);
+});
+
+// Tests that the UID on a new contact can be set.
+add_task(async function createContactWithUID() {
+ let contactWithUID = Cc[
+ "@mozilla.org/addressbook/cardproperty;1"
+ ].createInstance(Ci.nsIAbCard);
+ contactWithUID.UID = "I'm a UID!";
+ contactWithUID = book.addCard(contactWithUID);
+ equal("I'm a UID!", contactWithUID.UID, "New contact has the UID we set");
+
+ Assert.throws(() => {
+ // Set the UID after it already exists.
+ contactWithUID.UID = "This should not be possible";
+ }, /NS_ERROR_UNEXPECTED/);
+
+ // Setting the UID to it's existing value should not fail.
+ contactWithUID.UID = contactWithUID.UID; // eslint-disable-line no-self-assign
+
+ book.deleteCards([contactWithUID]);
+ observer.events.length = 0;
+});
+
+add_task(async function deleteAddressBook() {
+ await promiseDirectoryRemoved(book.URI);
+
+ observer.checkEvents(["addrbook-directory-deleted", book, null]);
+ ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.dirType"));
+ ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.description"));
+ ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.filename"));
+ ok(!Services.prefs.prefHasUserValue("ldap_2.servers.newbook.uid"));
+ let dbFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
+ dbFile.append(FILE_NAME);
+ ok(!dbFile.exists());
+ equal(MailServices.ab.directories.length, baseAddressBookCount);
+ Assert.throws(() => {
+ MailServices.ab.getDirectory(`${SCHEME}://${FILE_NAME}`);
+ }, /NS_ERROR_FAILURE/);
+});
+
+add_task(async function cleanUp() {
+ observer.checkEvents();
+ observer.cleanUp();
+});