summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/imap/test/unit/test_imapAttachmentSaves.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/imap/test/unit/test_imapAttachmentSaves.js')
-rw-r--r--comm/mailnews/imap/test/unit/test_imapAttachmentSaves.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/comm/mailnews/imap/test/unit/test_imapAttachmentSaves.js b/comm/mailnews/imap/test/unit/test_imapAttachmentSaves.js
new file mode 100644
index 0000000000..d3e3951492
--- /dev/null
+++ b/comm/mailnews/imap/test/unit/test_imapAttachmentSaves.js
@@ -0,0 +1,199 @@
+/* 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/. */
+
+/*
+ * Tests imap save and detach attachments.
+ */
+
+var { MessageGenerator } = ChromeUtils.import(
+ "resource://testing-common/mailnews/MessageGenerator.jsm"
+);
+var { PromiseTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mailnews/PromiseTestUtils.jsm"
+);
+
+// javascript mime emitter functions
+var { MsgHdrToMimeMessage } = ChromeUtils.import(
+ "resource:///modules/gloda/MimeMessage.jsm"
+);
+
+var kAttachFileName = "bob.txt";
+function SaveAttachmentCallback() {
+ this.attachments = null;
+ this._promise = new Promise((resolve, reject) => {
+ this._resolve = resolve;
+ this._reject = reject;
+ });
+}
+
+SaveAttachmentCallback.prototype = {
+ callback: function saveAttachmentCallback_callback(aMsgHdr, aMimeMessage) {
+ this.attachments = aMimeMessage.allAttachments;
+ this._resolve();
+ },
+ get promise() {
+ return this._promise;
+ },
+};
+var gCallbackObject = new SaveAttachmentCallback();
+
+// Dummy message window so we can say the inbox is open in a window.
+var dummyMsgWindow = Cc["@mozilla.org/messenger/msgwindow;1"].createInstance(
+ Ci.nsIMsgWindow
+);
+
+function MsgsDeletedListener() {
+ this._promise = new Promise(resolve => (this._resolve = resolve));
+}
+MsgsDeletedListener.prototype = {
+ msgsDeleted(aMsgArray) {
+ this._resolve();
+ },
+ get promise() {
+ return this._promise;
+ },
+};
+var trackDeletionMessageListener = new MsgsDeletedListener();
+
+add_setup(function () {
+ setupIMAPPump();
+
+ // Add folder listeners that will capture async events
+ MailServices.mfn.addListener(
+ trackDeletionMessageListener,
+ Ci.nsIMsgFolderNotificationService.msgsDeleted
+ );
+
+ // We need to register the dummyMsgWindow so that when we've finished running
+ // the append url, in nsImapMailFolder::OnStopRunningUrl, we'll think the
+ // Inbox is open in a folder and update it, which the detach code relies
+ // on to finish the detach.
+
+ dummyMsgWindow.openFolder = IMAPPump.inbox;
+ MailServices.mailSession.AddMsgWindow(dummyMsgWindow);
+});
+
+// load and update a message in the imap fake server
+add_task(async function loadImapMessage() {
+ let gMessageGenerator = new MessageGenerator();
+ // create a synthetic message with attachment
+ let smsg = gMessageGenerator.makeMessage({
+ attachments: [{ filename: kAttachFileName, body: "I like cheese!" }],
+ });
+
+ let msgURI = Services.io.newURI(
+ "data:text/plain;base64," + btoa(smsg.toMessageString())
+ );
+ let imapInbox = IMAPPump.daemon.getMailbox("INBOX");
+ let message = new ImapMessage(msgURI.spec, imapInbox.uidnext++, []);
+ IMAPPump.mailbox.addMessage(message);
+ let listener = new PromiseTestUtils.PromiseUrlListener();
+ IMAPPump.inbox.updateFolderWithListener(null, listener);
+ await listener.promise;
+ Assert.equal(1, IMAPPump.inbox.getTotalMessages(false));
+ let msgHdr = mailTestUtils.firstMsgHdr(IMAPPump.inbox);
+ Assert.ok(msgHdr instanceof Ci.nsIMsgDBHdr);
+});
+
+// process the message through mime
+add_task(async function startMime() {
+ let msgHdr = mailTestUtils.firstMsgHdr(IMAPPump.inbox);
+
+ MsgHdrToMimeMessage(
+ msgHdr,
+ gCallbackObject,
+ gCallbackObject.callback,
+ true // allowDownload
+ );
+ await gCallbackObject.promise;
+});
+
+// detach any found attachments
+add_task(async function startDetach() {
+ let msgHdr = mailTestUtils.firstMsgHdr(IMAPPump.inbox);
+ let msgURI = msgHdr.folder.generateMessageURI(msgHdr.messageKey);
+
+ let messenger = Cc["@mozilla.org/messenger;1"].createInstance(
+ Ci.nsIMessenger
+ );
+ let attachment = gCallbackObject.attachments[0];
+
+ messenger.detachAttachmentsWOPrompts(
+ do_get_profile(),
+ [attachment.contentType],
+ [attachment.url],
+ [attachment.name],
+ [msgURI],
+ null
+ );
+ // deletion of original message should kick async_driver.
+ await trackDeletionMessageListener.promise;
+});
+
+// test that the detachment was successful
+add_task(async function testDetach() {
+ // Check that the file attached to the message now exists in the profile
+ // directory.
+ let checkFile = do_get_profile().clone();
+ checkFile.append(kAttachFileName);
+ Assert.ok(checkFile.exists());
+
+ // The message should now have a detached attachment. Read the message,
+ // and search for "AttachmentDetached" which is added on detachment.
+
+ // Get the message header - detached copy has UID 2.
+ let msgHdr = IMAPPump.inbox.GetMessageHeader(2);
+ Assert.ok(msgHdr !== null);
+ let messageContent = await getContentFromMessage(msgHdr);
+ Assert.ok(messageContent.includes("AttachmentDetached"));
+});
+
+// Cleanup
+add_task(function endTest() {
+ teardownIMAPPump();
+});
+
+/**
+ * Get the full message content.
+ *
+ * @param aMsgHdr - nsIMsgDBHdr object whose text body will be read.
+ * @returns {Promise<string>} full message contents.
+ */
+function getContentFromMessage(aMsgHdr) {
+ let msgFolder = aMsgHdr.folder;
+ let msgUri = msgFolder.getUriForMsg(aMsgHdr);
+
+ return new Promise((resolve, reject) => {
+ let streamListener = {
+ QueryInterface: ChromeUtils.generateQI(["nsIStreamListener"]),
+ sis: Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
+ Ci.nsIScriptableInputStream
+ ),
+ content: "",
+ onDataAvailable(request, inputStream, offset, count) {
+ this.sis.init(inputStream);
+ this.content += this.sis.read(count);
+ },
+ onStartRequest(request) {},
+ onStopRequest(request, statusCode) {
+ this.sis.close();
+ if (Components.isSuccessCode(statusCode)) {
+ resolve(this.content);
+ } else {
+ reject(new Error(statusCode));
+ }
+ },
+ };
+ // Pass true for aLocalOnly since message should be in offline store.
+ MailServices.messageServiceFromURI(msgUri).streamMessage(
+ msgUri,
+ streamListener,
+ null,
+ null,
+ false,
+ "",
+ true
+ );
+ });
+}