diff options
Diffstat (limited to 'comm/mailnews/test/resources/msgFolderListenerSetup.js')
-rw-r--r-- | comm/mailnews/test/resources/msgFolderListenerSetup.js | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/comm/mailnews/test/resources/msgFolderListenerSetup.js b/comm/mailnews/test/resources/msgFolderListenerSetup.js new file mode 100644 index 0000000000..72eaedb7a3 --- /dev/null +++ b/comm/mailnews/test/resources/msgFolderListenerSetup.js @@ -0,0 +1,429 @@ +/* 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/. */ + +// ChromeUtils.import should be used for this, but it breaks mozmill. +// Assume whatever test loaded this file already has mailTestUtils. +/* globals mailTestUtils */ + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +var allTestedEvents = + MailServices.mfn.msgAdded | + MailServices.mfn.msgsClassified | + MailServices.mfn.msgsJunkStatusChanged | + MailServices.mfn.msgsDeleted | + MailServices.mfn.msgsMoveCopyCompleted | + MailServices.mfn.msgKeyChanged | + MailServices.mfn.msgUnincorporatedMoved | + MailServices.mfn.folderAdded | + MailServices.mfn.folderDeleted | + MailServices.mfn.folderMoveCopyCompleted | + MailServices.mfn.folderRenamed | + MailServices.mfn.folderCompactStart | + MailServices.mfn.folderCompactFinish | + MailServices.mfn.folderReindexTriggered; + +// Current test being executed +var gTest = 1; + +// Which events are expected +var gExpectedEvents = []; + +// The current status (what all has been done) +var gCurrStatus = 0; +var kStatus = { + notificationsDone: 0x1, + onStopCopyDone: 0x2, + functionCallDone: 0x4, + everythingDone: 0, +}; +kStatus.everythingDone = + kStatus.notificationsDone | kStatus.onStopCopyDone | kStatus.functionCallDone; + +// For copyFileMessage: this stores the header that was received +var gHdrsReceived = []; + +var gMsgHdrs = []; + +// Our listener, which captures events and verifies them as they are received. +var gMFListener = { + msgAdded(aMsg) { + verify([MailServices.mfn.msgAdded, aMsg]); + // We might not actually have a header in gHdrsReceived in the IMAP case, + // so use the aMsg we got instead + gMsgHdrs.push({ hdr: aMsg, ID: aMsg.messageId }); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } else if (gExpectedEvents[0][0] == MailServices.mfn.msgsClassified) { + // XXX this is a hack to deal with limitations of the classification logic + // and the new list. We want to issue a call to clear the list once all + // the messages have been added, which would be when the next expected + // event is msgsClassified. (The limitation is that if we don't do this, + // we can end up getting told about this message again later.) + aMsg.folder.clearNewMessages(); + } + }, + + msgsClassified(aMsgs, aJunkProcessed, aTraitProcessed) { + dump("classified id: " + aMsgs[0].messageId + "\n"); + verify([ + MailServices.mfn.msgsClassified, + aMsgs, + aJunkProcessed, + aTraitProcessed, + ]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + msgsJunkStatusChanged(messages) { + verify([MailServices.mfn.msgsJunkStatusChanged, messages]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + msgsDeleted(aMsgs) { + verify([MailServices.mfn.msgsDeleted, aMsgs]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + msgsMoveCopyCompleted(aMove, aSrcMsgs, aDestFolder, aDestMsgs) { + verify([ + MailServices.mfn.msgsMoveCopyCompleted, + aMove, + aSrcMsgs, + aDestFolder, + aDestMsgs, + ]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + msgKeyChanged(aOldKey, aNewMsgHdr) { + verify([MailServices.mfn.msgKeyChanged, aOldKey, aNewMsgHdr]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + msgUnincorporatedMoved(srcFolder, msg) { + verify([MailServices.mfn.msgUnincorporatedMoved, srcFolder, msg]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderAdded(aFolder) { + verify([MailServices.mfn.folderAdded, aFolder]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderDeleted(aFolder) { + verify([MailServices.mfn.folderDeleted, aFolder]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderMoveCopyCompleted(aMove, aSrcFolder, aDestFolder) { + verify([ + MailServices.mfn.folderMoveCopyCompleted, + aMove, + aSrcFolder, + aDestFolder, + ]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderRenamed(aOrigFolder, aNewFolder) { + verify([MailServices.mfn.folderRenamed, aOrigFolder, aNewFolder]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderCompactStart(folder) { + verify([MailServices.mfn.folderCompactStart, folder]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderCompactFinish(folder) { + verify([MailServices.mfn.folderCompactFinish, folder]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, + + folderReindexTriggered(folder) { + verify([MailServices.mfn.folderReindexTriggered, folder]); + if (gExpectedEvents.length == 0) { + gCurrStatus |= kStatus.notificationsDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + } + }, +}; + +// Copy listener, for proceeding after each operation. +var copyListener = { + // For copyFileMessage: this should be the folder the message is being stored to + mFolderStoredIn: null, + mMessageId: "", + OnStartCopy() {}, + OnProgress(aProgress, aProgressMax) {}, + SetMessageKey(aKey) { + gHdrsReceived.push(this.mFolderStoredIn.GetMessageHeader(aKey)); + }, + GetMessageId(aMessageId) { + aMessageId = { value: this.mMessageId }; + }, + OnStopCopy(aStatus) { + // Check: message successfully copied. + Assert.equal(aStatus, 0); + gCurrStatus |= kStatus.onStopCopyDone; + if (gCurrStatus == kStatus.everythingDone) { + resetStatusAndProceed(); + } + }, +}; + +function resetStatusAndProceed() { + gHdrsReceived.length = 0; + gCurrStatus = 0; + // Ugly hack: make sure we don't get stuck in a JS->C++->JS->C++... call stack + // This can happen with a bunch of synchronous functions grouped together, and + // can even cause tests to fail because they're still waiting for the listener + // to return + do_timeout(0, () => { + this.doTest(++gTest); + }); +} + +// Checks whether the array returned from a function has exactly these elements. +function hasExactlyElements(array, elements) { + // If an nsIArray (it could also be a single header or a folder) + if (elements instanceof Ci.nsIArray) { + var count = elements.length; + + // Check: array sizes should be equal. + Assert.equal(count, array.length); + + for (let i = 0; i < count; i++) { + // Check: query element, must be a header or folder and present in the array + var currElement; + try { + currElement = elements.queryElementAt(i, Ci.nsIMsgDBHdr); + } catch (e) {} + if (!currElement) { + try { + currElement = elements.queryElementAt(i, Ci.nsIMsgFolder); + } catch (e) {} + } + Assert.equal(typeof currElement, "object"); + Assert.notEqual( + mailTestUtils.non_strict_index_of(array, currElement), + -1 + ); + } + } else if (Array.isArray(elements)) { + Assert.equal(elements.length, array.length); + for (let el of elements) { + Assert.equal(typeof el, "object"); + Assert.equal( + el instanceof Ci.nsIMsgDBHdr || el instanceof Ci.nsIMsgFolder, + true + ); + Assert.notEqual(mailTestUtils.non_strict_index_of(array, el), -1); + } + } else if ( + elements instanceof Ci.nsIMsgDBHdr || + elements instanceof Ci.nsIMsgFolder + ) { + // If a single header or a folder + + // Check: there should be only one element in the array. + Assert.equal(array.length, 1); + + // Check: the element should be present + Assert.notEqual(mailTestUtils.non_strict_index_of(array, elements), -1); + } else { + // This shouldn't happen + do_throw("Unrecognized item returned from listener"); + } +} + +// Verifies an event +function verify(event) { + // Check: make sure we actually have an item to process + Assert.ok(gExpectedEvents.length >= 1); + var expected = gExpectedEvents.shift(); + + // Check: events match. + var eventType = expected[0]; + Assert.equal(event[0], eventType); + + dump("..... Verifying event type " + eventType + "\n"); + + switch (eventType) { + case MailServices.mfn.msgAdded: + // So for IMAP right now, we aren't able to get the actual nsIMsgDBHdr. + // Instead, we'll match up message ids as a (poor?) substitute. + if (expected[1].expectedMessageId) { + Assert.equal(expected[1].expectedMessageId, event[1].messageId); + break; + } + // If we do have a header, fall through to the case below + case MailServices.mfn.msgsDeleted: + case MailServices.mfn.folderDeleted: + // Check: headers match/folder matches. + hasExactlyElements(expected[1], event[1]); + break; + case MailServices.mfn.msgsClassified: + // In the IMAP case expected[1] is a list of mesage-id strings whereas in + // the local case (where we are copying from files), we actually have + // the headers. + if (typeof expected[1][0] == "string") { + // IMAP; message id strings + // The IMAP case has additional complexity in that the 'new message' + // list is not tailored to our needs and so may over-report about + // new messagse. So to deal with this we make sure the msgsClassified + // event is telling us about at least the N expected events and that + // the last N of these events match + if (event[1].length < expected[1].length) { + do_throw("Not enough reported classified messages."); + } + let ignoreCount = event[1].length - expected[1].length; + for (let i = 0; i < expected[1].length; i++) { + let eventHeader = event[1][i + ignoreCount]; + Assert.equal(expected[1][i], eventHeader.messageId); + } + } else { + // actual headers + hasExactlyElements(expected[1], event[1]); + } + // aJunkProcessed: was the message processed for junk? + Assert.equal(expected[2], event[2]); + // aTraitProcessed: was the message processed for traits? + Assert.equal(expected[3], event[3]); + break; + case MailServices.mfn.msgsJunkStatusChanged: + // Check: same messages? + hasExactlyElements(expected[1], event[1]); + break; + case MailServices.mfn.msgKeyChanged: + Assert.equal(expected[1].expectedMessageId, event[2].messageId); + break; + case MailServices.mfn.msgUnincorporatedMoved: + // Check: Same folder? + Assert.equal(expected[1].URI, event[1].URI); + // Check: message matches? + hasExactlyElements(expected[2], event[2]); + break; + case MailServices.mfn.msgsMoveCopyCompleted: + case MailServices.mfn.folderMoveCopyCompleted: + // Check: Move or copy as expected. + Assert.equal(expected[1], event[1]); + + // Check: headers match/folder matches. + hasExactlyElements(expected[2], event[2]); + + // Check: destination folder matches. + Assert.equal(expected[3].URI, event[3].URI); + + if (eventType == MailServices.mfn.folderMoveCopyCompleted) { + break; + } + + // Check: destination headers. We expect these for local and imap folders, + // but we will not have heard about the headers ahead of time, + // so the best we can do is make sure they match up. To this end, + // we check that the message-id header values match up. + for (let iMsg = 0; iMsg < event[2].length; iMsg++) { + let srcHdr = event[2][iMsg]; + let destHdr = event[4][iMsg]; + Assert.equal(srcHdr.messageId, destHdr.messageId); + } + break; + case MailServices.mfn.folderAdded: + // Check: parent folder matches + Assert.equal(expected[1].URI, event[1].parent.URI); + + // Check: folder name matches + Assert.equal(expected[2], event[1].prettyName); + Assert.equal(expected[2], event[1].name); + + // Not a check, but call the passed in callback with the new folder, + // used e.g. to store this folder somewhere. + if (expected[3]) { + expected[3](event[1]); + } + break; + case MailServices.mfn.folderRenamed: + // Check: source folder matches + hasExactlyElements(expected[1], event[1]); + + // Check: destination folder name matches + Assert.equal(expected[2], event[2].prettyName); + break; + case MailServices.mfn.folderCompactStart: + case MailServices.mfn.folderCompactFinish: + case MailServices.mfn.folderReindexTriggered: + // Check: same folder? + Assert.equal(expected[1].URI, event[1].URI); + break; + } +} |