/* 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 the many ways to make Thunderbird fetch new mail. In this file are * best case scenarios. Edge cases and failure cases are in separate files. * * An account of each type is created, and they are tested collectively and * individually. For each test, new messages are put on the server, the action * being tested is performed, then the test waits for the messages to appear. */ /* eslint-disable @microsoft/sdl/no-insecure-url */ requestLongerTimeout(2); const { MailConsts } = ChromeUtils.importESModule( "resource:///modules/MailConsts.sys.mjs" ); const { MailUtils } = ChromeUtils.importESModule( "resource:///modules/MailUtils.sys.mjs" ); const { MessageGenerator } = ChromeUtils.importESModule( "resource://testing-common/mailnews/MessageGenerator.sys.mjs" ); const { ServerTestUtils } = ChromeUtils.importESModule( "resource://testing-common/mailnews/ServerTestUtils.sys.mjs" ); const { storeState } = ChromeUtils.importESModule( "resource:///modules/CustomizationState.mjs" ); const generator = new MessageGenerator(); let localAccount, localRootFolder; let imapServer, imapAccount, imapRootFolder, imapInbox; let pop3Server, pop3Account, pop3RootFolder, pop3Inbox; let ewsServer, ewsAccount, ewsRootFolder, ewsInbox; let nntpServer, nntpAccount, nntpRootFolder, nntpFolder; const allInboxes = []; const about3Pane = document.getElementById("tabmail").currentAbout3Pane; const getMessagesButton = about3Pane.document.getElementById( "folderPaneGetMessages" ); const getMessagesContext = about3Pane.document.getElementById( "folderPaneGetMessagesContext" ); let toolbarButton, toolbarContext; add_setup(async function () { localAccount = MailServices.accounts.createLocalMailAccount(); localRootFolder = localAccount.incomingServer.rootFolder; [imapServer, pop3Server, ewsServer, nntpServer] = await ServerTestUtils.createServers([ ServerTestUtils.serverDefs.imap.plain, ServerTestUtils.serverDefs.pop3.plain, ServerTestUtils.serverDefs.ews.plain, ServerTestUtils.serverDefs.nntp.plain, ]); nntpServer.addGroup("getmessages.newsgroup"); imapAccount = MailServices.accounts.createAccount(); imapAccount.addIdentity(MailServices.accounts.createIdentity()); imapAccount.incomingServer = MailServices.accounts.createIncomingServer( "user", "test.test", "imap" ); imapAccount.incomingServer.prettyName = "IMAP Account"; imapAccount.incomingServer.port = 143; await addLoginInfo("imap://test.test", "user", "password"); imapRootFolder = imapAccount.incomingServer.rootFolder; imapInbox = imapRootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox); allInboxes.push(imapInbox); pop3Account = MailServices.accounts.createAccount(); pop3Account.addIdentity(MailServices.accounts.createIdentity()); pop3Account.incomingServer = MailServices.accounts.createIncomingServer( "user", "test.test", "pop3" ); pop3Account.incomingServer.prettyName = "POP3 Account"; pop3Account.incomingServer.port = 110; await addLoginInfo("mailbox://test.test", "user", "password"); pop3RootFolder = pop3Account.incomingServer.rootFolder; pop3Inbox = pop3RootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox); allInboxes.push(pop3Inbox); ewsAccount = MailServices.accounts.createAccount(); ewsAccount.addIdentity(MailServices.accounts.createIdentity()); ewsAccount.incomingServer = MailServices.accounts.createIncomingServer( "user", "test.test", "ews" ); ewsAccount.incomingServer.setStringValue( "ews_url", "http://test.test/EWS/Exchange.asmx" ); ewsAccount.incomingServer.prettyName = "EWS Account"; await addLoginInfo("ews://test.test", "user", "password"); ewsRootFolder = ewsAccount.incomingServer.rootFolder; ewsAccount.incomingServer.performExpand(null); ewsInbox = await TestUtils.waitForCondition( () => ewsRootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox), "waiting for EWS folders to sync" ); allInboxes.push(ewsInbox); nntpAccount = MailServices.accounts.createAccount(); nntpAccount.incomingServer = MailServices.accounts.createIncomingServer( "user", "test.test", "nntp" ); nntpAccount.incomingServer.prettyName = "NNTP Account"; nntpAccount.incomingServer.port = 119; nntpRootFolder = nntpAccount.incomingServer.rootFolder; nntpRootFolder.createSubfolder("getmessages.newsgroup", null); nntpFolder = nntpRootFolder.getChildNamed("getmessages.newsgroup"); allInboxes.push(nntpFolder); document.getElementById("toolbar-menubar").removeAttribute("autohide"); about3Pane.displayFolder(localRootFolder); storeState({ mail: ["get-messages"] }); toolbarButton = document.querySelector( `#unifiedToolbarContent [item-id="get-messages"]` ); toolbarContext = document.getElementById("toolbarGetMessagesContext"); await TestUtils.waitForCondition( () => toolbarButton.clientWidth && toolbarButton.clientHeight, "waiting for toolbar button" ); registerCleanupFunction(async function () { MailServices.accounts.removeAccount(localAccount, false); MailServices.accounts.removeAccount(imapAccount, false); MailServices.accounts.removeAccount(pop3Account, false); MailServices.accounts.removeAccount(ewsAccount, false); MailServices.accounts.removeAccount(nntpAccount, false); storeState({}); Services.logins.removeAllLogins(); }); }); async function addMessagesToServer(type) { const messages = generator.makeMessages({}); if (type == "imap") { await imapServer.addMessages(imapInbox, messages, false); } else if (type == "pop3") { await pop3Server.addMessages(messages); } else if (type == "ews") { await ewsServer.addMessages("inbox", messages); } else if (type == "nntp") { await nntpServer.addMessages("getmessages.newsgroup", messages); } } async function addMessagesToAllServers() { for (const inbox of allInboxes) { await addMessagesToServer(inbox.server.type); } } async function waitForMessages(inbox) { await TestUtils.waitForCondition( () => inbox.getNumUnread(false) == 10 && inbox.numPendingUnread == 0, `waiting for new ${inbox.server.type} messages to be received` ); await promiseServerIdle(inbox.server); info(`${inbox.server.type} messages received`); inbox.markAllMessagesRead(window.msgWindow); await promiseServerIdle(inbox.server); await TestUtils.waitForCondition( () => inbox.getNumUnread(false) == 0 && inbox.numPendingUnread == 0, `waiting for ${inbox.server.type} messages to be marked read` ); info(`${inbox.server.type} messages marked as read`); } async function testAllServers(testCallback) { await addMessagesToAllServers(); for (const inbox of allInboxes) { Assert.equal( inbox.getNumUnread(false), 0, `${inbox.server.type} inbox should start with no messages` ); } info("getting messages for all inboxes"); await testCallback(); for (const inbox of allInboxes) { await waitForMessages(inbox); } } async function testEachServer(testCallback) { await addMessagesToAllServers(); for (const inbox of allInboxes) { Assert.equal( inbox.getNumUnread(false), 0, `${inbox.server.type} inbox should start with no messages` ); } for (const inbox of allInboxes) { info(`getting messages for ${inbox.server.type} inbox`); await testCallback(inbox); await waitForMessages(inbox); for (const otherInbox of allInboxes) { if (otherInbox != inbox) { Assert.equal( otherInbox.getNumUnread(false), 0, `${otherInbox.server.type} should have no new messages` ); } } } for (const inbox of allInboxes) { await promiseServerIdle(inbox.server); } } async function checkPopupItemsAndActivateFirst(popup, startAtIndex) { await BrowserTestUtils.waitForPopupEvent(popup, "shown"); Assert.equal( popup.childElementCount, allInboxes.length + startAtIndex, "context menu has correct entries" ); for (let i = 0; i < allInboxes.length; i++) { Assert.equal( popup.children[i + startAtIndex].textContent, allInboxes[i].server.prettyName, `${allInboxes[i].server.type} context menu item is labelled correctly` ); } popup.activateItem(popup.children[0]); await BrowserTestUtils.waitForPopupEvent(popup, "hidden"); } /** * Tests the "Get All New Messages" menu item from the Folder Pane header button. */ add_task(async function testGetMessagesContextAll() { await testAllServers(async function () { EventUtils.synthesizeMouseAtCenter( getMessagesButton, { type: "contextmenu" }, about3Pane ); await checkPopupItemsAndActivateFirst(getMessagesContext, 2); }); }); /** * Tests each account menu item from the Folder Pane header button. */ add_task(async function testGetMessagesContext() { await testEachServer(async function (thisInbox) { EventUtils.synthesizeMouseAtCenter( getMessagesButton, { type: "contextmenu" }, about3Pane ); await BrowserTestUtils.waitForPopupEvent(getMessagesContext, "shown"); getMessagesContext.activateItem( getMessagesContext.querySelector( `[data-server-key="${thisInbox.server.key}"]` ) ); await BrowserTestUtils.waitForPopupEvent(getMessagesContext, "hidden"); }); }); /** * Tests the folder pane context menu. */ add_task(async function testFolderPaneContext() { await testEachServer(async function (thisInbox) { const folderPaneContext = about3Pane.document.getElementById("folderPaneContext"); const folderRow = about3Pane.folderPane.getRowForFolder( thisInbox.rootFolder ); EventUtils.synthesizeMouseAtCenter( folderRow.querySelector(".name"), { type: "contextmenu" }, about3Pane ); await BrowserTestUtils.waitForPopupEvent(folderPaneContext, "shown"); folderPaneContext.activateItem( folderPaneContext.querySelector("#folderPaneContext-getMessages") ); await BrowserTestUtils.waitForPopupEvent(folderPaneContext, "hidden"); }); }); /** * Tests clicking on the toolbar button. */ add_task(async function testToolbarButtonAll() { await testAllServers(function () { EventUtils.synthesizeMouseAtCenter(toolbarButton, {}, window); }); }); /** * Tests the "Get All New Messages" menu item from the toolbar button. */ add_task(async function testToolbarContextAll() { await testAllServers(async function () { EventUtils.synthesizeMouseAtCenter( toolbarButton, { type: "contextmenu" }, window ); await checkPopupItemsAndActivateFirst(toolbarContext, 2); }); }); /** * Tests each account menu item from the toolbar button. */ add_task(async function testToolbarContext() { await testEachServer(async function (thisInbox) { EventUtils.synthesizeMouseAtCenter( toolbarButton, { type: "contextmenu" }, window ); await BrowserTestUtils.waitForPopupEvent(toolbarContext, "shown"); toolbarContext.activateItem( toolbarContext.querySelector( `[data-server-key="${thisInbox.server.key}"]` ) ); await BrowserTestUtils.waitForPopupEvent(toolbarContext, "hidden"); }); }); async function subtestFileMenuAll(win) { const doc = win.document; const fileMenu = doc.getElementById("menu_File"); const fileMenuGetMessages = doc.getElementById("menu_getAllNewMsg"); await testAllServers(async function () { EventUtils.synthesizeMouseAtCenter(fileMenu, {}, win); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "shown"); fileMenuGetMessages.openMenu(true); await checkPopupItemsAndActivateFirst(fileMenuGetMessages.menupopup, 3); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "hidden"); }); } async function subtestFileMenu(win, thisInbox) { const doc = win.document; const fileMenu = doc.getElementById("menu_File"); const fileMenuGetMessages = doc.getElementById("menu_getAllNewMsg"); const fileMenuGetMessagesPopup = fileMenuGetMessages.menupopup; EventUtils.synthesizeMouseAtCenter(fileMenu, {}, win); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "shown"); fileMenuGetMessages.openMenu(true); await BrowserTestUtils.waitForPopupEvent(fileMenuGetMessagesPopup, "shown"); fileMenuGetMessagesPopup.activateItem(fileMenuGetMessagesPopup.children[1]); await BrowserTestUtils.waitForPopupEvent(fileMenuGetMessagesPopup, "hidden"); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "hidden"); await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); EventUtils.synthesizeMouseAtCenter(fileMenu, {}, win); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "shown"); fileMenuGetMessages.openMenu(true); await BrowserTestUtils.waitForPopupEvent(fileMenuGetMessagesPopup, "shown"); for (const menuitem of fileMenuGetMessagesPopup.children) { if (menuitem._folder == thisInbox.rootFolder) { fileMenuGetMessagesPopup.activateItem(menuitem); break; } } await BrowserTestUtils.waitForPopupEvent(fileMenuGetMessagesPopup, "hidden"); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "hidden"); await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); } /** * Tests the "All Accounts" menu item from the File menu. */ add_task(async function testFileMenuAll() { await subtestFileMenuAll(window); }).skip(AppConstants.platform == "macosx"); // Can't click the menu bar on mac. /** * Tests each account menu item from the File menu. */ add_task(async function testFileMenu() { const fileMenu = document.getElementById("menu_File"); const fileMenuGetMessages = document.getElementById("menu_getAllNewMsg"); const fileMenuGetMessagesPopup = fileMenuGetMessages.menupopup; await testEachServer(async function (thisInbox) { EventUtils.synthesizeMouseAtCenter(fileMenu, {}, window); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "shown"); fileMenuGetMessages.openMenu(true); await BrowserTestUtils.waitForPopupEvent(fileMenuGetMessagesPopup, "shown"); for (const menuitem of fileMenuGetMessagesPopup.children) { if (menuitem._folder == thisInbox.rootFolder) { fileMenuGetMessagesPopup.activateItem(menuitem); break; } } await BrowserTestUtils.waitForPopupEvent( fileMenuGetMessagesPopup, "hidden" ); await BrowserTestUtils.waitForPopupEvent(fileMenu.menupopup, "hidden"); }); }).skip(AppConstants.platform == "macosx"); // Can't click the menu bar on mac. /** * Tests displaying a folder, clicking the Folder Pane header button, the File * menu "Current Account" menu item, and pressing F5. All of these things are * tested together because the act of displaying a folder fetches new mail. */ add_task(async function testInFolder() { await testEachServer(async function (thisInbox) { info("displaying the folder"); about3Pane.displayFolder(thisInbox); if (thisInbox.server.type != "pop3") { // Why don't POP3 folders update when you open them? await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); } info("clicking the Folder Pane header button"); EventUtils.synthesizeMouseAtCenter(getMessagesButton, {}, about3Pane); await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); if (AppConstants.platform != "macosx") { info("clicking the File menu item"); await subtestFileMenu(window, thisInbox); } info("pressing F5"); EventUtils.synthesizeKey("VK_F5", {}); }); about3Pane.displayFolder(localRootFolder); }); /** * Tests the "Read messages" button in Account Central. */ add_task(async function testAccountCentral() { await testEachServer(async function (thisInbox) { about3Pane.displayFolder(thisInbox.rootFolder); const accountCentralBrowser = about3Pane.accountCentralBrowser; await TestUtils.waitForCondition( () => accountCentralBrowser.currentURI.spec.endsWith( encodeURIComponent(thisInbox.rootFolder.URI) ) && accountCentralBrowser.contentDocument.readyState == "complete", "waiting for Account Central to load" ); EventUtils.synthesizeMouseAtCenter( accountCentralBrowser.contentDocument.getElementById("readButton"), {}, accountCentralBrowser.contentWindow ); await TestUtils.waitForCondition( () => about3Pane.gFolder == thisInbox, "waiting for displayed folder to change" ); }); about3Pane.displayFolder(localRootFolder); }); /** * Tests the "All Accounts" menu item from the File menu and the toolbar of a * standalone message window. */ add_task(async function testMessageWindowAll() { const messageWindow = await openMessageFromFile( new FileUtils.File(getTestFilePath("../files/sampleContent.eml")) ); if (AppConstants.platform != "macosx") { await subtestFileMenuAll(messageWindow); } info("clicking the toolbar popup menu item"); await testAllServers(async function () { const button = messageWindow.document.getElementById("button-getmsg"); EventUtils.synthesizeMouseAtCenter( button.querySelector(".toolbarbutton-menubutton-dropmarker"), {}, messageWindow ); await checkPopupItemsAndActivateFirst(button.menupopup, 2); }); await BrowserTestUtils.closeWindow(messageWindow); await SimpleTest.promiseFocus(window); }); /** * Tests displaying a message, the File menu "Current Account" menu item, the * toolbar button, and pressing F5 in a standalone message window. * * This test assumes at least one of the earlier tests have run and therefore * there are messages in each of the folders. */ add_task(async function testMessageWindow() { const windowsToClose = []; try { await testEachServer(async function (thisInbox) { info("opening a message"); const messageWindowPromise = BrowserTestUtils.domWindowOpenedAndLoaded(); window.MsgOpenNewWindowForMessage(thisInbox.messages.getNext()); const messageWindow = await messageWindowPromise; await messageLoadedIn(messageWindow.messageBrowser); windowsToClose.push(messageWindow); if (thisInbox.server.type != "pop3") { // Why don't POP3 folders update when you open them? await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); } if (AppConstants.platform != "macosx") { info("clicking the File menu item"); await subtestFileMenu(messageWindow, thisInbox); } info("clicking the toolbar button"); const button = messageWindow.document.getElementById("button-getmsg"); const popup = button.menupopup; EventUtils.synthesizeMouseAtCenter( button.querySelector(".toolbarbutton-menubutton-button"), {}, messageWindow ); await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); info("clicking the toolbar popup menu item"); EventUtils.synthesizeMouseAtCenter( button.querySelector(".toolbarbutton-menubutton-dropmarker"), {}, messageWindow ); await BrowserTestUtils.waitForPopupEvent(popup, "shown"); for (const menuitem of popup.children) { if (menuitem._folder == thisInbox.rootFolder) { popup.activateItem(menuitem); break; } } await BrowserTestUtils.waitForPopupEvent(popup, "hidden"); await waitForMessages(thisInbox); await addMessagesToServer(thisInbox.server.type); info("pressing F5"); EventUtils.synthesizeKey("VK_F5", {}, messageWindow); }); } finally { for (const win of windowsToClose) { await BrowserTestUtils.closeWindow(win); } await SimpleTest.promiseFocus(window); } });