summaryrefslogtreecommitdiffstats
path: root/comm/mail/services/sync/test/unit
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/services/sync/test/unit')
-rw-r--r--comm/mail/services/sync/test/unit/head.js7
-rw-r--r--comm/mail/services/sync/test/unit/test_account_store.js361
-rw-r--r--comm/mail/services/sync/test/unit/test_account_tracker.js155
-rw-r--r--comm/mail/services/sync/test/unit/test_addressBook_store.js130
-rw-r--r--comm/mail/services/sync/test/unit/test_addressBook_tracker.js167
-rw-r--r--comm/mail/services/sync/test/unit/test_calendar_store.js180
-rw-r--r--comm/mail/services/sync/test/unit/test_calendar_tracker.js154
-rw-r--r--comm/mail/services/sync/test/unit/test_identity_store.js222
-rw-r--r--comm/mail/services/sync/test/unit/test_identity_tracker.js238
-rw-r--r--comm/mail/services/sync/test/unit/xpcshell.ini11
10 files changed, 1625 insertions, 0 deletions
diff --git a/comm/mail/services/sync/test/unit/head.js b/comm/mail/services/sync/test/unit/head.js
new file mode 100644
index 0000000000..8ccbe36050
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/head.js
@@ -0,0 +1,7 @@
+/* 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/. */
+
+function newUID() {
+ return Services.uuid.generateUUID().toString().substring(1, 37);
+}
diff --git a/comm/mail/services/sync/test/unit/test_account_store.js b/comm/mail/services/sync/test/unit/test_account_store.js
new file mode 100644
index 0000000000..e920ce14fe
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_account_store.js
@@ -0,0 +1,361 @@
+/* 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/. */
+
+do_get_profile();
+
+const { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+const { AccountsEngine, AccountRecord } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/accounts.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.import(
+ "resource://testing-common/TestUtils.jsm"
+);
+
+let engine, store, tracker;
+let imapAccount, imapServer, pop3Account, pop3Server, smtpServer;
+
+add_setup(async function () {
+ engine = new AccountsEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+
+ try {
+ // Ensure there is a local mail account...
+ MailServices.accounts.localFoldersServer;
+ } catch {
+ // ... if not, make one.
+ MailServices.accounts.createLocalMailAccount();
+ }
+
+ imapAccount = MailServices.accounts.createAccount();
+ imapServer = imapAccount.incomingServer =
+ MailServices.accounts.createIncomingServer("username", "hostname", "imap");
+ imapAccount.incomingServer.prettyName = "IMAP Server";
+
+ Assert.ok(imapServer.UID);
+ Assert.equal(
+ Services.prefs.getStringPref(`mail.server.${imapServer.key}.uid`),
+ imapServer.UID
+ );
+
+ pop3Account = MailServices.accounts.createAccount();
+ pop3Server = pop3Account.incomingServer =
+ MailServices.accounts.createIncomingServer("username", "hostname", "pop3");
+ pop3Account.incomingServer.prettyName = "POP3 Server";
+
+ Assert.ok(pop3Server.UID);
+ Assert.equal(
+ Services.prefs.getStringPref(`mail.server.${pop3Server.key}.uid`),
+ pop3Server.UID
+ );
+
+ smtpServer = MailServices.smtp.createServer();
+ smtpServer.username = "username";
+ smtpServer.hostname = "hostname";
+ smtpServer.description = "SMTP Server";
+
+ Assert.ok(smtpServer.UID);
+ Assert.equal(
+ Services.prefs.getStringPref(`mail.smtpserver.${smtpServer.key}.uid`, ""),
+ smtpServer.UID
+ );
+
+ // Sanity check.
+ Assert.equal(MailServices.accounts.accounts.length, 3);
+ Assert.equal(MailServices.smtp.servers.length, 1);
+});
+
+add_task(async function testGetAllIDs() {
+ Assert.deepEqual(await store.getAllIDs(), {
+ [imapServer.UID]: true,
+ [pop3Server.UID]: true,
+ [smtpServer.UID]: true,
+ });
+});
+
+add_task(async function testItemExists() {
+ Assert.equal(await store.itemExists(imapServer.UID), true);
+ Assert.equal(await store.itemExists(pop3Server.UID), true);
+ Assert.equal(await store.itemExists(smtpServer.UID), true);
+});
+
+add_task(async function testCreateIMAPRecord() {
+ let record = await store.createRecord(imapServer.UID);
+ Assert.ok(record instanceof AccountRecord);
+ Assert.equal(record.id, imapServer.UID);
+ Assert.equal(record.username, "username");
+ Assert.equal(record.hostname, "hostname");
+ Assert.equal(record.type, "imap");
+ Assert.deepEqual(record.prefs, {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 143,
+ prettyName: "IMAP Server",
+ socketType: 0,
+ });
+ Assert.equal(record.isDefault, undefined);
+});
+
+add_task(async function testCreatePOP3Record() {
+ let record = await store.createRecord(pop3Server.UID);
+ Assert.ok(record instanceof AccountRecord);
+ Assert.equal(record.id, pop3Server.UID);
+ Assert.equal(record.username, "username");
+ Assert.equal(record.hostname, "hostname");
+ Assert.equal(record.type, "pop3");
+ Assert.deepEqual(record.prefs, {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 110,
+ prettyName: "POP3 Server",
+ socketType: 0,
+ });
+ Assert.equal(record.isDefault, undefined);
+});
+
+add_task(async function testCreateSMTPRecord() {
+ let smtpServerID = smtpServer.UID;
+
+ let record = await store.createRecord(smtpServerID);
+ Assert.ok(record instanceof AccountRecord);
+ Assert.equal(record.id, smtpServerID);
+ Assert.equal(record.username, "username");
+ Assert.equal(record.hostname, "hostname");
+ Assert.equal(record.type, "smtp");
+ Assert.deepEqual(record.prefs, {
+ authMethod: 3,
+ port: 0,
+ description: "SMTP Server",
+ socketType: 0,
+ });
+ Assert.equal(record.isDefault, true);
+});
+
+add_task(async function testCreateDeletedRecord() {
+ let fakeID = "12345678-1234-1234-1234-123456789012";
+ let record = await store.createRecord(fakeID);
+ Assert.ok(record instanceof AccountRecord);
+ Assert.equal(record.id, fakeID);
+ Assert.equal(record.deleted, true);
+});
+
+add_task(async function testSyncIMAPRecords() {
+ let newID = newUID();
+ await store.applyIncoming({
+ id: newID,
+ username: "username",
+ hostname: "new.hostname",
+ type: "imap",
+ prefs: {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 143,
+ prettyName: "New IMAP Server",
+ socketType: Ci.nsMsgSocketType.plain,
+ },
+ });
+
+ Assert.equal(MailServices.accounts.accounts.length, 4);
+
+ let newServer = MailServices.accounts.allServers.find(s => s.UID == newID);
+ Assert.equal(newServer.username, "username");
+ Assert.equal(newServer.hostName, "new.hostname");
+ Assert.equal(newServer.prettyName, "New IMAP Server");
+ Assert.equal(newServer.port, 143);
+ Assert.equal(newServer.socketType, Ci.nsMsgSocketType.plain);
+
+ await store.applyIncoming({
+ id: newID,
+ username: "username",
+ hostname: "new.hostname",
+ type: "imap",
+ prefs: {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 993,
+ prettyName: "Changed IMAP Server",
+ socketType: Ci.nsMsgSocketType.SSL,
+ },
+ });
+
+ Assert.equal(newServer.prettyName, "Changed IMAP Server");
+ Assert.equal(newServer.port, 993);
+ Assert.equal(newServer.socketType, Ci.nsMsgSocketType.SSL);
+
+ await Assert.rejects(
+ store.applyIncoming({
+ id: newID,
+ type: "pop3",
+ }),
+ /Refusing to change server type/
+ );
+
+ await store.applyIncoming({
+ id: newID,
+ deleted: true,
+ });
+
+ Assert.equal(MailServices.accounts.accounts.length, 3);
+});
+
+add_task(async function testSyncPOP3Records() {
+ let newID = newUID();
+ await store.applyIncoming({
+ id: newID,
+ username: "username",
+ hostname: "new.hostname",
+ type: "pop3",
+ prefs: {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 110,
+ prettyName: "New POP3 Server",
+ socketType: Ci.nsMsgSocketType.plain,
+ },
+ });
+
+ Assert.equal(MailServices.accounts.accounts.length, 4);
+
+ let newServer = MailServices.accounts.allServers.find(s => s.UID == newID);
+ Assert.equal(newServer.username, "username");
+ Assert.equal(newServer.hostName, "new.hostname");
+ Assert.equal(newServer.prettyName, "New POP3 Server");
+ Assert.equal(newServer.port, 110);
+ Assert.equal(newServer.socketType, Ci.nsMsgSocketType.plain);
+
+ await store.applyIncoming({
+ id: newID,
+ username: "username",
+ hostname: "new.hostname",
+ type: "pop3",
+ prefs: {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 995,
+ prettyName: "Changed POP3 Server",
+ socketType: Ci.nsMsgSocketType.SSL,
+ },
+ });
+
+ Assert.equal(newServer.prettyName, "Changed POP3 Server");
+ Assert.equal(newServer.port, 995);
+ Assert.equal(newServer.socketType, Ci.nsMsgSocketType.SSL);
+
+ await Assert.rejects(
+ store.applyIncoming({
+ id: newID,
+ type: "imap",
+ }),
+ /Refusing to change server type/
+ );
+
+ await store.applyIncoming({
+ id: newID,
+ deleted: true,
+ });
+
+ Assert.equal(MailServices.accounts.accounts.length, 3);
+});
+
+add_task(async function testSyncSMTPRecords() {
+ let newSMTPServerID = newUID();
+ await store.applyIncoming({
+ id: newSMTPServerID,
+ username: "username",
+ hostname: "hostname",
+ type: "smtp",
+ prefs: {
+ authMethod: 3,
+ port: 0,
+ description: "Second Outgoing Server",
+ socketType: 0,
+ },
+ isDefault: true,
+ });
+
+ Assert.equal(MailServices.smtp.servers.length, 2);
+
+ let newSMTPServer = MailServices.smtp.servers.find(
+ s => s.UID == newSMTPServerID
+ );
+ Assert.equal(newSMTPServer.username, "username");
+ Assert.equal(newSMTPServer.hostname, "hostname");
+ Assert.equal(newSMTPServer.description, "Second Outgoing Server");
+ Assert.equal(MailServices.smtp.defaultServer.key, newSMTPServer.key);
+
+ await store.applyIncoming({
+ id: smtpServer.UID,
+ username: "username",
+ hostname: "new.hostname",
+ type: "smtp",
+ prefs: {
+ authMethod: 3,
+ port: 0,
+ description: "New SMTP Server",
+ socketType: 0,
+ },
+ isDefault: true,
+ });
+
+ Assert.equal(smtpServer.description, "New SMTP Server");
+ Assert.equal(MailServices.smtp.defaultServer.key, smtpServer.key);
+
+ // TODO test update
+
+ await store.applyIncoming({
+ id: newSMTPServerID,
+ deleted: true,
+ });
+
+ Assert.equal(MailServices.smtp.servers.length, 1);
+ Assert.equal(MailServices.smtp.servers[0].key, smtpServer.key);
+ Assert.equal(MailServices.smtp.defaultServer.key, smtpServer.key);
+});
diff --git a/comm/mail/services/sync/test/unit/test_account_tracker.js b/comm/mail/services/sync/test/unit/test_account_tracker.js
new file mode 100644
index 0000000000..98a132b48f
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_account_tracker.js
@@ -0,0 +1,155 @@
+/* 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/. */
+
+do_get_profile();
+
+const { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+const { AccountsEngine } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/accounts.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.import(
+ "resource://testing-common/TestUtils.jsm"
+);
+
+let engine, store, tracker;
+
+add_setup(async function () {
+ engine = new AccountsEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+ tracker = engine._tracker;
+
+ Assert.equal(tracker.score, 0);
+ Assert.equal(tracker._isTracking, false);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ try {
+ // Ensure there is a local mail account...
+ MailServices.accounts.localFoldersServer;
+ } catch {
+ // ... if not, make one.
+ MailServices.accounts.createLocalMailAccount();
+ }
+
+ tracker.start();
+ Assert.equal(tracker._isTracking, true);
+});
+
+/**
+ * Test creating, changing, and deleting an account that should be synced.
+ */
+add_task(async function testAccount() {
+ Assert.equal(tracker.score, 0);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ let id = newUID();
+ info(id);
+ let newAccount = MailServices.accounts.createAccount();
+ newAccount.incomingServer = MailServices.accounts.createIncomingServer(
+ "username",
+ "hostname",
+ "imap"
+ );
+ newAccount.incomingServer.UID = id;
+ newAccount.incomingServer.prettyName = "First Incoming Server";
+
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ tracker.resetScore();
+ Assert.equal(tracker.score, 0);
+
+ newAccount.incomingServer.prettyName = "Changed name";
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ MailServices.accounts.removeAccount(newAccount, true);
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+});
+
+/**
+ * Test the store methods on calendars. The tracker should ignore them.
+ */
+add_task(async function testIncomingChanges() {
+ let id = newUID();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ username: "username",
+ hostname: "new.hostname",
+ type: "imap",
+ prefs: {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 143,
+ prettyName: "New IMAP Server",
+ socketType: Ci.nsMsgSocketType.plain,
+ },
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ username: "username",
+ hostname: "new.hostname",
+ type: "imap",
+ prefs: {
+ authMethod: 3,
+ biffMinutes: 10,
+ doBiff: true,
+ downloadOnBiff: false,
+ emptyTrashOnExit: false,
+ incomingDuplicateAction: 0,
+ limitOfflineMessageSize: false,
+ loginAtStartUp: false,
+ maxMessageSize: 50,
+ port: 993,
+ prettyName: "Changed IMAP Server",
+ socketType: Ci.nsMsgSocketType.SSL,
+ },
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ deleted: true,
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+});
diff --git a/comm/mail/services/sync/test/unit/test_addressBook_store.js b/comm/mail/services/sync/test/unit/test_addressBook_store.js
new file mode 100644
index 0000000000..d32b80eac6
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_addressBook_store.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 http://mozilla.org/MPL/2.0/. */
+
+do_get_profile();
+
+const { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+const { AddressBooksEngine, AddressBookRecord } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/addressBooks.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.import(
+ "resource://testing-common/TestUtils.jsm"
+);
+const { PromiseTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/PromiseTestUtils.sys.mjs"
+);
+
+let engine, store, tracker;
+let cardDAVBook;
+
+// TODO test ldap books
+
+add_setup(async function () {
+ engine = new AddressBooksEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+
+ let dirPrefId = MailServices.ab.newAddressBook(
+ "Sync Address Book",
+ null,
+ MailServices.ab.CARDDAV_DIRECTORY_TYPE
+ );
+ cardDAVBook = MailServices.ab.getDirectoryFromId(dirPrefId);
+ cardDAVBook.setStringValue("carddav.url", "https://localhost:1234/a/book");
+});
+
+add_task(async function testGetAllIDs() {
+ Assert.deepEqual(await store.getAllIDs(), {
+ [cardDAVBook.UID]: true,
+ });
+});
+
+add_task(async function testItemExists() {
+ Assert.equal(await store.itemExists(cardDAVBook.UID), true);
+});
+
+add_task(async function testCreateRecord() {
+ let record = await store.createRecord(cardDAVBook.UID);
+ Assert.ok(record instanceof AddressBookRecord);
+ Assert.equal(record.id, cardDAVBook.UID);
+ Assert.equal(record.name, "Sync Address Book");
+ Assert.equal(record.type, MailServices.ab.CARDDAV_DIRECTORY_TYPE);
+ Assert.deepEqual(record.prefs, { url: "https://localhost:1234/a/book" });
+});
+
+add_task(async function testCreateDeletedRecord() {
+ let fakeID = "12345678-1234-1234-1234-123456789012";
+ let record = await store.createRecord(fakeID);
+ Assert.ok(record instanceof AddressBookRecord);
+ Assert.equal(record.id, fakeID);
+ Assert.equal(record.deleted, true);
+});
+
+add_task(async function testSyncRecords() {
+ Assert.equal(MailServices.ab.directories.length, 3);
+ PromiseTestUtils.expectUncaughtRejection(/Connection failure/);
+
+ let newID = newUID();
+ await store.applyIncoming({
+ id: newID,
+ name: "bar",
+ type: MailServices.ab.CARDDAV_DIRECTORY_TYPE,
+ prefs: {
+ url: "https://localhost/",
+ syncInterval: 0,
+ username: "username",
+ },
+ });
+ Services.obs.notifyObservers(null, "weave:service:sync:finish");
+
+ Assert.equal(MailServices.ab.directories.length, 4);
+ let newBook = MailServices.ab.getDirectoryFromUID(newID);
+ Assert.equal(newBook.dirName, "bar");
+ Assert.equal(newBook.dirType, MailServices.ab.CARDDAV_DIRECTORY_TYPE);
+ Assert.equal(
+ newBook.getStringValue("carddav.url", null),
+ "https://localhost/"
+ );
+ Assert.equal(newBook.getIntValue("carddav.syncinterval", null), 0);
+ Assert.equal(newBook.getStringValue("carddav.username", null), "username");
+
+ await store.applyIncoming({
+ id: newID,
+ name: "bar!",
+ type: MailServices.ab.CARDDAV_DIRECTORY_TYPE,
+ prefs: {
+ url: "https://localhost/",
+ syncInterval: 30,
+ username: "username@localhost",
+ },
+ });
+
+ Assert.equal(MailServices.ab.directories.length, 4);
+ newBook = MailServices.ab.getDirectoryFromUID(newID);
+ Assert.equal(newBook.dirName, "bar!");
+ Assert.equal(newBook.dirType, MailServices.ab.CARDDAV_DIRECTORY_TYPE);
+ Assert.equal(
+ newBook.getStringValue("carddav.url", null),
+ "https://localhost/"
+ );
+ Assert.equal(newBook.getIntValue("carddav.syncinterval", null), 30);
+ Assert.equal(
+ newBook.getStringValue("carddav.username", null),
+ "username@localhost"
+ );
+
+ await store.applyIncoming({
+ id: newID,
+ deleted: true,
+ });
+
+ Assert.equal(MailServices.ab.directories.length, 3);
+ newBook = MailServices.ab.getDirectoryFromUID(newID);
+ Assert.equal(newBook, null);
+});
diff --git a/comm/mail/services/sync/test/unit/test_addressBook_tracker.js b/comm/mail/services/sync/test/unit/test_addressBook_tracker.js
new file mode 100644
index 0000000000..9831252fb6
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_addressBook_tracker.js
@@ -0,0 +1,167 @@
+/* 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/. */
+
+do_get_profile();
+
+const { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+const { AddressBooksEngine } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/addressBooks.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.import(
+ "resource://testing-common/TestUtils.jsm"
+);
+const { PromiseTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/PromiseTestUtils.sys.mjs"
+);
+
+let engine, store, tracker;
+
+add_setup(async function () {
+ engine = new AddressBooksEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+ tracker = engine._tracker;
+
+ Assert.equal(tracker.score, 0);
+ Assert.equal(tracker._isTracking, false);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ tracker.start();
+ Assert.equal(tracker._isTracking, true);
+});
+
+/**
+ * Test creating, changing, and deleting an address book that should be synced.
+ */
+add_task(async function testNetworkAddressBook() {
+ Assert.equal(tracker.score, 0);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ let id = newUID();
+ let dirPrefId = MailServices.ab.newAddressBook(
+ "Sync Address Book",
+ null,
+ MailServices.ab.CARDDAV_DIRECTORY_TYPE,
+ id
+ );
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ tracker.resetScore();
+ Assert.equal(tracker.score, 0);
+
+ let book = MailServices.ab.getDirectoryFromId(dirPrefId);
+ book.dirName = "changed name";
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ book.setIntValue("carddav.syncinterval", 0);
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ book.setStringValue("carddav.url", "https://localhost/");
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ let deletedPromise = TestUtils.topicObserved("addrbook-directory-deleted");
+ MailServices.ab.deleteAddressBook(book.URI);
+ await deletedPromise;
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+});
+
+/**
+ * Test a local address book. This shouldn't affect the tracker at all.
+ */
+add_task(async function testStorageAddressBook() {
+ let dirPrefId = MailServices.ab.newAddressBook(
+ "Sync Address Book",
+ null,
+ MailServices.ab.JS_DIRECTORY_TYPE
+ );
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ let book = MailServices.ab.getDirectoryFromId(dirPrefId);
+ book.dirName = "changed name";
+ book.setBoolValue("readOnly", true);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ let deletedPromise = TestUtils.topicObserved("addrbook-directory-deleted");
+ MailServices.ab.deleteAddressBook(book.URI);
+ await deletedPromise;
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+});
+
+/**
+ * Test the store methods on address books. The tracker should ignore them.
+ */
+add_task(async function testIncomingChanges() {
+ PromiseTestUtils.expectUncaughtRejection(/Connection failure/);
+
+ let id = newUID();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ name: "New Book",
+ type: MailServices.ab.CARDDAV_DIRECTORY_TYPE,
+ prefs: {
+ url: "https://localhost/",
+ syncInterval: 0,
+ username: "username",
+ },
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ name: "New Book (changed)!",
+ type: MailServices.ab.CARDDAV_DIRECTORY_TYPE,
+ prefs: {
+ url: "https://localhost/",
+ syncInterval: 30,
+ username: "username@localhost",
+ },
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ deleted: true,
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+});
diff --git a/comm/mail/services/sync/test/unit/test_calendar_store.js b/comm/mail/services/sync/test/unit/test_calendar_store.js
new file mode 100644
index 0000000000..41dd01c22a
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_calendar_store.js
@@ -0,0 +1,180 @@
+/* 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/. */
+
+do_get_profile();
+
+const { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm");
+const { CalendarsEngine, CalendarRecord } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/calendars.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+
+let engine, store, tracker;
+let calDAVCalendar, icsCalendar, fileICSCalendar, storageCalendar;
+
+// TODO test caldav calendars
+
+add_setup(async function () {
+ await new Promise(resolve => cal.manager.startup({ onResult: resolve }));
+
+ engine = new CalendarsEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+
+ calDAVCalendar = cal.manager.createCalendar(
+ "caldav",
+ Services.io.newURI("https://localhost/caldav")
+ );
+ calDAVCalendar.name = "CalDAV Calendar";
+ cal.manager.registerCalendar(calDAVCalendar);
+
+ icsCalendar = cal.manager.createCalendar(
+ "ics",
+ Services.io.newURI("https://localhost/ics")
+ );
+ icsCalendar.name = "ICS Calendar";
+ cal.manager.registerCalendar(icsCalendar);
+
+ fileICSCalendar = cal.manager.createCalendar(
+ "ics",
+ Services.io.newURI("file:///home/user/test.ics")
+ );
+ fileICSCalendar.name = "File ICS Calendar";
+ cal.manager.registerCalendar(fileICSCalendar);
+
+ storageCalendar = cal.manager.createCalendar(
+ "storage",
+ Services.io.newURI("moz-storage-calendar://")
+ );
+ storageCalendar.name = "Storage Calendar";
+ cal.manager.registerCalendar(storageCalendar);
+});
+
+add_task(async function testGetAllIDs() {
+ Assert.deepEqual(await store.getAllIDs(), {
+ [calDAVCalendar.id]: true,
+ [icsCalendar.id]: true,
+ });
+});
+
+add_task(async function testItemExists() {
+ Assert.equal(await store.itemExists(calDAVCalendar.id), true);
+ Assert.equal(await store.itemExists(icsCalendar.id), true);
+});
+
+add_task(async function testCreateCalDAVRecord() {
+ let record = await store.createRecord(calDAVCalendar.id);
+ Assert.ok(record instanceof CalendarRecord);
+ Assert.equal(record.id, calDAVCalendar.id);
+ Assert.equal(record.name, "CalDAV Calendar");
+ Assert.equal(record.type, "caldav");
+ Assert.equal(record.uri, "https://localhost/caldav");
+ Assert.deepEqual(record.prefs, {});
+});
+
+add_task(async function testCreateICSRecord() {
+ let record = await store.createRecord(icsCalendar.id);
+ Assert.ok(record instanceof CalendarRecord);
+ Assert.equal(record.id, icsCalendar.id);
+ Assert.equal(record.name, "ICS Calendar");
+ Assert.equal(record.type, "ics");
+ Assert.equal(record.uri, "https://localhost/ics");
+ Assert.deepEqual(record.prefs, {});
+});
+
+add_task(async function testCreateDeletedRecord() {
+ let fakeID = "12345678-1234-1234-1234-123456789012";
+ let record = await store.createRecord(fakeID);
+ Assert.ok(record instanceof CalendarRecord);
+ Assert.equal(record.id, fakeID);
+ Assert.equal(record.deleted, true);
+});
+
+add_task(async function testSyncRecords() {
+ // Sync a new calendar.
+
+ let newID = newUID();
+ await store.applyIncoming({
+ id: newID,
+ name: "New ICS Calendar",
+ type: "ics",
+ uri: "https://localhost/newICS",
+ prefs: {
+ color: "#abcdef",
+ },
+ });
+
+ Assert.equal(cal.manager.getCalendars().length, 5);
+ let calendar = cal.manager.getCalendarById(newID);
+ Assert.equal(calendar.id, newID);
+ Assert.equal(calendar.name, "New ICS Calendar");
+ Assert.equal(calendar.type, "ics");
+ Assert.equal(calendar.uri.spec, "https://localhost/newICS");
+ Assert.equal(calendar.getProperty("color"), "#abcdef");
+
+ // Change the name and some properties.
+
+ await store.applyIncoming({
+ id: newID,
+ name: "Changed ICS Calendar",
+ type: "ics",
+ uri: "https://localhost/changedICS",
+ prefs: {
+ color: "#123456",
+ readOnly: true,
+ },
+ });
+
+ Assert.equal(cal.manager.getCalendars().length, 5);
+ calendar = cal.manager.getCalendarById(newID);
+ Assert.equal(calendar.name, "Changed ICS Calendar");
+ Assert.equal(calendar.type, "ics");
+ Assert.equal(calendar.uri.spec, "https://localhost/changedICS");
+ Assert.equal(calendar.getProperty("color"), "#123456");
+ Assert.equal(calendar.getProperty("readOnly"), true);
+
+ // Change the calendar type. This should fail.
+
+ await Assert.rejects(
+ store.applyIncoming({
+ id: newID,
+ name: "New CalDAV Calendar",
+ type: "caldav",
+ uri: "https://localhost/caldav",
+ prefs: {
+ color: "#123456",
+ readOnly: true,
+ },
+ }),
+ /Refusing to change calendar type/
+ );
+
+ // Enable the cache. This should fail.
+
+ await Assert.rejects(
+ store.applyIncoming({
+ id: newID,
+ name: "Changed ICS Calendar",
+ type: "ics",
+ uri: "https://localhost/changedICS",
+ prefs: {
+ cacheEnabled: true,
+ color: "#123456",
+ readOnly: true,
+ },
+ }),
+ /Refusing to change the cache setting/
+ );
+
+ await store.applyIncoming({
+ id: newID,
+ deleted: true,
+ });
+
+ Assert.equal(cal.manager.getCalendars().length, 4);
+ calendar = cal.manager.getCalendarById(newID);
+ Assert.equal(calendar, null);
+});
diff --git a/comm/mail/services/sync/test/unit/test_calendar_tracker.js b/comm/mail/services/sync/test/unit/test_calendar_tracker.js
new file mode 100644
index 0000000000..042f5782aa
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_calendar_tracker.js
@@ -0,0 +1,154 @@
+/* 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/. */
+
+do_get_profile();
+
+const { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm");
+const { CalendarsEngine } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/calendars.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+
+let engine, store, tracker;
+
+add_setup(async function () {
+ await new Promise(resolve => cal.manager.startup({ onResult: resolve }));
+ cal.manager.getCalendars();
+
+ engine = new CalendarsEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+ tracker = engine._tracker;
+
+ Assert.equal(tracker.score, 0);
+ Assert.equal(tracker._isTracking, false);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ tracker.start();
+ Assert.equal(tracker._isTracking, true);
+});
+
+/**
+ * Test creating, changing, and deleting a calendar that should be synced.
+ */
+add_task(async function testNetworkCalendar() {
+ Assert.equal(tracker.score, 0);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ let id = newUID();
+ let calendar = cal.manager.createCalendar(
+ "ics",
+ Services.io.newURI("https://localhost:1234/a/calendar")
+ );
+ calendar.name = "Sync Calendar";
+ calendar.id = id;
+ cal.manager.registerCalendar(calendar);
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ tracker.resetScore();
+ Assert.equal(tracker.score, 0);
+
+ calendar.name = "changed name";
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ calendar.setProperty("color", "#123456");
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ calendar.setProperty("calendar-main-in-composite", true);
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ cal.manager.unregisterCalendar(calendar);
+ cal.manager.removeCalendar(calendar);
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+});
+
+/**
+ * Test a storage calendar. This shouldn't affect the tracker at all.
+ */
+add_task(async function testStorageCalendar() {
+ let storageCalendar = cal.manager.createCalendar(
+ "storage",
+ Services.io.newURI("moz-storage-calendar://")
+ );
+ storageCalendar.name = "Sync Calendar";
+ storageCalendar.id = newUID();
+ cal.manager.registerCalendar(storageCalendar);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ storageCalendar.name = "changed name";
+ storageCalendar.setProperty("color", "#123456");
+ storageCalendar.setProperty("calendar-main-in-composite", true);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ cal.manager.unregisterCalendar(storageCalendar);
+ cal.manager.removeCalendar(storageCalendar);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+});
+
+/**
+ * Test the store methods on calendars. The tracker should ignore them.
+ */
+add_task(async function testIncomingChanges() {
+ let id = newUID();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ name: "New Calendar",
+ type: "ics",
+ uri: "https://localhost/ics",
+ prefs: {},
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ name: "New Calendar (changed)",
+ type: "ics",
+ uri: "https://localhost/ics",
+ prefs: {},
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ deleted: true,
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+});
diff --git a/comm/mail/services/sync/test/unit/test_identity_store.js b/comm/mail/services/sync/test/unit/test_identity_store.js
new file mode 100644
index 0000000000..42d4a0f356
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_identity_store.js
@@ -0,0 +1,222 @@
+/* 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/. */
+
+do_get_profile();
+
+const { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+const { IdentitiesEngine, IdentityRecord } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/identities.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.import(
+ "resource://testing-common/TestUtils.jsm"
+);
+
+let engine, store, tracker;
+let accountA, smtpServerA, identityA;
+let accountB, identityB;
+
+add_setup(async function () {
+ engine = new IdentitiesEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+
+ try {
+ // Ensure there is a local mail account...
+ MailServices.accounts.localFoldersServer;
+ } catch {
+ // ... if not, make one.
+ MailServices.accounts.createLocalMailAccount();
+ }
+
+ // Mail account and identity.
+
+ accountA = MailServices.accounts.createAccount();
+ accountA.incomingServer = MailServices.accounts.createIncomingServer(
+ "username",
+ "hostname",
+ "imap"
+ );
+ smtpServerA = MailServices.smtp.createServer();
+
+ identityA = MailServices.accounts.createIdentity();
+ identityA.email = "username@hostname";
+ identityA.fullName = "User";
+ identityA.smtpServerKey = smtpServerA.key;
+ accountA.addIdentity(identityA);
+
+ Assert.ok(identityA.UID);
+ Assert.equal(
+ Services.prefs.getStringPref(`mail.identity.${identityA.key}.uid`),
+ identityA.UID
+ );
+
+ // NNTP account and identity. NNTP isn't currently supported, so this test
+ // will prove the identity isn't synced.
+
+ accountB = MailServices.accounts.createAccount();
+ accountB.incomingServer = MailServices.accounts.createIncomingServer(
+ "username",
+ "hostname",
+ "nntp"
+ );
+
+ identityB = MailServices.accounts.createIdentity();
+ identityB.email = "username@hostname";
+ identityB.fullName = "user";
+ accountB.addIdentity(identityB);
+
+ // Sanity check.
+
+ Assert.equal(MailServices.accounts.allIdentities.length, 2);
+ Assert.equal(accountA.identities.length, 1);
+ Assert.equal(accountA.defaultIdentity.key, identityA.key);
+ Assert.equal(accountB.identities.length, 1);
+ Assert.equal(accountB.defaultIdentity.key, identityB.key);
+});
+
+add_task(async function testGetAllIDs() {
+ Assert.deepEqual(await store.getAllIDs(), {
+ [identityA.UID]: true,
+ });
+});
+
+add_task(async function testItemExists() {
+ Assert.equal(await store.itemExists(identityA.UID), true);
+});
+
+add_task(async function testCreateRecord() {
+ let record = await store.createRecord(identityA.UID);
+ Assert.ok(record instanceof IdentityRecord);
+ Assert.equal(record.id, identityA.UID);
+ Assert.deepEqual(record.accounts, [
+ {
+ id: accountA.incomingServer.UID,
+ isDefault: true,
+ },
+ ]);
+ Assert.deepEqual(record.prefs, {
+ attachSignature: false,
+ attachVCard: false,
+ autoQuote: true,
+ catchAll: false,
+ catchAllHint: null,
+ composeHtml: true,
+ email: "username@hostname",
+ escapedVCard: null,
+ fullName: "User",
+ htmlSigFormat: false,
+ htmlSigText: "",
+ label: "",
+ organization: "",
+ replyOnTop: 0,
+ replyTo: null,
+ sigBottom: true,
+ sigOnForward: false,
+ sigOnReply: true,
+ });
+ Assert.equal(record.smtpID, smtpServerA.UID);
+});
+
+add_task(async function testCreateDeletedRecord() {
+ let fakeID = "12345678-1234-1234-1234-123456789012";
+ let record = await store.createRecord(fakeID);
+ Assert.ok(record instanceof IdentityRecord);
+ Assert.equal(record.id, fakeID);
+ Assert.equal(record.deleted, true);
+});
+
+add_task(async function testSyncRecords() {
+ let newIdentityID = newUID();
+ await store.applyIncoming({
+ id: newIdentityID,
+ accounts: [
+ {
+ id: accountA.incomingServer.UID,
+ isDefault: false,
+ },
+ ],
+ prefs: {
+ attachSignature: false,
+ attachVCard: false,
+ autoQuote: true,
+ catchAll: false,
+ catchAllHint: null,
+ composeHtml: true,
+ email: "username@hostname",
+ escapedVCard: null,
+ fullName: "User",
+ htmlSigFormat: false,
+ htmlSigText: "",
+ label: "",
+ organization: "",
+ replyOnTop: 0,
+ replyTo: null,
+ sigBottom: true,
+ sigOnForward: false,
+ sigOnReply: true,
+ },
+ smtpID: smtpServerA.UID,
+ });
+
+ Assert.equal(MailServices.accounts.allIdentities.length, 3);
+ Assert.equal(accountA.identities.length, 2);
+
+ let newIdentity = MailServices.accounts.allIdentities.find(
+ i => i.UID == newIdentityID
+ );
+ Assert.equal(newIdentity.email, "username@hostname");
+ Assert.equal(newIdentity.fullName, "User");
+ Assert.equal(newIdentity.smtpServerKey, smtpServerA.key);
+ Assert.equal(accountA.defaultIdentity.key, identityA.key);
+
+ await store.applyIncoming({
+ id: newIdentityID,
+ accounts: [
+ {
+ id: accountA.incomingServer.UID,
+ isDefault: true,
+ },
+ ],
+ prefs: {
+ attachSignature: false,
+ attachVCard: false,
+ autoQuote: true,
+ catchAll: false,
+ catchAllHint: null,
+ composeHtml: true,
+ email: "username@hostname",
+ escapedVCard: null,
+ fullName: "User (changed)",
+ htmlSigFormat: false,
+ htmlSigText: "",
+ label: "",
+ organization: "",
+ replyOnTop: 0,
+ replyTo: null,
+ sigBottom: true,
+ sigOnForward: false,
+ sigOnReply: true,
+ },
+ smtpID: smtpServerA.UID,
+ });
+
+ Assert.equal(newIdentity.fullName, "User (changed)");
+ Assert.equal(accountA.defaultIdentity.key, newIdentity.key);
+
+ await store.applyIncoming({
+ id: newIdentityID,
+ deleted: true,
+ });
+
+ Assert.equal(MailServices.accounts.allIdentities.length, 2);
+ Assert.equal(accountA.identities.length, 1);
+ Assert.equal(accountA.defaultIdentity.key, identityA.key);
+ Assert.equal(accountB.identities.length, 1);
+ Assert.equal(accountB.defaultIdentity.key, identityB.key);
+});
diff --git a/comm/mail/services/sync/test/unit/test_identity_tracker.js b/comm/mail/services/sync/test/unit/test_identity_tracker.js
new file mode 100644
index 0000000000..eda39a1794
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/test_identity_tracker.js
@@ -0,0 +1,238 @@
+/* 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/. */
+
+do_get_profile();
+
+const { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+const { IdentitiesEngine } = ChromeUtils.importESModule(
+ "resource://services-sync/engines/identities.sys.mjs"
+);
+const { Service } = ChromeUtils.importESModule(
+ "resource://services-sync/service.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.import(
+ "resource://testing-common/TestUtils.jsm"
+);
+
+let engine, store, tracker;
+let accountA, smtpServerA, smtpServerB, identityA, identityB;
+
+add_setup(async function () {
+ engine = new IdentitiesEngine(Service);
+ await engine.initialize();
+ store = engine._store;
+ tracker = engine._tracker;
+
+ Assert.equal(tracker.score, 0);
+ Assert.equal(tracker._isTracking, false);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ try {
+ // Ensure there is a local mail account...
+ MailServices.accounts.localFoldersServer;
+ } catch {
+ // ... if not, make one.
+ MailServices.accounts.createLocalMailAccount();
+ }
+
+ accountA = MailServices.accounts.createAccount();
+ accountA.incomingServer = MailServices.accounts.createIncomingServer(
+ "username",
+ "hostname",
+ "imap"
+ );
+ smtpServerA = MailServices.smtp.createServer();
+ smtpServerB = MailServices.smtp.createServer();
+
+ identityA = MailServices.accounts.createIdentity();
+ identityA.email = "identity.a@hostname";
+ identityA.fullName = "Identity A";
+ identityA.smtpServerKey = smtpServerA.key;
+ accountA.addIdentity(identityA);
+
+ identityB = MailServices.accounts.createIdentity();
+ identityB.email = "identity.b@hostname";
+ identityB.fullName = "Identity B";
+ identityB.smtpServerKey = smtpServerB.key;
+ accountA.addIdentity(identityB);
+
+ Assert.equal(MailServices.accounts.allIdentities.length, 2);
+ Assert.equal(accountA.identities.length, 2);
+ Assert.equal(accountA.defaultIdentity.key, identityA.key);
+
+ tracker.start();
+ Assert.equal(tracker._isTracking, true);
+});
+
+/**
+ * Test creating, changing, and deleting an identity that should be synced.
+ */
+add_task(async function testIdentity() {
+ Assert.equal(tracker.score, 0);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ let id = newUID();
+ let newIdentity = MailServices.accounts.createIdentity();
+ newIdentity.UID = id;
+ newIdentity.email = "username@hostname";
+ newIdentity.fullName = "User";
+ newIdentity.smtpServerKey = smtpServerA.key;
+ accountA.addIdentity(newIdentity);
+
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ tracker.resetScore();
+ Assert.equal(tracker.score, 0);
+
+ newIdentity.fullName = "Changed name";
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ newIdentity.label = "Changed label";
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ newIdentity.smtpServerKey = smtpServerB.key;
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ newIdentity.smtpServerKey = null;
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ accountA.removeIdentity(newIdentity);
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), { [id]: 0 });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+});
+
+/**
+ * Test swapping the default identity of an account.
+ */
+add_task(async function testDefaultIdentityChange() {
+ Assert.equal(tracker.score, 0);
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+
+ accountA.defaultIdentity = identityB;
+
+ Assert.equal(tracker.score, 301);
+ Assert.deepEqual(await tracker.getChangedIDs(), {
+ [identityA.UID]: 0,
+ [identityB.UID]: 0,
+ });
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+});
+
+/**
+ * Test the store methods on identites. The tracker should ignore them.
+ */
+add_task(async function testIncomingChanges() {
+ let id = newUID();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ accounts: [
+ {
+ id: accountA.UID,
+ isDefault: true,
+ },
+ ],
+ prefs: {
+ attachSignature: false,
+ attachVCard: false,
+ autoQuote: true,
+ catchAll: false,
+ catchAllHint: null,
+ composeHtml: true,
+ email: "username@hostname",
+ escapedVCard: null,
+ fullName: "User",
+ htmlSigFormat: false,
+ htmlSigText: "",
+ label: "",
+ organization: "",
+ replyOnTop: 0,
+ replyTo: null,
+ sigBottom: true,
+ sigOnForward: false,
+ sigOnReply: true,
+ },
+ smtpID: smtpServerA.UID,
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.clearChangedIDs();
+ tracker.resetScore();
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ accounts: [
+ {
+ id: accountA.UID,
+ isDefault: true,
+ },
+ ],
+ prefs: {
+ attachSignature: false,
+ attachVCard: false,
+ autoQuote: true,
+ catchAll: false,
+ catchAllHint: null,
+ composeHtml: true,
+ email: "username@hostname",
+ escapedVCard: null,
+ fullName: "User (changed)",
+ htmlSigFormat: false,
+ htmlSigText: "",
+ label: "",
+ organization: "",
+ replyOnTop: 0,
+ replyTo: null,
+ sigBottom: true,
+ sigOnForward: false,
+ sigOnReply: true,
+ },
+ smtpID: smtpServerA.UID,
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+
+ tracker.ignoreAll = true;
+ await store.applyIncoming({
+ id,
+ deleted: true,
+ });
+ tracker.ignoreAll = false;
+
+ Assert.deepEqual(await tracker.getChangedIDs(), {});
+ Assert.equal(tracker.score, 0);
+});
diff --git a/comm/mail/services/sync/test/unit/xpcshell.ini b/comm/mail/services/sync/test/unit/xpcshell.ini
new file mode 100644
index 0000000000..a8de1816a6
--- /dev/null
+++ b/comm/mail/services/sync/test/unit/xpcshell.ini
@@ -0,0 +1,11 @@
+[default]
+head = head.js
+
+[test_account_store.js]
+[test_account_tracker.js]
+[test_addressBook_store.js]
+[test_addressBook_tracker.js]
+[test_calendar_store.js]
+[test_calendar_tracker.js]
+[test_identity_store.js]
+[test_identity_tracker.js]