diff options
Diffstat (limited to 'comm/mail/test/browser/folder-display/browser_messageCommandsOnMsgstore.js')
-rw-r--r-- | comm/mail/test/browser/folder-display/browser_messageCommandsOnMsgstore.js | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/comm/mail/test/browser/folder-display/browser_messageCommandsOnMsgstore.js b/comm/mail/test/browser/folder-display/browser_messageCommandsOnMsgstore.js new file mode 100644 index 0000000000..899a211de8 --- /dev/null +++ b/comm/mail/test/browser/folder-display/browser_messageCommandsOnMsgstore.js @@ -0,0 +1,333 @@ +/* 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/. */ + +/** + * This tests some commands on messages via the UI. But we specifically check, + * whether the commands have an effect in the message store on disk, i.e. the + * markings on the messages are stored in the msgStore, not only in the database. + * For now, it checks for bug 840418. + */ + +"use strict"; + +var utils = ChromeUtils.import("resource://testing-common/mozmill/utils.jsm"); +const { + open_compose_with_forward, + open_compose_with_reply, + setup_msg_contents, +} = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm"); +const { + be_in_folder, + create_folder, + empty_folder, + get_special_folder, + make_message_sets_in_folders, + mc, + press_delete, + right_click_on_row, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +const { + click_menus_in_sequence, + plan_for_window_close, + wait_for_window_close, +} = ChromeUtils.import("resource://testing-common/mozmill/WindowHelpers.jsm"); + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +let gInbox; +let gOutbox; +let gAutoRead; + +add_setup(async function () { + gAutoRead = Services.prefs.getBoolPref("mailnews.mark_message_read.auto"); + Services.prefs.setBoolPref("mailnews.mark_message_read.auto", false); + + gOutbox = await get_special_folder(Ci.nsMsgFolderFlags.Queue); + gInbox = await create_folder("MsgStoreChecks"); + await make_message_sets_in_folders([gInbox], [{ count: 6 }]); + + // We delete the first message so that we have to compact anything. + await be_in_folder(gInbox); + let curMessage = select_click_row(0); + press_delete(mc); + Assert.notEqual(curMessage, select_click_row(0)); + + let urlListener = { + compactDone: false, + + OnStartRunningUrl(aUrl) {}, + OnStopRunningUrl(aUrl, aExitCode) { + Assert.equal(aExitCode, 0); + Assert.ok(gInbox.msgDatabase.summaryValid); + this.compactDone = true; + }, + }; + + // Compaction adds the X-Mozilla-Status rows into the messages + // that we will need later on. + Assert.ok(gInbox.msgStore.supportsCompaction); + gInbox.compact(urlListener, null); + + utils.waitFor( + function () { + return urlListener.compactDone; + }, + "Timeout waiting for compact to complete", + 10000, + 100 + ); +}); + +/** + * Checks that a message has particular status stored in the mbox file, + * in the X-Mozilla-Status header. + * + * @param folder The folder containing the message to check. + * @param offset Offset to the start of the message within mbox file. + * @param expectedStatus The required status of the message. + */ +async function check_status(folder, offset, expectedStatus) { + let mboxstring = await IOUtils.readUTF8(folder.filePath.path); + + // Ah-hoc header parsing. Only check the first 1KB because the X-Mozilla-* + // headers should be near the start. + let msg = mboxstring.slice(offset, offset + 1024); + msg = msg.replace(/\r/g, ""); // Simplify by using LFs only. + for (let line of msg.split("\n")) { + if (line == "") { + break; // end of header block. + } + if (line.startsWith("X-Mozilla-Status:")) { + let hexValue = /:\s*([0-9a-f]+)/i.exec(line)[1]; + let gotStatus = parseInt(hexValue, 16); + Assert.equal( + gotStatus, + expectedStatus, + `Check X-Mozilla-Status (for msg at offset ${offset})` + ); + return; + } + } + // If we got this far, we didn't find the header. + Assert.ok( + false, + `Find X-Mozilla-Status header (for msg at offset ${offset})` + ); +} + +add_task(async function test_mark_messages_read() { + be_in_folder(gOutbox); // TODO shouldn't have to swap folders + // 5 messages in the folder + await be_in_folder(gInbox); + let curMessage = select_click_row(0); + // Store the offset because it will be unavailable via the hdr + // after the message is deleted. + let offset = curMessage.messageOffset; + await check_status(gInbox, offset, 0); // status = unread + press_delete(mc); + Assert.notEqual(curMessage, select_click_row(0)); + await check_status( + gInbox, + offset, + Ci.nsMsgMessageFlags.Read + Ci.nsMsgMessageFlags.Expunged + ); + + // 4 messages in the folder. + curMessage = select_click_row(0); + await check_status(gInbox, curMessage.messageOffset, 0); // status = unread + + // Make sure we can mark all read with >0 messages unread. + await right_click_on_row(0); + let hiddenPromise = BrowserTestUtils.waitForEvent( + getMailContext(), + "popuphidden" + ); + await click_menus_in_sequence(getMailContext(), [ + { id: "mailContext-mark" }, + { id: "mailContext-markAllRead" }, + ]); + await hiddenPromise; + await new Promise(resolve => requestAnimationFrame(resolve)); + + // All the 4 messages should now be read. + Assert.ok(curMessage.isRead, "Message should have been marked Read!"); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Read + ); + curMessage = select_click_row(1); + Assert.ok(curMessage.isRead, "Message should have been marked Read!"); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Read + ); + curMessage = select_click_row(2); + Assert.ok(curMessage.isRead, "Message should have been marked Read!"); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Read + ); + curMessage = select_click_row(3); + Assert.ok(curMessage.isRead, "Message should have been marked Read!"); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Read + ); + + // Let's have the last message unread. + await right_click_on_row(3); + hiddenPromise = BrowserTestUtils.waitForEvent( + getMailContext(), + "popuphidden" + ); + await click_menus_in_sequence(getMailContext(), [ + { id: "mailContext-mark" }, + { id: "mailContext-markUnread" }, + ]); + await hiddenPromise; + await new Promise(resolve => requestAnimationFrame(resolve)); + + Assert.ok(!curMessage.isRead, "Message should have not been marked Read!"); + await check_status(gInbox, curMessage.messageOffset, 0); +}); + +add_task(async function test_mark_messages_flagged() { + // Mark a message with the star. + let curMessage = select_click_row(1); + await right_click_on_row(1); + let hiddenPromise = BrowserTestUtils.waitForEvent( + getMailContext(), + "popuphidden" + ); + await click_menus_in_sequence(getMailContext(), [ + { id: "mailContext-mark" }, + { id: "mailContext-markFlagged" }, + ]); + await hiddenPromise; + await new Promise(resolve => requestAnimationFrame(resolve)); + + Assert.ok(curMessage.isFlagged, "Message should have been marked Flagged!"); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Read + Ci.nsMsgMessageFlags.Marked + ); +}); + +async function subtest_check_queued_message() { + // Always check the last message in the Outbox for the correct flag. + await be_in_folder(gOutbox); + let lastMsg = [...gOutbox.messages].pop(); + await check_status( + gOutbox, + lastMsg.messageOffset, + Ci.nsMsgMessageFlags.Queued + ); +} + +/** + * Create a reply or forward of a message and queue it for sending later. + * + * @param aMsgRow Row index of message in Inbox that is to be replied/forwarded. + * @param aReply true = reply, false = forward. + */ +async function reply_forward_message(aMsgRow, aReply) { + await be_in_folder(gInbox); + select_click_row(aMsgRow); + let cwc; + if (aReply) { + // Reply to the message. + cwc = open_compose_with_reply(); + } else { + // Forward the message. + cwc = open_compose_with_forward(); + // Type in some recipient. + setup_msg_contents(cwc, "somewhere@host.invalid", "", ""); + } + + // Send it later. + plan_for_window_close(cwc); + // Ctrl+Shift+Return = Send Later + cwc.window.document.getElementById("messageEditor").focus(); + EventUtils.synthesizeKey( + "VK_RETURN", + { + shiftKey: true, + accelKey: true, + }, + cwc.window + ); + wait_for_window_close(cwc); + + await subtest_check_queued_message(); + + // Now this is hacky. We can't get the message to be sent out of TB because there + // is no fake SMTP server support yet. + // But we know that upon real sending of the message, the code would/should call + // .addMessageDispositionState(). So call it directly and check the expected + // flags were set. This is risky as the real code could change and call + // a different function and the purpose of this test would be lost. + await be_in_folder(gInbox); + let curMessage = select_click_row(aMsgRow); + let disposition = aReply + ? gInbox.nsMsgDispositionState_Replied + : gInbox.nsMsgDispositionState_Forwarded; + gInbox.addMessageDispositionState(curMessage, disposition); +} + +add_task(async function test_mark_messages_replied() { + await reply_forward_message(2, true); + let curMessage = select_click_row(2); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Replied + Ci.nsMsgMessageFlags.Read + ); +}); + +add_task(async function test_mark_messages_forwarded() { + await be_in_folder(gInbox); + // Forward a clean message. + await reply_forward_message(3, false); + let curMessage = select_click_row(3); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Forwarded + ); + + // Forward a message that is read and already replied to. + curMessage = select_click_row(2); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Replied + Ci.nsMsgMessageFlags.Read + ); + await reply_forward_message(2, false); + await check_status( + gInbox, + curMessage.messageOffset, + Ci.nsMsgMessageFlags.Forwarded + + Ci.nsMsgMessageFlags.Replied + + Ci.nsMsgMessageFlags.Read + ); +}); + +registerCleanupFunction(async function () { + Services.prefs.setBoolPref("mailnews.mark_message_read.auto", gAutoRead); + // Clear all the created messages. + await be_in_folder(gInbox.parent); + await empty_folder(gInbox); + // await empty_folder(gOutbox); TODO + gInbox.server.rootFolder.emptyTrash(null); +}); |