Bug 1599991 - Copy mozmill tests to mochitest; r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net>
Tue, 19 Nov 2019 11:52:39 +1300
changeset 28309 825c14a55e122cec28b5e1f7d3ce83007d89f32c
parent 28308 c272f21f60cef07fc06efcbcabc5880014c90bce
child 28310 9a2171cc93933aa39ee042e7379548c8eacbd9e2
push id16761
push usergeoff@darktrojan.net
push dateWed, 04 Dec 2019 08:16:39 +0000
treeherdercomm-central@825c14a55e12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1599991
Bug 1599991 - Copy mozmill tests to mochitest; r=mkmelin
mail/base/content/gloda-autocomplete-input.js
mail/moz.build
mail/test/browser/account/browser.ini
mail/test/browser/account/browser_abWhitelist.js
mail/test/browser/account/browser_actions.js
mail/test/browser/account/browser_archiveOptions.js
mail/test/browser/account/browser_deletion.js
mail/test/browser/account/browser_mailAccountSetupWizard.js
mail/test/browser/account/browser_portSetting.js
mail/test/browser/account/browser_retestConfig.js
mail/test/browser/account/browser_settingsInfrastructure.js
mail/test/browser/account/browser_tree.js
mail/test/browser/account/browser_values.js
mail/test/browser/account/xml/example.com
mail/test/browser/account/xml/example.com^headers^
mail/test/browser/account/xml/momo.invalid
mail/test/browser/account/xml/momo.invalid^headers^
mail/test/browser/addrbook/browser.ini
mail/test/browser/addrbook/browser_addressBook.js
mail/test/browser/addrbook/browser_addressBookPanes.js
mail/test/browser/addrbook/browser_updateMailingList.js
mail/test/browser/attachment/browser.ini
mail/test/browser/attachment/browser_attachment.js
mail/test/browser/attachment/browser_attachmentEvents.js
mail/test/browser/attachment/browser_attachmentInPlainMsg.js
mail/test/browser/attachment/browser_attachmentMenus.js
mail/test/browser/attachment/browser_attachmentSize.js
mail/test/browser/attachment/data/attachment.txt
mail/test/browser/attachment/data/bug1358565.eml
mail/test/browser/cloudfile/browser.ini
mail/test/browser/cloudfile/browser_attachmentItem.js
mail/test/browser/cloudfile/browser_attachmentUrls.js
mail/test/browser/cloudfile/browser_manager.js
mail/test/browser/cloudfile/browser_notifications.js
mail/test/browser/cloudfile/data/testFile1
mail/test/browser/cloudfile/data/testFile2
mail/test/browser/cloudfile/data/testFile3
mail/test/browser/cloudfile/data/testFile4
mail/test/browser/cloudfile/head.js
mail/test/browser/cloudfile/html/settings-with-link.xhtml
mail/test/browser/composition/browser.ini
mail/test/browser/composition/browser_addressWidgets.js
mail/test/browser/composition/browser_attachment.js
mail/test/browser/composition/browser_attachmentReminder.js
mail/test/browser/composition/browser_base64Display.js
mail/test/browser/composition/browser_blockedContent.js
mail/test/browser/composition/browser_charsetEdit.js
mail/test/browser/composition/browser_charsetUpgrade.js
mail/test/browser/composition/browser_cp932Display.js
mail/test/browser/composition/browser_draftIdentity.js
mail/test/browser/composition/browser_drafts.js
mail/test/browser/composition/browser_emlActions.js
mail/test/browser/composition/browser_focus.js
mail/test/browser/composition/browser_forwardHeaders.js
mail/test/browser/composition/browser_forwardRFC822Attach.js
mail/test/browser/composition/browser_forwardUTF8.js
mail/test/browser/composition/browser_forwardedContent.js
mail/test/browser/composition/browser_forwardedEmlActions.js
mail/test/browser/composition/browser_imageDisplay.js
mail/test/browser/composition/browser_imageInsertionDialog.js
mail/test/browser/composition/browser_multipartRelated.js
mail/test/browser/composition/browser_newmsgComposeIdentity.js
mail/test/browser/composition/browser_replyAddresses.js
mail/test/browser/composition/browser_replyFormatFlowed.js
mail/test/browser/composition/browser_replyMultipartCharset.js
mail/test/browser/composition/browser_replySignature.js
mail/test/browser/composition/browser_saveChangesOnQuit.js
mail/test/browser/composition/browser_sendButton.js
mail/test/browser/composition/browser_sendFormat.js
mail/test/browser/composition/browser_signatureInit.js
mail/test/browser/composition/browser_signatureUpdating.js
mail/test/browser/composition/data/attachment.txt
mail/test/browser/composition/data/base64-encoded-msg.eml
mail/test/browser/composition/data/base64-with-whitespace.eml
mail/test/browser/composition/data/body-greek.eml
mail/test/browser/composition/data/body-utf16.eml
mail/test/browser/composition/data/charset-cp932.eml
mail/test/browser/composition/data/content-utf8-alt-rel.eml
mail/test/browser/composition/data/content-utf8-alt-rel2.eml
mail/test/browser/composition/data/content-utf8-rel-alt.eml
mail/test/browser/composition/data/content-utf8-rel-only.eml
mail/test/browser/composition/data/feed-message.eml
mail/test/browser/composition/data/format-flowed.eml
mail/test/browser/composition/data/format1-altering.eml
mail/test/browser/composition/data/format1-plain.eml
mail/test/browser/composition/data/format2-style-attr.eml
mail/test/browser/composition/data/format3-style-tag.eml
mail/test/browser/composition/data/long-html-line.eml
mail/test/browser/composition/data/mime-encoded-subject.eml
mail/test/browser/composition/data/multipart-charset.eml
mail/test/browser/composition/data/tb-logo.png
mail/test/browser/composition/data/testmsg.eml
mail/test/browser/content-policy/browser.ini
mail/test/browser/content-policy/browser_composeMailto.js
mail/test/browser/content-policy/browser_dnsPrefetch.js
mail/test/browser/content-policy/browser_exposedInContentTabs.js
mail/test/browser/content-policy/browser_generalContentPolicy.js
mail/test/browser/content-policy/browser_jsContentPolicy.js
mail/test/browser/content-policy/browser_pluginsPolicy.js
mail/test/browser/content-policy/browser_viewSource.js
mail/test/browser/content-policy/html/mailtolink.html
mail/test/browser/content-policy/html/pass.png
mail/test/browser/content-policy/html/plugin.html
mail/test/browser/content-policy/html/remote-noscript.html
mail/test/browser/content-policy/html/remoteimage.html
mail/test/browser/content-policy/html/remoteimagedata.html
mail/test/browser/content-policy/html/remotevideo.html
mail/test/browser/content-policy/html/video.ogv
mail/test/browser/content-tabs/browser.ini
mail/test/browser/content-tabs/browser_aboutSupport.js
mail/test/browser/content-tabs/browser_addonsMgr.js
mail/test/browser/content-tabs/browser_contentTab.js
mail/test/browser/content-tabs/browser_installXpi.js
mail/test/browser/content-tabs/html/blocklist.xml
mail/test/browser/content-tabs/html/blocklistHard.xml
mail/test/browser/content-tabs/html/blocklist_details.html
mail/test/browser/content-tabs/html/corrupt.xpi
mail/test/browser/content-tabs/html/dummy.xml
mail/test/browser/content-tabs/html/favicon.ico
mail/test/browser/content-tabs/html/installxpi.html
mail/test/browser/content-tabs/html/installxpi.xpi
mail/test/browser/content-tabs/html/plugin.html
mail/test/browser/content-tabs/html/plugin_crashed_help.html
mail/test/browser/content-tabs/html/plugin_update.html
mail/test/browser/content-tabs/html/test-lwthemes.html
mail/test/browser/content-tabs/html/test.png
mail/test/browser/content-tabs/html/webextension.xpi
mail/test/browser/content-tabs/html/whatsnew.html
mail/test/browser/content-tabs/html/whatsnew.png
mail/test/browser/content-tabs/html/whatsnew1.html
mail/test/browser/cookies/browser.ini
mail/test/browser/cookies/browser_cookies.js
mail/test/browser/cookies/html/cookietest1.html
mail/test/browser/cookies/html/cookietest2.html
mail/test/browser/downloads/browser.ini
mail/test/browser/downloads/browser_aboutDownloads.js
mail/test/browser/folder-display/browser.ini
mail/test/browser/folder-display/browser_archiveMessages.js
mail/test/browser/folder-display/browser_closeWindowOnDelete.js
mail/test/browser/folder-display/browser_columns.js
mail/test/browser/folder-display/browser_deletionFromVirtualFolders.js
mail/test/browser/folder-display/browser_deletionWithMultipleDisplays.js
mail/test/browser/folder-display/browser_displayName.js
mail/test/browser/folder-display/browser_folderPaneVisibility.js
mail/test/browser/folder-display/browser_folderToolbar.js
mail/test/browser/folder-display/browser_invalidDbFolderLoad.js
mail/test/browser/folder-display/browser_mailViews.js
mail/test/browser/folder-display/browser_messageCommands.js
mail/test/browser/folder-display/browser_messageCommandsOnMsgstore.js
mail/test/browser/folder-display/browser_messagePaneVisibility.js
mail/test/browser/folder-display/browser_messageReloads.js
mail/test/browser/folder-display/browser_messageSize.js
mail/test/browser/folder-display/browser_messageWindow.js
mail/test/browser/folder-display/browser_openingMessages.js
mail/test/browser/folder-display/browser_openingMessagesWithoutABackingView.js
mail/test/browser/folder-display/browser_paneFocus.js
mail/test/browser/folder-display/browser_recentMenu.js
mail/test/browser/folder-display/browser_rightClickMiddleClickFolders.js
mail/test/browser/folder-display/browser_rightClickMiddleClickMessages.js
mail/test/browser/folder-display/browser_savedsearchReloadAfterCompact.js
mail/test/browser/folder-display/browser_selection.js
mail/test/browser/folder-display/browser_summarization.js
mail/test/browser/folder-display/browser_tabsSimple.js
mail/test/browser/folder-display/browser_virtualFolderCommands.js
mail/test/browser/folder-display/browser_watchIgnoreThread.js
mail/test/browser/folder-pane/browser.ini
mail/test/browser/folder-pane/browser_displayMessageWithFolderModes.js
mail/test/browser/folder-pane/browser_folderNamesInRecentMode.js
mail/test/browser/folder-pane/browser_folderPane.js
mail/test/browser/folder-pane/browser_folderPaneConsumers.js
mail/test/browser/folder-tree-modes/browser.ini
mail/test/browser/folder-tree-modes/browser_customFolderTreeMode.js
mail/test/browser/folder-tree-modes/browser_customSmartFolder.js
mail/test/browser/folder-tree-modes/browser_modeSwitching.js
mail/test/browser/folder-tree-modes/browser_smartFolders.js
mail/test/browser/folder-tree-modes/browser_unreadFolders.js
mail/test/browser/folder-tree-modes/test-extension/bootstrap.js
mail/test/browser/folder-tree-modes/test-extension/chrome.manifest
mail/test/browser/folder-tree-modes/test-extension/manifest.json
mail/test/browser/folder-widget/browser.ini
mail/test/browser/folder-widget/browser_messageFilters.js
mail/test/browser/im/browser.ini
mail/test/browser/im/browser_chatTabRestore.js
mail/test/browser/im/browser_toolbarButtons.js
mail/test/browser/instrumentation/browser.ini
mail/test/browser/instrumentation/browser_instrumentSetup.js
mail/test/browser/junk-commands/browser.ini
mail/test/browser/junk-commands/browser_junkCommands.js
mail/test/browser/keyboard/browser.ini
mail/test/browser/keyboard/browser_spacehit.js
mail/test/browser/message-header/browser.ini
mail/test/browser/message-header/browser_messageHeader.js
mail/test/browser/message-header/browser_phishingBar.js
mail/test/browser/message-header/browser_replyIdentity.js
mail/test/browser/message-header/browser_replyToListFromAddressSelection.js
mail/test/browser/message-header/browser_returnReceipt.js
mail/test/browser/message-header/data/evil-attached.eml
mail/test/browser/message-header/data/evil.eml
mail/test/browser/message-reader/browser.ini
mail/test/browser/message-reader/browser_bug594646.js
mail/test/browser/message-reader/data/bug594646_newline_charset_8bit.eml
mail/test/browser/message-reader/data/bug594646_newline_charset_b64.eml
mail/test/browser/message-reader/data/bug594646_newline_charset_qp.eml
mail/test/browser/message-reader/data/bug594646_newline_httpequiv_8bit.eml
mail/test/browser/message-reader/data/bug594646_newline_httpequiv_b64.eml
mail/test/browser/message-reader/data/bug594646_newline_httpequiv_qp.eml
mail/test/browser/message-reader/data/bug594646_reference.eml
mail/test/browser/message-reader/data/bug594646_reversed_order_8bit.eml
mail/test/browser/message-reader/data/bug594646_reversed_order_b64.eml
mail/test/browser/message-reader/data/bug594646_reversed_order_qp.eml
mail/test/browser/message-window/browser.ini
mail/test/browser/message-window/browser_autohideMenubar.js
mail/test/browser/message-window/browser_commands.js
mail/test/browser/message-window/browser_emlSubject.js
mail/test/browser/message-window/browser_messageSidebar.js
mail/test/browser/message-window/browser_vcardActions.js
mail/test/browser/message-window/browser_viewPlaintext.js
mail/test/browser/message-window/data/emptySubject.eml
mail/test/browser/message-window/data/evil.eml
mail/test/browser/message-window/data/test-alt-HTML-missing.eml
mail/test/browser/message-window/data/test-alt-plain-HTML-reversed.eml
mail/test/browser/message-window/data/test-alt-plain-missing.eml
mail/test/browser/message-window/data/test-alt-rel-text.eml
mail/test/browser/message-window/data/test-alt-rel-with-attach.eml
mail/test/browser/message-window/data/test-alt-rel.eml
mail/test/browser/message-window/data/test-alt-rogue.eml
mail/test/browser/message-window/data/test-alt-rogue2.eml
mail/test/browser/message-window/data/test-alt.eml
mail/test/browser/message-window/data/test-rel-alt.eml
mail/test/browser/message-window/data/test-triple-alt.eml
mail/test/browser/message-window/data/test-vcard-icon.eml
mail/test/browser/moz.build
mail/test/browser/multiple-identities/browser.ini
mail/test/browser/multiple-identities/browser_displayNames.js
mail/test/browser/multiple-identities/readme.txt
mail/test/browser/newmailaccount/browser.ini
mail/test/browser/newmailaccount/browser_newmailaccount.js
mail/test/browser/newmailaccount/html/badSuggestFromName
mail/test/browser/newmailaccount/html/config.xml
mail/test/browser/newmailaccount/html/configCorrupt.xml
mail/test/browser/newmailaccount/html/configError.xml
mail/test/browser/newmailaccount/html/emptySuggestFromName
mail/test/browser/newmailaccount/html/providerList
mail/test/browser/newmailaccount/html/providerListBad
mail/test/browser/newmailaccount/html/providerListIncomplete
mail/test/browser/newmailaccount/html/providerListNoOtherLangs
mail/test/browser/newmailaccount/html/providerListWildcard
mail/test/browser/newmailaccount/html/registration.html
mail/test/browser/newmailaccount/html/registrationCorrupt.html
mail/test/browser/newmailaccount/html/registrationError.html
mail/test/browser/newmailaccount/html/suggestFromName
mail/test/browser/newmailaccount/html/target.html
mail/test/browser/notification/browser.ini
mail/test/browser/notification/browser_notification.js
mail/test/browser/override-main-menu-collapse/browser.ini
mail/test/browser/override-main-menu-collapse/browser_overrideMainmenuCollapse.js
mail/test/browser/pref-window/browser.ini
mail/test/browser/pref-window/browser_fontChooser.js
mail/test/browser/quick-filter-bar/browser.ini
mail/test/browser/quick-filter-bar/browser_displayIssues.js
mail/test/browser/quick-filter-bar/browser_filterLogic.js
mail/test/browser/quick-filter-bar/browser_keyboardInterface.js
mail/test/browser/quick-filter-bar/browser_stickyFilterLogic.js
mail/test/browser/quick-filter-bar/browser_toggleBar.js
mail/test/browser/search-window/browser.ini
mail/test/browser/search-window/browser_multipleSearchWindows.js
mail/test/browser/search-window/browser_rightClickToOpenSearchWindow.js
mail/test/browser/search-window/browser_searchWindow.js
mail/test/browser/session-store/browser.ini
mail/test/browser/session-store/browser_sessionStore.js
mail/test/browser/smime/browser.ini
mail/test/browser/smime/browser_multipartAlternative.js
mail/test/browser/smime/data/Bob.p12
mail/test/browser/smime/data/README.md
mail/test/browser/smime/data/TestCA.pem
mail/test/browser/smime/data/multipart-alternative.eml
mail/test/browser/startup-firstrun/browser.ini
mail/test/browser/startup-firstrun/browser_menubarCollapsed.js
mail/test/browser/subscribe/browser.ini
mail/test/browser/subscribe/browser_newsFilter.js
mail/test/browser/tabmail/browser.ini
mail/test/browser/tabmail/browser_closing.js
mail/test/browser/tabmail/browser_customize.js
mail/test/browser/tabmail/browser_dragndrop.js
mail/test/browser/utils/browser.ini
mail/test/browser/utils/browser_extensionSupport.js
mail/test/browser/utils/browser_iteratorUtils.js
mail/test/browser/utils/html/collections.html
mail/test/mozmill/cloudfile/test-cloudfile-manager.js
mail/test/mozmill/shared-modules/CloudfileHelpers.jsm
mail/test/mozmill/shared-modules/PrefTabHelpers.jsm
mozharness/unittests/thunderbird_extra.py
taskcluster/ci/test/tests.yml
--- a/mail/base/content/gloda-autocomplete-input.js
+++ b/mail/base/content/gloda-autocomplete-input.js
@@ -217,16 +217,17 @@ customElements.whenDefined("autocomplete
       this.value = "";
     }
 
     disconnectedCallback() {
       Services.obs.removeObserver(
         this.textObserver,
         "autocomplete-did-enter-text"
       );
+      this.hasConnected = false;
     }
   }
 
   MozXULElement.implementCustomInterface(MozGlodaAutocompleteInput, [
     Ci.nsIObserver,
   ]);
   customElements.define("gloda-autocomplete-input", MozGlodaAutocompleteInput, {
     extends: "input",
--- a/mail/moz.build
+++ b/mail/moz.build
@@ -16,11 +16,15 @@ DIRS += [
 ]
 
 if CONFIG['MAKENSISU']:
     DIRS += ['installer/windows']
 
 if CONFIG['MOZ_BUNDLED_FONTS']:
     DIRS += ['/%s/browser/fonts' % CONFIG['mozreltopsrcdir']]
 
-TEST_DIRS += ['test/mozmill', 'test/marionette']
+TEST_DIRS += [
+    'test/browser',
+    'test/marionette',
+    'test/mozmill',
+]
 
 FINAL_TARGET_FILES.defaults += ['app/permissions']
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/account/browser.ini
@@ -0,0 +1,59 @@
+[DEFAULT]
+prefs =
+  browser.tabs.remote.autostart=false
+  ldap_2.servers.osx.description=
+  ldap_2.servers.osx.dirType=-1
+  ldap_2.servers.osx.uri=
+  mail.account.account1.server=server1
+  mail.account.account2.identities=id1,id2
+  mail.account.account2.server=server2
+  mail.accountmanager.accounts=account1,account2
+  mail.accountmanager.defaultaccount=account2
+  mail.accountmanager.localfoldersserver=server1
+  mail.identity.id1.fullName=Tinderbox
+  mail.identity.id1.htmlSigFormat=false
+  mail.identity.id1.smtpServer=smtp1
+  mail.identity.id1.useremail=tinderbox@foo.invalid
+  mail.identity.id1.valid=true
+  mail.identity.id2.fullName=Tinderboxpushlog
+  mail.identity.id2.htmlSigFormat=true
+  mail.identity.id2.smtpServer=smtp1
+  mail.identity.id2.useremail=tinderboxpushlog@foo.invalid
+  mail.identity.id2.valid=true
+  mail.provider.suppress_dialog_on_startup=true
+  mail.server.server1.type=none
+  mail.server.server1.userName=nobody
+  mail.server.server2.check_new_mail=false
+  mail.server.server2.directory-rel=[ProfD]Mail/tinderbox
+  mail.server.server2.download_on_biff=true
+  mail.server.server2.hostname=tinderbox123
+  mail.server.server2.login_at_startup=false
+  mail.server.server2.name=tinderbox@foo.invalid
+  mail.server.server2.type=pop3
+  mail.server.server2.userName=tinderbox
+  mail.server.server2.whiteListAbURI=
+  mail.shell.checkDefaultClient=false
+  mail.smtp.defaultserver=smtp1
+  mail.smtpserver.smtp1.hostname=tinderbox123
+  mail.smtpserver.smtp1.username=tinderbox
+  mail.smtpservers=smtp1
+  mail.spotlight.firstRunDone=true
+  mail.winsearch.firstRunDone=true
+  mailnews.auto_config.addons_url=about:blank
+  mailnews.auto_config_url=about:blank
+  mailnews.start_page.override_url=about:blank
+  mailnews.start_page.url=about:blank
+subsuite = thunderbird
+support-files = xml/**
+
+[browser_abWhitelist.js]
+[browser_actions.js]
+[browser_archiveOptions.js]
+[browser_deletion.js]
+[browser_mailAccountSetupWizard.js]
+[browser_portSetting.js]
+skip-if = os == "win"
+[browser_retestConfig.js]
+[browser_settingsInfrastructure.js]
+[browser_tree.js]
+[browser_values.js]
copy from mail/test/mozmill/account/test-ab-whitelist.js
copy to mail/test/browser/account/browser_abWhitelist.js
--- a/mail/test/mozmill/account/test-ab-whitelist.js
+++ b/mail/test/browser/account/browser_abWhitelist.js
@@ -1,84 +1,79 @@
 /* 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/. */
 
 "use strict";
 
 var mozmill = ChromeUtils.import(
-  "chrome://mozmill/content/modules/mozmill.jsm"
+  "resource://testing-common/mozmill/mozmill.jsm"
 );
 var controller = ChromeUtils.import(
-  "chrome://mozmill/content/modules/controller.jsm"
+  "resource://testing-common/mozmill/controller.jsm"
 );
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var {
-  assert_equals,
-  assert_false,
-  assert_true,
-  FAKE_SERVER_HOSTNAME,
-} = ChromeUtils.import(
+var { FAKE_SERVER_HOSTNAME } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var gOldWhiteList = null;
 var gKeyString = null;
 
 var gAccount = null;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   let server = MailServices.accounts.FindServer(
     "tinderbox",
     FAKE_SERVER_HOSTNAME,
     "pop3"
   );
   gAccount = MailServices.accounts.FindAccountForServer(server);
   let serverKey = server.key;
 
   gKeyString = "mail.server." + serverKey + ".whiteListAbURI";
   gOldWhiteList = Services.prefs.getCharPref(gKeyString);
   Services.prefs.setCharPref(gKeyString, "");
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   Services.prefs.setCharPref(gKeyString, gOldWhiteList);
-}
+});
 
 /* First, test that when we initially load the account manager, that
  * we're not whitelisting any address books.  Then, we'll check all
  * address books and save.
  */
 function subtest_check_whitelist_init_and_save(amc) {
   // Ok, the advanced settings window is open.  Let's choose
   // the junkmail settings.
   let accountRow = get_account_tree_row(gAccount.key, "am-junk.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   let doc = amc.window.document.getElementById("contentFrame").contentDocument;
 
   // At this point, we shouldn't have anything checked, but we should have
   // the two default address books (Personal and Collected) displayed
   let list = doc.getElementById("whiteListAbURI");
-  assert_equals(
+  Assert.equal(
     2,
     list.getRowCount(),
     "There was an unexpected number of address books"
   );
 
   // Now we'll check both address books
   for (let i = 0; i < list.getRowCount(); i++) {
     let abNode = list.getItemAtIndex(i);
@@ -98,24 +93,24 @@ function subtest_check_whitelist_load_an
   click_account_tree_row(amc, accountRow);
 
   let doc = amc.window.document.getElementById("contentFrame").contentDocument;
   let list = doc.getElementById("whiteListAbURI");
   let whiteListURIs = Services.prefs.getCharPref(gKeyString).split(" ");
 
   for (let i = 0; i < list.getRowCount(); i++) {
     let abNode = list.getItemAtIndex(i);
-    assert_equals(
+    Assert.equal(
       "true",
       abNode.firstElementChild.getAttribute("checked"),
       "Should have been checked"
     );
     // Also ensure that the address book URI was properly saved in the
     // prefs
-    assert_true(whiteListURIs.includes(abNode.getAttribute("value")));
+    Assert.ok(whiteListURIs.includes(abNode.getAttribute("value")));
     // Now un-check that address book
     amc.click(new elib.Elem(abNode.firstElementChild));
   }
 
   // And close the dialog
   amc.window.document.getElementById("accountManager").acceptDialog();
 }
 
@@ -136,27 +131,27 @@ function subtest_check_whitelist_load_cl
     // out.
     throw Error(
       "The whitelist preference for this server wasn't properly cleared."
     );
   } catch (e) {}
 
   for (let i = 0; i < list.getRowCount(); i++) {
     let abNode = list.getItemAtIndex(i);
-    assert_equals(
+    Assert.equal(
       "false",
       abNode.firstElementChild.getAttribute("checked"),
       "Should not have been checked"
     );
     // Also ensure that the address book URI was properly cleared in the
     // prefs
-    assert_false(whiteListURIs.includes(abNode.getAttribute("value")));
+    Assert.ok(!whiteListURIs.includes(abNode.getAttribute("value")));
   }
 
   // And close the dialog
   amc.window.document.getElementById("accountManager").acceptDialog();
 }
 
-function test_address_book_whitelist() {
+add_task(function test_address_book_whitelist() {
   open_advanced_settings(subtest_check_whitelist_init_and_save);
   open_advanced_settings(subtest_check_whitelist_load_and_clear);
   open_advanced_settings(subtest_check_whitelist_load_cleared);
-}
+});
copy from mail/test/mozmill/account/test-account-actions.js
copy to mail/test/browser/account/browser_actions.js
--- a/mail/test/mozmill/account/test-account-actions.js
+++ b/mail/test/browser/account/browser_actions.js
@@ -6,39 +6,33 @@
 
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var {
-  assert_equals,
-  assert_not_equals,
-  assert_true,
-  close_popup,
-  wait_for_popup_to_open,
-} = ChromeUtils.import(
+var { close_popup, wait_for_popup_to_open } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var imapAccount, nntpAccount, originalAccountCount;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // There may be pre-existing accounts from other tests.
   originalAccountCount = MailServices.accounts.allServers.length;
   // There already should be a Local Folders account created.
   // It is needed for this test.
-  assert_true(MailServices.accounts.localFoldersServer);
+  Assert.ok(MailServices.accounts.localFoldersServer);
 
   // Create an IMAP server
   let imapServer = MailServices.accounts
     .createIncomingServer("nobody", "example.com", "imap")
     .QueryInterface(Ci.nsIImapIncomingServer);
 
   let identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox@example.com";
@@ -54,29 +48,29 @@ function setupModule(module) {
 
   identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox2@example.com";
 
   nntpAccount = MailServices.accounts.createAccount();
   nntpAccount.incomingServer = nntpServer;
   nntpAccount.addIdentity(identity);
   // Now there should be 2 more accounts.
-  assert_equals(
+  Assert.equal(
     MailServices.accounts.allServers.length,
     originalAccountCount + 2
   );
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   // Remove our test accounts to leave the profile clean.
   MailServices.accounts.removeAccount(nntpAccount);
   MailServices.accounts.removeAccount(imapAccount);
   // There should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, originalAccountCount);
-}
+  Assert.equal(MailServices.accounts.allServers.length, originalAccountCount);
+});
 
 /**
  * Check that the account actions for the account are enabled or disabled appropriately.
  *
  * @param amc          the account options controller
  * @param aAccountKey  the key of the account to select
  * @param aIsSetAsDefaultEnabled  true if the menuitem should be enabled, false otherwise
  * @param aIsRemoveEnabled        true if the menuitem should be enabled, false otherwise
@@ -93,44 +87,44 @@ function subtest_check_account_actions(
   let accountRow = get_account_tree_row(aAccountKey, null, amc);
   click_account_tree_row(amc, accountRow);
 
   // click the Actions Button to bring up the popup with menuitems to test
   amc.click(amc.eid("accountActionsButton"), 5, 5);
   wait_for_popup_to_open(amc.e("accountActionsDropdown"));
 
   let actionAddMailAccount = amc.e("accountActionsAddMailAccount");
-  assert_not_equals(actionAddMailAccount, undefined);
-  assert_equals(
+  Assert.notEqual(actionAddMailAccount, undefined);
+  Assert.equal(
     !actionAddMailAccount.getAttribute("disabled"),
     aIsAddAccountEnabled
   );
 
   let actionAddOtherAccount = amc.e("accountActionsAddOtherAccount");
-  assert_not_equals(actionAddOtherAccount, undefined);
-  assert_equals(
+  Assert.notEqual(actionAddOtherAccount, undefined);
+  Assert.equal(
     !actionAddOtherAccount.getAttribute("disabled"),
     aIsAddAccountEnabled
   );
 
   let actionSetDefault = amc.e("accountActionsDropdownSetDefault");
-  assert_not_equals(actionSetDefault, undefined);
-  assert_equals(
+  Assert.notEqual(actionSetDefault, undefined);
+  Assert.equal(
     !actionSetDefault.getAttribute("disabled"),
     aIsSetAsDefaultEnabled
   );
 
   let actionRemove = amc.e("accountActionsDropdownRemove");
-  assert_not_equals(actionRemove, undefined);
-  assert_equals(!actionRemove.getAttribute("disabled"), aIsRemoveEnabled);
+  Assert.notEqual(actionRemove, undefined);
+  Assert.equal(!actionRemove.getAttribute("disabled"), aIsRemoveEnabled);
 
   close_popup(amc, amc.eid("accountActionsDropdown"));
 }
 
-function test_account_actions() {
+add_task(function test_account_actions() {
   // IMAP account: can be default, can be removed.
   open_advanced_settings(function(amc) {
     subtest_check_account_actions(amc, imapAccount.key, true, true, true);
   });
 
   // NNTP (News) account: can't be default, can be removed.
   open_advanced_settings(function(amc) {
     subtest_check_account_actions(amc, nntpAccount.key, false, true, true);
@@ -188,9 +182,9 @@ function test_account_actions() {
   Services.prefs.lockPref(disableItemPref);
 
   open_advanced_settings(function(amc) {
     subtest_check_account_actions(amc, imapAccount.key, true, true, false);
   });
 
   Services.prefs.unlockPref(disableItemPref);
   Services.prefs.getDefaultBranch("").deleteBranch(disableItemPref);
-}
+});
copy from mail/test/mozmill/account/test-archive-options.js
copy to mail/test/browser/account/browser_archiveOptions.js
--- a/mail/test/mozmill/account/test-archive-options.js
+++ b/mail/test/browser/account/browser_archiveOptions.js
@@ -1,70 +1,70 @@
 /* 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/. */
 
 "use strict";
 
 var mozmill = ChromeUtils.import(
-  "chrome://mozmill/content/modules/mozmill.jsm"
+  "resource://testing-common/mozmill/mozmill.jsm"
 );
 var controller = ChromeUtils.import(
-  "chrome://mozmill/content/modules/controller.jsm"
+  "resource://testing-common/mozmill/controller.jsm"
 );
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
-var utils = ChromeUtils.import("chrome://mozmill/content/modules/utils.jsm");
+var utils = ChromeUtils.import("resource://testing-common/mozmill/utils.jsm");
 
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var { assert_equals, assert_false, assert_true, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var {
   plan_for_modal_dialog,
   plan_for_window_close,
   wait_for_modal_dialog,
   wait_for_window_close,
 } = ChromeUtils.import("resource://testing-common/mozmill/WindowHelpers.jsm");
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var defaultIdentity;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   defaultIdentity = MailServices.accounts.defaultAccount.defaultIdentity;
-}
+});
 
 /**
  * Check that the archive options button is enabled or disabled appropriately.
  *
  * @param amc          the account options controller
  * @param aAccountKey  key of the account the check
  * @param isEnabled    true if the button should be enabled, false otherwise
  */
 function subtest_check_archive_options_enabled(amc, aAccountKey, isEnabled) {
   let accountRow = get_account_tree_row(aAccountKey, "am-copies.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.window.document.getElementById("contentFrame");
   let button = iframe.contentDocument.getElementById("archiveHierarchyButton");
 
-  assert_equals(button.disabled, !isEnabled);
+  Assert.equal(button.disabled, !isEnabled);
 }
 
-function test_archive_options_enabled() {
+add_task(function test_archive_options_enabled() {
   let defaultAccount = MailServices.accounts.defaultAccount;
   // First, create an IMAP server
   let imapServer = MailServices.accounts
     .createIncomingServer("nobody", "example.com", "imap")
     .QueryInterface(Ci.nsIImapIncomingServer);
 
   let identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox@example.com";
@@ -93,116 +93,113 @@ function test_archive_options_enabled() 
   open_advanced_settings(function(amc) {
     subtest_check_archive_options_enabled(amc, account.key, false);
   });
   open_advanced_settings(function(amc) {
     subtest_check_archive_options_enabled(amc, defaultAccount.key, false);
   });
 
   MailServices.accounts.removeAccount(account);
-}
+});
 
 function subtest_initial_state(identity) {
   plan_for_modal_dialog("archive-options", function(ac) {
-    assert_equals(
+    Assert.equal(
       ac.e("archiveGranularity").selectedIndex,
       identity.archiveGranularity
     );
-    assert_equals(
+    Assert.equal(
       ac.e("archiveKeepFolderStructure").checked,
       identity.archiveKeepFolderStructure
     );
   });
   mc.window.openDialog(
     "chrome://messenger/content/am-archiveoptions.xul",
     "",
     "centerscreen,chrome,modal,titlebar,resizable=yes",
     identity
   );
   wait_for_modal_dialog("archive-options");
 }
 
-function test_open_archive_options() {
+add_task(function test_open_archive_options() {
   for (let granularity = 0; granularity < 3; granularity++) {
     defaultIdentity.archiveGranularity = granularity;
     for (let kfs = 0; kfs < 2; kfs++) {
       defaultIdentity.archiveKeepFolderStructure = kfs;
       subtest_initial_state(defaultIdentity);
     }
   }
-}
+});
 
 function subtest_save_state(identity, granularity, kfs) {
   plan_for_modal_dialog("archive-options", function(ac) {
     ac.e("archiveGranularity").selectedIndex = granularity;
     ac.e("archiveKeepFolderStructure").checked = kfs;
     ac.keypress(null, "VK_RETURN", {});
   });
   mc.window.openDialog(
     "chrome://messenger/content/am-archiveoptions.xul",
     "",
     "centerscreen,chrome,modal,titlebar,resizable=yes",
     identity
   );
   wait_for_modal_dialog("archive-options");
 }
 
-function test_save_archive_options() {
+add_task(function test_save_archive_options() {
   defaultIdentity.archiveGranularity = 0;
   defaultIdentity.archiveKeepFolderStructure = false;
   subtest_save_state(defaultIdentity, 1, true);
 
-  assert_equals(defaultIdentity.archiveGranularity, 1);
-  assert_equals(defaultIdentity.archiveKeepFolderStructure, true);
-}
+  Assert.equal(defaultIdentity.archiveGranularity, 1);
+  Assert.equal(defaultIdentity.archiveKeepFolderStructure, true);
+});
 
 function subtest_check_archive_enabled(amc, archiveEnabled) {
   defaultIdentity.archiveEnabled = archiveEnabled;
 
   click_account_tree_row(amc, 2);
 
   let iframe = amc.window.document.getElementById("contentFrame");
   let checkbox = iframe.contentDocument.getElementById(
     "identity.archiveEnabled"
   );
 
-  assert_equals(checkbox.checked, archiveEnabled);
+  Assert.equal(checkbox.checked, archiveEnabled);
 }
 
-function test_archive_enabled() {
+add_task(function test_archive_enabled() {
   open_advanced_settings(function(amc) {
     subtest_check_archive_enabled(amc, true);
   });
 
   open_advanced_settings(function(amc) {
     subtest_check_archive_enabled(amc, false);
   });
-}
+});
 
 function subtest_disable_archive(amc) {
   defaultIdentity.archiveEnabled = true;
   click_account_tree_row(amc, 2);
 
   let iframe = amc.window.document.getElementById("contentFrame");
   let checkbox = iframe.contentDocument.getElementById(
     "identity.archiveEnabled"
   );
 
-  assert_true(checkbox.checked);
-  assert_false(checkbox.disabled);
+  Assert.ok(checkbox.checked);
+  Assert.ok(!checkbox.disabled);
   amc.click(new elib.Elem(checkbox));
   utils.waitFor(
     () => !checkbox.checked,
     "Archive checkbox didn't toggle to unchecked"
   );
   plan_for_window_close(amc);
   amc.window.document.getElementById("accountManager").acceptDialog();
   wait_for_window_close();
 
-  assert_false(defaultIdentity.archiveEnabled);
+  Assert.ok(!defaultIdentity.archiveEnabled);
 }
 
-function test_disable_archive() {
+add_task(function test_disable_archive() {
   open_advanced_settings(subtest_disable_archive);
-}
-// Disable test on Windows since for some yet unknown reason clicking the checkbox
-// doesn't have the desired result. See bug 1461173 for details.
-test_disable_archive.EXCLUDED_PLATFORMS = ["winnt"];
+});
copy from mail/test/mozmill/account/test-account-deletion.js
copy to mail/test/browser/account/browser_deletion.js
--- a/mail/test/mozmill/account/test-account-deletion.js
+++ b/mail/test/browser/account/browser_deletion.js
@@ -6,27 +6,24 @@
  * This test checks proper deletion of an account from the Account manager.
  */
 
 "use strict";
 
 var { open_advanced_settings, remove_account } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var { assert_equals, assert_false, assert_true } = ChromeUtils.import(
-  "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
-);
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var gPopAccount, gImapAccount, gOriginalAccountCount;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // There may be pre-existing accounts from other tests.
   gOriginalAccountCount = MailServices.accounts.allServers.length;
 
   // Create a POP server
   let popServer = MailServices.accounts
     .createIncomingServer("nobody", "pop.foo.invalid", "pop3")
     .QueryInterface(Ci.nsIPop3IncomingServer);
 
@@ -44,68 +41,68 @@ function setupModule(module) {
 
   identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox@imap.foo.invalid";
 
   gImapAccount = MailServices.accounts.createAccount();
   gImapAccount.incomingServer = imapServer;
   gImapAccount.addIdentity(identity);
 
-  assert_equals(
+  Assert.equal(
     MailServices.accounts.allServers.length,
     gOriginalAccountCount + 2
   );
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   // There should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, gOriginalAccountCount);
-}
+  Assert.equal(MailServices.accounts.allServers.length, gOriginalAccountCount);
+});
 
-function test_account_data_deletion() {
+add_task(function test_account_data_deletion() {
   open_advanced_settings(function(amc) {
     subtest_account_data_deletion1(amc);
   });
 
   open_advanced_settings(function(amc) {
     subtest_account_data_deletion2(amc);
   });
-}
+});
 
 /**
  * Bug 274452
  * Check if files of an account are preserved.
  *
  * @param amc  The account options controller.
  */
 function subtest_account_data_deletion1(amc) {
   let accountDir = gPopAccount.incomingServer.localPath;
-  assert_true(accountDir.isDirectory());
+  Assert.ok(accountDir.isDirectory());
 
   // Get some existing file in the POP3 account data dir.
   let inboxFile = accountDir.clone();
   inboxFile.append("Inbox.msf");
-  assert_true(inboxFile.isFile());
+  Assert.ok(inboxFile.isFile());
 
   remove_account(gPopAccount, amc, true, false);
   gPopAccount = null;
-  assert_true(accountDir.exists());
+  Assert.ok(accountDir.exists());
 }
 
 /**
  * Bug 274452
  * Check if files of an account can be deleted.
  *
  * @param amc  The account options controller.
  */
 function subtest_account_data_deletion2(amc) {
   let accountDir = gImapAccount.incomingServer.localPath;
-  assert_true(accountDir.isDirectory());
+  Assert.ok(accountDir.isDirectory());
 
   // Get some file in the IMAP account data dir.
   let inboxFile = accountDir.clone();
   inboxFile.append("INBOX.msf");
-  assert_true(inboxFile.isFile());
+  Assert.ok(inboxFile.isFile());
 
   remove_account(gImapAccount, amc, true, true);
   gImapAccount = null;
-  assert_false(accountDir.exists());
+  Assert.ok(!accountDir.exists());
 }
copy from mail/test/mozmill/account/test-mail-account-setup-wizard.js
copy to mail/test/browser/account/browser_mailAccountSetupWizard.js
--- a/mail/test/mozmill/account/test-mail-account-setup-wizard.js
+++ b/mail/test/browser/account/browser_mailAccountSetupWizard.js
@@ -1,25 +1,25 @@
 /* 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/. */
 
 "use strict";
 
-var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+var elementslib = ChromeUtils.import(
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 
 var {
   open_advanced_settings_from_account_wizard,
   open_mail_account_setup_wizard,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var { assert_equals, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { input_value, delete_all_existing } = ChromeUtils.import(
   "resource://testing-common/mozmill/KeyboardHelpers.jsm"
 );
 var { gMockPromptService } = ChromeUtils.import(
   "resource://testing-common/mozmill/PromptHelpers.jsm"
 );
@@ -32,16 +32,19 @@ var { MailServices } = ChromeUtils.impor
 var user = {
   name: "Yamato Nadeshiko",
   email: "yamato.nadeshiko@example.com",
   password: "abc12345",
   incomingHost: "testin.example.com",
   outgoingHost: "testout.example.com",
 };
 
+const PREF_NAME = "mailnews.auto_config_url";
+const PREF_VALUE = Services.prefs.getCharPref(PREF_NAME);
+
 // Remove an account in the Account Manager, but not via the UI.
 function remove_account_internal(amc, aAccount, aOutgoing) {
   let win = amc.window;
 
   try {
     // Remove the account and incoming server
     let serverId = aAccount.incomingServer.serverURI;
     MailServices.accounts.removeAccount(aAccount);
@@ -55,24 +58,21 @@ function remove_account_internal(amc, aA
     let smtpKey = aOutgoing.key;
     MailServices.smtp.deleteServer(aOutgoing);
     win.replaceWithDefaultSmtpServer(smtpKey);
   } catch (ex) {
     throw new Error("failure to remove account: " + ex + "\n");
   }
 }
 
-function test_mail_account_setup() {
+add_task(function test_mail_account_setup() {
   // Set the pref to load a local autoconfig file.
-  let pref_name = "mailnews.auto_config_url";
-  let url = collector.addHttpResource("../account/xml", "autoconfig");
-  Services.prefs.setCharPref(pref_name, url);
-
-  // Force .com MIME-Type to text/xml
-  collector.httpd.registerContentType("com", "text/xml");
+  let url =
+    "http://mochi.test:8888/browser/comm/mail/test/browser/account/xml/";
+  Services.prefs.setCharPref(PREF_NAME, url);
 
   open_mail_account_setup_wizard(function(awc) {
     // Input user's account information
     awc.click(awc.eid("realname"));
     if (awc.e("realname").value) {
       // If any realname is already filled, clear it out, we have our own.
       delete_all_existing(awc, awc.eid("realname"));
     }
@@ -98,23 +98,23 @@ function test_mail_account_setup() {
     gMockPromptService.returnValue = true;
 
     // Open the advanced settings (Account Manager) to create the account
     // immediately.  We use an invalid email/password so the setup will fail
     // anyway.
     open_advanced_settings_from_account_wizard(subtest_verify_account, awc);
 
     let promptState = gMockPromptService.promptState;
-    assert_equals("confirm", promptState.method);
+    Assert.equal("confirm", promptState.method);
 
     // Clean up
     gMockPromptService.unregister();
-    Services.prefs.clearUserPref(pref_name);
+    Services.prefs.setCharPref(PREF_NAME, PREF_VALUE);
   });
-}
+});
 
 function subtest_verify_account(amc) {
   amc.waitFor(
     () => amc.window.currentAccount != null,
     "Timeout waiting for currentAccount to become non-null"
   );
   let account = amc.window.currentAccount;
   let identity = account.defaultIdentity;
@@ -162,26 +162,23 @@ function subtest_verify_account(amc) {
     remove_account_internal(amc, account, outgoing);
   }
 }
 
 /**
  * Make sure that we don't re-set the information we get from the config
  * file if the password is incorrect.
  */
-function test_bad_password_uses_old_settings() {
+add_task(function test_bad_password_uses_old_settings() {
   // Set the pref to load a local autoconfig file, that will fetch the
   // ../account/xml/example.com which contains the settings for the
   // @example.com email account (see the 'user' object).
-  let pref_name = "mailnews.auto_config_url";
-  let url = collector.addHttpResource("../account/xml", "autoconfig");
-  Services.prefs.setCharPref(pref_name, url);
-
-  // Force .com MIME-Type to text/xml
-  collector.httpd.registerContentType("com", "text/xml");
+  let url =
+    "http://mochi.test:8888/browser/comm/mail/test/browser/account/xml/";
+  Services.prefs.setCharPref(PREF_NAME, url);
 
   mc.sleep(0);
   open_mail_account_setup_wizard(function(awc) {
     try {
       // Input user's account information
       awc.click(awc.eid("realname"));
       if (awc.e("realname").value) {
         // If any realname is already filled, clear it out, we have our own.
@@ -216,38 +213,38 @@ function test_bad_password_uses_old_sett
         600,
         awc.e("create_button")
       );
       awc.e("create_button").click();
       awc.e("manual-edit_button").click();
 
       // Make sure all the values are the same as in the user object.
       awc.sleep(1000);
-      assert_equals(
+      Assert.equal(
         awc.e("outgoing_hostname").value,
         user.outgoingHost,
         "Outgoing server changed!"
       );
-      assert_equals(
+      Assert.equal(
         awc.e("incoming_hostname").value,
         user.incomingHost,
         "incoming server changed!"
       );
     } finally {
       // Clean up
-      Services.prefs.clearUserPref(pref_name);
+      Services.prefs.setCharPref(PREF_NAME, PREF_VALUE);
       awc.e("cancel_button").click();
     }
   });
-}
+});
 
-function test_remember_password() {
+add_task(function test_remember_password() {
   remember_password_test(true);
   remember_password_test(false);
-}
+});
 
 /**
  * Test remember_password checkbox behavior with
  * signon.rememberSignons set to "aPrefValue"
  */
 function remember_password_test(aPrefValue) {
   // save the pref for backup purpose
   let rememberSignons_pref_save = Services.prefs.getBoolPref(
copy from mail/test/mozmill/account/test-account-port-setting.js
copy to mail/test/browser/account/browser_portSetting.js
--- a/mail/test/mozmill/account/test-account-port-setting.js
+++ b/mail/test/browser/account/browser_portSetting.js
@@ -1,16 +1,16 @@
 /* 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/. */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
@@ -74,19 +74,26 @@ function subtest_check_set_port_number(a
     )
   );
 }
 
 function subtest_check_port_number(amc) {
   subtest_check_set_port_number(amc, true);
 }
 
-function test_account_port_setting() {
+add_task(function test_account_port_setting() {
   for (
     gTestNumber = 1;
     gTestNumber < PORT_NUMBERS_TO_TEST.length;
     ++gTestNumber
   ) {
     open_advanced_settings(subtest_check_set_port_number);
   }
 
   open_advanced_settings(subtest_check_port_number);
-}
+
+  Assert.report(
+    false,
+    undefined,
+    undefined,
+    "Test ran to completion successfully"
+  );
+});
copy from mail/test/mozmill/account/test-retest-config.js
copy to mail/test/browser/account/browser_retestConfig.js
--- a/mail/test/mozmill/account/test-retest-config.js
+++ b/mail/test/browser/account/browser_retestConfig.js
@@ -1,22 +1,22 @@
 /* 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/. */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 
 var { open_mail_account_setup_wizard } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var { assert_true, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { input_value, delete_all_existing } = ChromeUtils.import(
   "resource://testing-common/mozmill/KeyboardHelpers.jsm"
 );
 var { close_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
@@ -24,30 +24,33 @@ var { close_window } = ChromeUtils.impor
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var user = {
   name: "test",
   email: "test@momo.invalid",
   altEmail: "test2@momo.invalid",
 };
 
-function setupModule(module) {
+const PREF_NAME = "mailnews.auto_config_url";
+const PREF_VALUE = Services.prefs.getCharPref(PREF_NAME);
+
+add_task(function setupModule(module) {
   Services.prefs.setCharPref("mail.wizard.logging.dump", "All");
 
-  let url = collector.addHttpResource("../account/xml", "accountconfig");
-  Services.prefs.setCharPref("mailnews.auto_config_url", url);
-  collector.httpd.registerContentType("invalid", "text/xml");
-}
+  let url =
+    "http://mochi.test:8888/browser/comm/mail/test/browser/account/xml/";
+  Services.prefs.setCharPref(PREF_NAME, url);
+});
 
-function tearDownModule(module) {
-  Services.prefs.clearUserPref("mailnews.auto_config_url");
+registerCleanupFunction(function teardownModule(module) {
+  Services.prefs.setCharPref(PREF_NAME, PREF_VALUE);
   Services.prefs.clearUserPref("mail.wizard.logging.dump");
-}
+});
 
-function test_re_test_config() {
+add_task(function test_re_test_config() {
   // Opening multiple windows in the same run seems to require letting the stack
   // unwind before opening the next one, so do that here.
   mc.sleep(0);
   open_mail_account_setup_wizard(function(awc) {
     // Input user's account information
     awc.click(awc.eid("realname"));
     if (awc.e("realname").value) {
       // If any realname is already filled, clear it out, we have our own.
@@ -106,16 +109,16 @@ function test_re_test_config() {
       awc.e("next_button")
     );
 
     awc.e("next_button").click();
 
     // Previously, we'd switched to the manual editing state. Now we've started
     // over, we should make sure the information is presented back in its original
     // "automatic" mode.
-    assert_true(
+    Assert.ok(
       awc.e("manual-edit_area").hidden,
       "We're not back to the original state!"
     );
 
     close_window(awc);
   });
-}
+});
copy from mail/test/mozmill/account/test-account-settings-infrastructure.js
copy to mail/test/browser/account/browser_settingsInfrastructure.js
--- a/mail/test/mozmill/account/test-account-settings-infrastructure.js
+++ b/mail/test/browser/account/browser_settingsInfrastructure.js
@@ -8,43 +8,38 @@
  * panes are switched.
  *
  * New checks can be added to it as needed.
  */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var {
-  assert_equals,
-  assert_false,
-  assert_true,
-  FAKE_SERVER_HOSTNAME,
-} = ChromeUtils.import(
+var { FAKE_SERVER_HOSTNAME } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var gPopAccount, gImapAccount, gOriginalAccountCount;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // There may be pre-existing accounts from other tests.
   gOriginalAccountCount = MailServices.accounts.allServers.length;
 
   // Create a POP server
   let popServer = MailServices.accounts
     .createIncomingServer("nobody", "pop.invalid", "pop3")
     .QueryInterface(Ci.nsIPop3IncomingServer);
 
@@ -63,96 +58,96 @@ function setupModule(module) {
   identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox@imap.invalid";
 
   gImapAccount = MailServices.accounts.createAccount();
   gImapAccount.incomingServer = imapServer;
   gImapAccount.addIdentity(identity);
 
   // Now there should be one more account.
-  assert_equals(
+  Assert.equal(
     MailServices.accounts.allServers.length,
     gOriginalAccountCount + 2
   );
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   // Remove our test accounts to leave the profile clean.
   MailServices.accounts.removeAccount(gPopAccount);
   MailServices.accounts.removeAccount(gImapAccount);
 
   // There should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, gOriginalAccountCount);
-}
+  Assert.equal(MailServices.accounts.allServers.length, gOriginalAccountCount);
+});
 
 /**
  * Bug 525024.
  * Check that the options in the server pane are properly preserved across
  * pane switches.
  */
-function test_account_dot_IDs() {
+add_task(function test_account_dot_IDs() {
   open_advanced_settings(function(amc) {
     subtest_check_account_dot_IDs(amc);
   });
-}
+});
 
 /**
  * Check that the options in the server pane are stored even if the id
  * of the element contains multiple dots (not used in standard TB yet
  * but extensions may want it).
  *
  * @param amc  the account options controller
  */
 function subtest_check_account_dot_IDs(amc) {
   let accountRow = get_account_tree_row(gPopAccount.key, "am-server.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.e("contentFrame").contentDocument;
   // Check whether a standard element with "server.loginAtStartUp" stores its
   // value properly.
   let loginCheck = iframe.getElementById("server.loginAtStartUp");
-  assert_false(loginCheck.checked);
+  Assert.ok(!loginCheck.checked);
   amc.check(new elib.Elem(loginCheck), true);
 
   accountRow = get_account_tree_row(gPopAccount.key, "am-junk.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   accountRow = get_account_tree_row(gPopAccount.key, "am-server.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   // Re-assign iframe.contentDocument because it was lost when changing panes
   // (uses loadURI to load a new document).
   iframe = amc.e("contentFrame").contentDocument;
 
   // Check by element properties.
   loginCheck = iframe.getElementById("server.loginAtStartUp");
-  assert_true(loginCheck.checked);
+  Assert.ok(loginCheck.checked);
 
   // Check for correct value in the accountValues array, that will be saved into prefs.
   let rawCheckValue = amc.window.getAccountValue(
     gPopAccount,
     amc.window.getValueArrayFor(gPopAccount),
     "server",
     "loginAtStartUp",
     null,
     false
   );
 
-  assert_true(rawCheckValue);
+  Assert.ok(rawCheckValue);
 
   // The "server.login.At.StartUp" value does not exist yet, so the value should be 'null'.
   rawCheckValue = amc.window.getAccountValue(
     gPopAccount,
     amc.window.getValueArrayFor(gPopAccount),
     "server",
     "login.At.StartUp",
     null,
     false
   );
-  assert_equals(rawCheckValue, null);
+  Assert.equal(rawCheckValue, null);
 
   // Change the ID so that "server.login.At.StartUp" exists now.
   loginCheck.id = "server.login.At.StartUp";
 
   accountRow = get_account_tree_row(gPopAccount.key, "am-junk.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   accountRow = get_account_tree_row(gPopAccount.key, "am-server.xul", amc);
@@ -165,32 +160,32 @@ function subtest_check_account_dot_IDs(a
     gPopAccount,
     amc.window.getValueArrayFor(gPopAccount),
     "server",
     "login.At.StartUp",
     null,
     false
   );
 
-  assert_true(rawCheckValue);
+  Assert.ok(rawCheckValue);
 }
 
 /**
  * Test for bug 807101.
  * Check if form controls are properly disabled when their attached prefs are locked.
  */
-function test_account_locked_prefs() {
+add_task(function test_account_locked_prefs() {
   open_advanced_settings(function(amc) {
     subtest_check_locked_prefs_addressing(amc);
   });
 
   open_advanced_settings(function(amc) {
     subtest_check_locked_prefs_server(amc);
   });
-}
+});
 
 /**
  * Check that the LDAP server selection elements (radio group) are properly
  * disabled when their attached pref (prefstring attribute) is locked.
  *
  * @param amc  the account options controller
  */
 function subtest_check_locked_prefs_addressing(amc) {
@@ -201,31 +196,31 @@ function subtest_check_locked_prefs_addr
   );
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.e("contentFrame").contentDocument;
 
   // By default, 'use global LDAP server preferences' is set, not the
   // 'different LDAP server'.
   let useLDAPdirectory = iframe.getElementById("directories");
-  assert_false(useLDAPdirectory.selected);
+  Assert.ok(!useLDAPdirectory.selected);
 
   // So the server selector is disabled.
   let LDAPdirectory = iframe.getElementById("identity.directoryServer");
-  assert_true(LDAPdirectory.disabled);
+  Assert.ok(LDAPdirectory.disabled);
 
   // And the Edit button too.
   let LDAPeditButton = iframe.getElementById("editButton");
-  assert_true(LDAPeditButton.disabled);
+  Assert.ok(LDAPeditButton.disabled);
 
   // Now toggle the 'different LDAP server' on. The server selector
   // and edit button should enable.
   amc.radio(new elib.Elem(useLDAPdirectory));
-  assert_false(LDAPdirectory.disabled);
-  assert_false(LDAPeditButton.disabled);
+  Assert.ok(!LDAPdirectory.disabled);
+  Assert.ok(!LDAPeditButton.disabled);
 
   // Lock the pref for the server selector.
   let prefstring = LDAPdirectory.getAttribute("prefstring");
   let controlPref = prefstring.replace(
     "%identitykey%",
     gPopAccount.defaultIdentity.key
   );
   Services.prefs.getDefaultBranch("").setBoolPref(controlPref, "xxx");
@@ -240,25 +235,25 @@ function subtest_check_locked_prefs_addr
 
   // Re-assign iframe.contentDocument because it was lost when changing panes
   // (uses loadURI to load a new document).
   iframe = amc.e("contentFrame").contentDocument;
 
   // We are now back and the 'different LDAP server' should still be selected
   // (the setting was saved).
   useLDAPdirectory = iframe.getElementById("directories");
-  assert_true(useLDAPdirectory.selected);
+  Assert.ok(useLDAPdirectory.selected);
 
   // But now the server selector should be disabled due to locked pref.
   LDAPdirectory = iframe.getElementById("identity.directoryServer");
-  assert_true(LDAPdirectory.disabled);
+  Assert.ok(LDAPdirectory.disabled);
 
   // The edit button still enabled (does not depend on the same pref lock)
   LDAPeditButton = iframe.getElementById("editButton");
-  assert_false(LDAPeditButton.disabled);
+  Assert.ok(!LDAPeditButton.disabled);
 
   // Unlock the pref to clean up.
   Services.prefs.unlockPref(controlPref);
   Services.prefs.getDefaultBranch("").deleteBranch(controlPref);
 }
 
 /**
  * Check that the POP3 'keep on server' settings elements (2-level
@@ -270,38 +265,38 @@ function subtest_check_locked_prefs_addr
 function subtest_check_locked_prefs_server(amc) {
   let accountRow = get_account_tree_row(gPopAccount.key, "am-server.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.e("contentFrame").contentDocument;
 
   // Top level leaveOnServer checkbox, disabled by default.
   let leaveOnServer = iframe.getElementById("pop3.leaveMessagesOnServer");
-  assert_false(leaveOnServer.disabled);
-  assert_false(leaveOnServer.checked);
+  Assert.ok(!leaveOnServer.disabled);
+  Assert.ok(!leaveOnServer.checked);
 
   // Second level deleteByAge checkbox, disabled by default.
   let deleteByAge = iframe.getElementById("pop3.deleteByAgeFromServer");
-  assert_true(deleteByAge.disabled);
-  assert_false(deleteByAge.checked);
+  Assert.ok(deleteByAge.disabled);
+  Assert.ok(!deleteByAge.checked);
 
   // Third level daysToLeave textbox, disabled by default.
   let daysToLeave = iframe.getElementById("pop3.numDaysToLeaveOnServer");
-  assert_true(daysToLeave.disabled);
+  Assert.ok(daysToLeave.disabled);
 
   // When leaveOnServer is checked, only deleteByAge will get enabled.
   amc.check(new elib.Elem(leaveOnServer), true);
-  assert_true(leaveOnServer.checked);
-  assert_false(deleteByAge.disabled);
-  assert_true(daysToLeave.disabled);
+  Assert.ok(leaveOnServer.checked);
+  Assert.ok(!deleteByAge.disabled);
+  Assert.ok(daysToLeave.disabled);
 
   // When deleteByAge is checked, daysToLeave will get enabled.
   amc.check(new elib.Elem(deleteByAge), true);
-  assert_true(deleteByAge.checked);
-  assert_false(daysToLeave.disabled);
+  Assert.ok(deleteByAge.checked);
+  Assert.ok(!daysToLeave.disabled);
 
   // Lock the pref deleteByAge checkbox (middle of the element hierarchy).
   let prefstring = deleteByAge.getAttribute("prefstring");
   let controlPref = prefstring.replace(
     "%serverkey%",
     gPopAccount.incomingServer.key
   );
   Services.prefs.getDefaultBranch("").setBoolPref(controlPref, true);
@@ -315,67 +310,67 @@ function subtest_check_locked_prefs_serv
   click_account_tree_row(amc, accountRow);
 
   // Re-assign iframe.contentDocument because it was lost when changing panes
   // (uses loadURI to load a new document).
   iframe = amc.e("contentFrame").contentDocument;
 
   // Now leaveOnServer was preserved as checked.
   leaveOnServer = iframe.getElementById("pop3.leaveMessagesOnServer");
-  assert_false(leaveOnServer.disabled);
-  assert_true(leaveOnServer.checked);
+  Assert.ok(!leaveOnServer.disabled);
+  Assert.ok(leaveOnServer.checked);
 
   // Now deleteByAge was preserved as checked but is locked/disabled.
   deleteByAge = iframe.getElementById("pop3.deleteByAgeFromServer");
-  assert_true(deleteByAge.disabled);
-  assert_true(deleteByAge.checked);
+  Assert.ok(deleteByAge.disabled);
+  Assert.ok(deleteByAge.checked);
 
   // Because deleteByAge is checked, daysToLeave should be enabled.
   daysToLeave = iframe.getElementById("pop3.numDaysToLeaveOnServer");
-  assert_false(daysToLeave.disabled);
+  Assert.ok(!daysToLeave.disabled);
 
   // When leaveOnserver is unchecked, both of deleteByAge and daysToLeave
   // should get disabled.
   amc.check(new elib.Elem(leaveOnServer), false);
-  assert_false(leaveOnServer.disabled);
-  assert_false(leaveOnServer.checked);
+  Assert.ok(!leaveOnServer.disabled);
+  Assert.ok(!leaveOnServer.checked);
 
-  assert_true(deleteByAge.disabled);
-  assert_true(deleteByAge.checked);
-  assert_true(daysToLeave.disabled);
+  Assert.ok(deleteByAge.disabled);
+  Assert.ok(deleteByAge.checked);
+  Assert.ok(daysToLeave.disabled);
 
   // Unlock the pref to clean up.
   Services.prefs.unlockPref(controlPref);
   Services.prefs.getDefaultBranch("").deleteBranch(controlPref);
 }
 
 /**
  * Bug 530142.
  * Check that that if one field is set to a value, switching directly to another
  * account pane showing the same field really loads the value from the new account,
  * even when empty. This is tested on the Reply-To field.
  */
-function test_replyTo_leak() {
+add_task(function test_replyTo_leak() {
   open_advanced_settings(function(amc) {
     subtest_check_replyTo_leak(amc);
   });
-}
+});
 
 /**
  * @param amc  the account options controller
  */
 function subtest_check_replyTo_leak(amc) {
   let accountRow = get_account_tree_row(gPopAccount.key, null, amc);
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.window.document.getElementById("contentFrame");
 
   // The Reply-To field should be empty.
   let replyAddress = iframe.contentDocument.getElementById("identity.replyTo");
-  assert_equals(replyAddress.value, "");
+  Assert.equal(replyAddress.value, "");
 
   // Now we set a value into it and switch to another account, the main pane.
   replyAddress.value = "somewhere@else.com";
 
   // This test expects the following POP account to exist by default
   // in the test profile with port number 110 and no security.
   let firstServer = MailServices.accounts.FindServer(
     "tinderbox",
@@ -384,28 +379,28 @@ function subtest_check_replyTo_leak(amc)
   );
   let firstAccount = MailServices.accounts.FindAccountForServer(firstServer);
 
   accountRow = get_account_tree_row(firstAccount.key, null, amc);
   click_account_tree_row(amc, accountRow);
 
   // the Reply-To field should be empty as this account does not have it set.
   replyAddress = iframe.contentDocument.getElementById("identity.replyTo");
-  assert_equals(replyAddress.value, "");
+  Assert.equal(replyAddress.value, "");
 }
 
 /**
  * Test for bug 804091.
  * Check if onchange handlers are properly executed when panes are switched.
  */
-function test_account_onchange_handler() {
+add_task(function test_account_onchange_handler() {
   open_advanced_settings(function(amc) {
     subtest_check_onchange_handler(amc);
   });
-}
+});
 
 /**
  * Check if onchange handlers are properly executed when panes are switched.
  *
  * @param amc  the account options controller
  */
 function subtest_check_onchange_handler(amc) {
   let accountRow = get_account_tree_row(
@@ -414,21 +409,21 @@ function subtest_check_onchange_handler(
     amc
   );
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.e("contentFrame").contentDocument;
 
   let autoSync = iframe.getElementById("autosyncValue");
   // 30 is the default value so check if we are in clean state.
-  assert_equals(autoSync.value, 30);
+  Assert.equal(autoSync.value, 30);
 
   let autoSyncInterval = iframe.getElementById("autosyncInterval");
   // 1 is the default value and means the 30 is in days.
-  assert_equals(autoSyncInterval.value, 1);
+  Assert.equal(autoSyncInterval.value, 1);
 
   // Now type in 35 (days).
   amc.radio(new elib.ID(iframe, "useAutosync.ByAge"));
   autoSync.select();
   amc.type(new elib.Elem(autoSync), "35");
 
   // Immediately switch to another pane and back.
   accountRow = get_account_tree_row(gImapAccount.key, "am-junk.xul", amc);
@@ -436,14 +431,14 @@ function subtest_check_onchange_handler(
 
   accountRow = get_account_tree_row(gImapAccount.key, "am-offline.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   iframe = amc.e("contentFrame").contentDocument;
 
   // The pane optimized the entered value a bit. So now we should find 5.
   autoSync = iframe.getElementById("autosyncValue");
-  assert_equals(autoSync.value, 5);
+  Assert.equal(autoSync.value, 5);
 
   // And the unit is 7 days = week.
   autoSyncInterval = iframe.getElementById("autosyncInterval");
-  assert_equals(autoSyncInterval.value, 7);
+  Assert.equal(autoSyncInterval.value, 7);
 }
copy from mail/test/mozmill/account/test-account-tree.js
copy to mail/test/browser/account/browser_tree.js
--- a/mail/test/mozmill/account/test-account-tree.js
+++ b/mail/test/browser/account/browser_tree.js
@@ -11,164 +11,161 @@
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
   remove_account,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var { assert_equals, assert_false, assert_true } = ChromeUtils.import(
-  "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
-);
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var gPopAccount, gOriginalAccountCount;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // There may be pre-existing accounts from other tests.
   gOriginalAccountCount = MailServices.accounts.allServers.length;
 
   // Create a POP server
   let popServer = MailServices.accounts
     .createIncomingServer("nobody", "foo.invalid", "pop3")
     .QueryInterface(Ci.nsIPop3IncomingServer);
 
   let identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox@foo.invalid";
 
   gPopAccount = MailServices.accounts.createAccount();
   gPopAccount.incomingServer = popServer;
   gPopAccount.addIdentity(identity);
 
   // Now there should be one more account.
-  assert_equals(
+  Assert.equal(
     MailServices.accounts.allServers.length,
     gOriginalAccountCount + 1
   );
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   if (gPopAccount) {
     // Remove our test account to leave the profile clean.
     MailServices.accounts.removeAccount(gPopAccount);
     gPopAccount = null;
   }
   // There should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, gOriginalAccountCount);
-}
+  Assert.equal(MailServices.accounts.allServers.length, gOriginalAccountCount);
+});
 
 /**
  * Test for bug 536248.
  * Check if the account manager dialog remembers the open state of accounts.
  */
-function test_account_open_state() {
+add_task(function test_account_open_state() {
   open_advanced_settings(function(amc) {
     subtest_check_account_open_state(amc, true);
   });
   open_advanced_settings(function(amc) {
     subtest_check_account_open_state(amc, false);
   });
   // After this test all the accounts must be "open".
-}
+});
 
 /**
  * Check if the open state of accounts is in the wished state.
  *
  * @param amc           The account options controller.
  * @param aWishedState  The open state in which the account row should be found (bool).
  */
 function subtest_check_account_open_state(amc, aWishedState) {
   let accountRow = get_account_tree_row(gPopAccount.key, null, amc);
   click_account_tree_row(amc, accountRow);
 
   // See if the account row is in the wished open state.
   let accountTree = amc.e("accounttree");
-  assert_equals(accountRow, accountTree.view.selection.currentIndex);
-  assert_equals(accountTree.view.isContainerOpen(accountRow), aWishedState);
+  Assert.equal(accountRow, accountTree.view.selection.currentIndex);
+  Assert.equal(accountTree.view.isContainerOpen(accountRow), aWishedState);
 
   accountTree.view.toggleOpenState(accountRow);
-  assert_equals(accountTree.view.isContainerOpen(accountRow), !aWishedState);
+  Assert.equal(accountTree.view.isContainerOpen(accountRow), !aWishedState);
 
   // Whatever the open state of the account was, selecting one of its subpanes
   // must open it.
   amc.window.selectServer(gPopAccount.incomingServer, "am-junk.xul");
-  assert_true(accountTree.view.isContainerOpen(accountRow));
+  Assert.ok(accountTree.view.isContainerOpen(accountRow));
 
   // Set the proper state again for continuation of the test.
   accountTree.view
     .getItemAtIndex(accountRow)
     .setAttribute("open", !aWishedState);
-  assert_equals(accountTree.view.isContainerOpen(accountRow), !aWishedState);
+  Assert.equal(accountTree.view.isContainerOpen(accountRow), !aWishedState);
 }
 
 /**
  * Bug 740617.
  * Check if the default account is styled in bold.
  *
  */
-function test_default_account_highlight() {
+add_task(function test_default_account_highlight() {
   open_advanced_settings(function(amc) {
     subtest_check_default_account_highlight(amc);
   });
-}
+});
 
 /**
  * Check if the default account is styled in bold and another account is not.
  *
  * @param amc           The account options controller.
  */
 function subtest_check_default_account_highlight(amc) {
   // Select the default account.
   let accountRow = get_account_tree_row(
     MailServices.accounts.defaultAccount.key,
     null,
     amc
   );
   click_account_tree_row(amc, accountRow);
 
   let accountTree = amc.e("accounttree");
-  assert_equals(accountRow, accountTree.view.selection.currentIndex);
+  Assert.equal(accountRow, accountTree.view.selection.currentIndex);
   let cell = accountTree.view.getItemAtIndex(accountRow).firstElementChild
     .firstElementChild;
-  assert_equals(cell.tagName, "treecell");
+  Assert.equal(cell.tagName, "treecell");
 
   // We can't read the computed style of the tree cell directly, so at least see
   // if the isDefaultServer-true property is set on it. Hopefully the proper style
   // is attached to this property.
   let propArray = accountTree.view
     .getCellProperties(accountRow, accountTree.columns.getColumnAt(0))
     .split(" ");
-  assert_true(propArray.includes("isDefaultServer-true"));
+  Assert.ok(propArray.includes("isDefaultServer-true"));
 
   // Now select another account that is not default.
   accountRow = get_account_tree_row(gPopAccount.key, null, amc);
   click_account_tree_row(amc, accountRow);
 
   // There should isDefaultServer-true on its tree cell.
   propArray = accountTree.view
     .getCellProperties(accountRow, accountTree.columns.getColumnAt(0))
     .split(" ");
-  assert_false(propArray.includes("isDefaultServer-true"));
+  Assert.ok(!propArray.includes("isDefaultServer-true"));
 }
 /**
  * Bug 58713.
  * Check if after deleting an account the next one is selected.
  *
  * This test should always be the last one as it removes our specially
  * created gPopAccount.
  */
-function test_selection_after_account_deletion() {
+add_task(function test_selection_after_account_deletion() {
   open_advanced_settings(function(amc) {
     subtest_check_selection_after_account_deletion(amc);
   });
-}
+});
 
 /**
  * Check if after deleting an account the next one is selected.
  *
  * @param amc           The account options controller.
  */
 function subtest_check_selection_after_account_deletion(amc) {
   let accountList = [];
@@ -185,18 +182,18 @@ function subtest_check_selection_after_a
 
   // Get position of the current account in the account list.
   let accountIndex = accountList.indexOf(gPopAccount);
 
   // Remove our account.
   remove_account(gPopAccount, amc);
   gPopAccount = null;
   // Now there should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, gOriginalAccountCount);
+  Assert.equal(MailServices.accounts.allServers.length, gOriginalAccountCount);
 
   // See if the currently selected account is the one next in the account list.
   let accountTree = amc.e("accounttree");
   let accountRow = accountTree.view.selection.currentIndex;
-  assert_equals(
+  Assert.equal(
     accountTree.view.getItemAtIndex(accountRow)._account,
     accountList[accountIndex + 1]
   );
 }
copy from mail/test/mozmill/account/test-account-values.js
copy to mail/test/browser/account/browser_values.js
--- a/mail/test/mozmill/account/test-account-values.js
+++ b/mail/test/browser/account/browser_values.js
@@ -5,83 +5,80 @@
 /**
  * This test checks proper operation of the account settings panes
  * when certain special or invalid values are entered into the fields.
  */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 
 var {
   click_account_tree_row,
   get_account_tree_row,
   open_advanced_settings,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AccountManagerHelpers.jsm"
 );
-var { assert_equals, assert_false } = ChromeUtils.import(
-  "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
-);
 var { input_value, delete_all_existing } = ChromeUtils.import(
   "resource://testing-common/mozmill/KeyboardHelpers.jsm"
 );
 var { plan_for_modal_dialog, wait_for_modal_dialog } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var gPopAccount, gOriginalAccountCount;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // There may be pre-existing accounts from other tests.
   gOriginalAccountCount = MailServices.accounts.allServers.length;
 
   // Create a POP server
   let popServer = MailServices.accounts
     .createIncomingServer("nobody", "example.invalid", "pop3")
     .QueryInterface(Ci.nsIPop3IncomingServer);
 
   let identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox@example.invalid";
 
   gPopAccount = MailServices.accounts.createAccount();
   gPopAccount.incomingServer = popServer;
   gPopAccount.addIdentity(identity);
 
   // Now there should be one more account.
-  assert_equals(
+  Assert.equal(
     MailServices.accounts.allServers.length,
     gOriginalAccountCount + 1
   );
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   // Remove our test account to leave the profile clean.
   MailServices.accounts.removeAccount(gPopAccount);
   // There should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, gOriginalAccountCount);
-}
+  Assert.equal(MailServices.accounts.allServers.length, gOriginalAccountCount);
+});
 
 /**
  * Bug 208628.
  * Check that if the CC field is empty, enabling CC will automatically
  * prefill the currently default email address.
  */
-function test_default_CC_address() {
+add_task(function test_default_CC_address() {
   open_advanced_settings(function(amc) {
     subtest_check_default_CC_address(amc);
   });
-}
+});
 
 /**
  * Check that if the CC field is empty, enabling CC will automatically
  * prefill the currently default email address.
  *
  * @param amc  the account options controller
  */
 function subtest_check_default_CC_address(amc) {
@@ -90,119 +87,119 @@ function subtest_check_default_CC_addres
 
   let iframe = amc.window.document.getElementById("contentFrame");
 
   let defaultAddress = iframe.contentDocument.getElementById("identity.email")
     .value;
   let ccCheck = iframe.contentDocument.getElementById("identity.doCc");
   let ccAddress = iframe.contentDocument.getElementById("identity.doCcList");
   // The CC checkbox is not enabled and the address value is empty.
-  assert_false(ccCheck.checked);
-  assert_equals(ccAddress.value, "");
+  Assert.ok(!ccCheck.checked);
+  Assert.equal(ccAddress.value, "");
   // After ticking the CC checkbox the default address should be prefilled.
   amc.check(new elib.Elem(ccCheck), true);
-  assert_equals(ccAddress.value, defaultAddress);
+  Assert.equal(ccAddress.value, defaultAddress);
 
   let bccCheck = iframe.contentDocument.getElementById("identity.doBcc");
   let bccAddress = iframe.contentDocument.getElementById("identity.doBccList");
   // The BCC checkbox is not enabled but we set the address value to something.
-  assert_false(bccCheck.checked);
-  assert_equals(bccAddress.value, "");
+  Assert.ok(!bccCheck.checked);
+  Assert.equal(bccAddress.value, "");
   let bccUserAddress = "somebody@else.invalid";
   bccAddress.value = bccUserAddress;
   // After ticking the BCC checkbox the current value of the address should not change.
   amc.check(new elib.Elem(bccCheck), true);
-  assert_equals(bccAddress.value, bccUserAddress);
+  Assert.equal(bccAddress.value, bccUserAddress);
 }
 
 /**
  * Bug 720199.
  * Check if the account name automatically changes when the user changes
  * the username or hostname.
  */
-function test_account_name() {
+add_task(function test_account_name() {
   // We already have a POP account ready.
   // Create also a NNTP server.
   let nntpServer = MailServices.accounts
     .createIncomingServer(null, "example.nntp.invalid", "nntp")
     .QueryInterface(Ci.nsINntpIncomingServer);
 
   let identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox2@example.invalid";
 
   let nntpAccount = MailServices.accounts.createAccount();
   nntpAccount.incomingServer = nntpServer;
   nntpAccount.addIdentity(identity);
 
-  assert_equals(
+  Assert.equal(
     gPopAccount.incomingServer.prettyName,
     "nobody on example.invalid"
   );
-  assert_equals(nntpAccount.incomingServer.prettyName, "example.nntp.invalid");
+  Assert.equal(nntpAccount.incomingServer.prettyName, "example.nntp.invalid");
 
   // The automatic account name update works only if the name is
   // in the form of user@host.
   gPopAccount.incomingServer.prettyName = "nobody@example.invalid";
 
   let newHost = "some.host.invalid";
   let newUser = "somebody";
 
   // On NNTP there is no user name so just set new hostname.
   open_advanced_settings(function(amc) {
     subtest_check_account_name(nntpAccount, newHost, null, amc);
   });
 
   // And see if the account name is updated to it.
-  assert_equals(nntpAccount.incomingServer.prettyName, newHost);
+  Assert.equal(nntpAccount.incomingServer.prettyName, newHost);
 
   // On POP3 there is both user name and host name.
   // Set new host name first.
   open_advanced_settings(function(amc) {
     subtest_check_account_name(gPopAccount, newHost, null, amc);
   });
 
   // And see if in the account name the host part is updated to it.
-  assert_equals(gPopAccount.incomingServer.prettyName, "nobody@" + newHost);
+  Assert.equal(gPopAccount.incomingServer.prettyName, "nobody@" + newHost);
 
   // Set new host name first.
   open_advanced_settings(function(amc) {
     subtest_check_account_name(gPopAccount, null, newUser, amc);
   });
 
   // And see if in the account name the user part is updated.
-  assert_equals(gPopAccount.incomingServer.prettyName, newUser + "@" + newHost);
+  Assert.equal(gPopAccount.incomingServer.prettyName, newUser + "@" + newHost);
 
   newHost = "another.host.invalid";
   newUser = "anotherbody";
 
   // Set user name and host name at once.
   open_advanced_settings(function(amc) {
     subtest_check_account_name(gPopAccount, newHost, newUser, amc);
   });
 
   // And see if in the account name the host part is updated to it.
-  assert_equals(gPopAccount.incomingServer.prettyName, newUser + "@" + newHost);
+  Assert.equal(gPopAccount.incomingServer.prettyName, newUser + "@" + newHost);
 
   // Now have an account name where the name does not match the hostname.
   gPopAccount.incomingServer.prettyName = newUser + "@example.invalid";
 
   newHost = "third.host.invalid";
   // Set the host name again.
   open_advanced_settings(function(amc) {
     subtest_check_account_name(gPopAccount, newHost, null, amc);
   });
 
   // And the account name should not be touched.
-  assert_equals(
+  Assert.equal(
     gPopAccount.incomingServer.prettyName,
     newUser + "@example.invalid"
   );
 
   MailServices.accounts.removeAccount(nntpAccount);
-}
+});
 
 /**
  * Changes the user name and hostname to the supplied values.
  *
  * @param aAccount      the account to change
  * @param aNewHostname  the hostname value to set
  * @param aNewUsername  the username value to set
  * @param amc           the account options controller
@@ -210,25 +207,25 @@ function test_account_name() {
 function subtest_check_account_name(aAccount, aNewHostname, aNewUsername, amc) {
   let accountRow = get_account_tree_row(aAccount.key, "am-server.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.window.document.getElementById("contentFrame");
 
   if (aNewHostname) {
     let hostname = iframe.contentDocument.getElementById("server.realHostName");
-    assert_equals(hostname.value, aAccount.incomingServer.realHostName);
+    Assert.equal(hostname.value, aAccount.incomingServer.realHostName);
 
     // Now change the server host name.
     hostname.value = aNewHostname;
   }
 
   if (aNewUsername) {
     let username = iframe.contentDocument.getElementById("server.realUsername");
-    assert_equals(username.value, aAccount.incomingServer.realUsername);
+    Assert.equal(username.value, aAccount.incomingServer.realUsername);
 
     // Now change the server user name.
     username.value = aNewUsername;
   }
 
   if (aNewUsername) {
     // If username has changed, we get a confirmation dialog.
     plan_for_modal_dialog("commonDialog", function(cdc) {
@@ -242,38 +239,38 @@ function subtest_check_account_name(aAcc
     wait_for_modal_dialog("commonDialog");
   }
 }
 
 /**
  * Bug 536768.
  * Check if invalid junk target settings (folders) are fixed to sane values.
  */
-function test_invalid_junk_target() {
+add_task(function test_invalid_junk_target() {
   // Set the junk target prefs to invalid values.
   let branch = Services.prefs.getBranch(
     "mail.server." + gPopAccount.incomingServer.key + "."
   );
   branch.setCharPref("spamActionTargetAccount", "some random non-existent URI");
   branch.setCharPref("spamActionTargetFolder", "some random non-existent URI");
   let moveOnSpam = true;
   branch.setBoolPref("moveOnSpam", moveOnSpam);
   open_advanced_settings(function(amc) {
     subtest_check_invalid_junk_target(amc);
   });
 
   // The pref has no default so its non-existence means it was cleared.
   moveOnSpam = branch.getBoolPref("moveOnSpam", false);
-  assert_false(moveOnSpam);
+  Assert.ok(!moveOnSpam);
   // The targets should point to the same pop account now.
   let targetAccount = branch.getCharPref("spamActionTargetAccount");
-  assert_equals(targetAccount, gPopAccount.incomingServer.serverURI);
+  Assert.equal(targetAccount, gPopAccount.incomingServer.serverURI);
   let targetFolder = branch.getCharPref("spamActionTargetFolder");
-  assert_equals(targetFolder, gPopAccount.incomingServer.serverURI + "/Junk");
-}
+  Assert.equal(targetFolder, gPopAccount.incomingServer.serverURI + "/Junk");
+});
 
 /**
  * Just show the Junk settings pane and let it fix the values.
  *
  * @param amc  the account options controller
  */
 function subtest_check_invalid_junk_target(amc) {
   let accountRow = get_account_tree_row(gPopAccount.key, "am-junk.xul", amc);
@@ -282,63 +279,63 @@ function subtest_check_invalid_junk_targ
   // We need to save the new fixed values so click OK on the Account settings.
   amc.window.document.documentElement.acceptDialog();
 }
 
 /**
  * Bug 327812.
  * Checks if invalid server hostnames are not accepted.
  */
-function test_invalid_hostname() {
+add_task(function test_invalid_hostname() {
   let branch = Services.prefs.getBranch(
     "mail.server." + gPopAccount.incomingServer.key + "."
   );
   let origHostname = branch.getCharPref("realhostname");
 
   open_advanced_settings(function(amc) {
     subtest_check_invalid_hostname(amc, false, origHostname);
   });
   open_advanced_settings(function(amc) {
     subtest_check_invalid_hostname(amc, true, origHostname);
   });
 
   // The new bad hostname should not have been saved.
   let newHostname = branch.getCharPref("realhostname");
-  assert_equals(origHostname, newHostname);
-}
+  Assert.equal(origHostname, newHostname);
+});
 
 /**
  * Set the hostname to an invalid value and check if it gets fixed.
  *
  * @param amc                the account options controller
  * @param aExitSettings      Attempt to close the Account settings dialog.
  * @param aOriginalHostname  Original hostname of this server.
  */
 function subtest_check_invalid_hostname(amc, aExitSettings, aOriginalHostname) {
   let accountRow = get_account_tree_row(gPopAccount.key, "am-server.xul", amc);
   click_account_tree_row(amc, accountRow);
 
   let iframe = amc.window.document.getElementById("contentFrame");
   let hostname = iframe.contentDocument.getElementById("server.realHostName");
-  assert_equals(hostname.value, aOriginalHostname);
+  Assert.equal(hostname.value, aOriginalHostname);
 
   hostname.value = "some_invalid+host&domain*in>invalid";
 
   if (!aExitSettings) {
     accountRow = get_account_tree_row(gPopAccount.key, "am-junk.xul", amc);
     click_account_tree_row(amc, accountRow);
 
     // The invalid hostname should be set back to previous value at this point...
     accountRow = get_account_tree_row(gPopAccount.key, "am-server.xul", amc);
     click_account_tree_row(amc, accountRow);
 
     // ...let's check that:
     iframe = amc.window.document.getElementById("contentFrame");
     hostname = iframe.contentDocument.getElementById("server.realHostName");
-    assert_equals(hostname.value, aOriginalHostname);
+    Assert.equal(hostname.value, aOriginalHostname);
   } else {
     // If the hostname is bad, we should get a warning dialog.
     plan_for_modal_dialog("commonDialog", function(cdc) {
       // Just dismiss it.
       cdc.window.document.documentElement.acceptDialog();
     });
 
     // Click OK on the Account settings.
@@ -350,23 +347,23 @@ function subtest_check_invalid_hostname(
 
 /**
  * Bug 1426328.
  * Check that the AM will trim user added spaces around text values.
  */
 const badName = "trailing  space ";
 const badEmail = " leading_space@example.com";
 
-function test_trailing_spaces() {
+add_task(function test_trailing_spaces() {
   open_advanced_settings(function(amc) {
     subtest_check_trailing_spaces(amc);
   });
-  assert_equals(gPopAccount.incomingServer.prettyName, badName.trim());
-  assert_equals(gPopAccount.defaultIdentity.email, badEmail.trim());
-}
+  Assert.equal(gPopAccount.incomingServer.prettyName, badName.trim());
+  Assert.equal(gPopAccount.defaultIdentity.email, badEmail.trim());
+});
 
 /**
  * Check that the AM will trim user added spaces around text values
  * when storing them into the account.
  *
  * @param amc  the account options controller
  */
 function subtest_check_trailing_spaces(amc) {
@@ -377,14 +374,14 @@ function subtest_check_trailing_spaces(a
 
   let accountName = iframe.contentDocument.getElementById("server.prettyName");
   let defaultAddress = iframe.contentDocument.getElementById("identity.email");
   delete_all_existing(amc, new elib.Elem(accountName));
   delete_all_existing(amc, new elib.Elem(defaultAddress));
   input_value(amc, badName, new elib.Elem(accountName));
   input_value(amc, badEmail, new elib.Elem(defaultAddress));
 
-  assert_equals(accountName.value, badName);
-  assert_equals(defaultAddress.value, badEmail);
+  Assert.equal(accountName.value, badName);
+  Assert.equal(defaultAddress.value, badEmail);
 
   // We really need to save the new values so click OK on the Account settings.
   amc.window.document.documentElement.acceptDialog();
 }
copy from mail/test/mozmill/account/xml/example.com
copy to mail/test/browser/account/xml/example.com
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/account/xml/example.com^headers^
@@ -0,0 +1,1 @@
+Content-Type: text/xml
copy from mail/test/mozmill/account/xml/momo.invalid
copy to mail/test/browser/account/xml/momo.invalid
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/account/xml/momo.invalid^headers^
@@ -0,0 +1,1 @@
+Content-Type: text/xml
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/addrbook/browser.ini
@@ -0,0 +1,15 @@
+[DEFAULT]
+prefs =
+  ldap_2.servers.osx.description=
+  ldap_2.servers.osx.dirType=-1
+  ldap_2.servers.osx.uri=
+  mail.provider.suppress_dialog_on_startup=true
+  mail.spotlight.firstRunDone=true
+  mail.winsearch.firstRunDone=true
+  mailnews.start_page.override_url=about:blank
+  mailnews.start_page.url=about:blank
+subsuite = thunderbird
+
+[browser_addressBook.js]
+[browser_addressBookPanes.js]
+[browser_updateMailingList.js]
copy from mail/test/mozmill/addrbook/test-address-book.js
copy to mail/test/browser/addrbook/browser_addressBook.js
--- a/mail/test/mozmill/addrbook/test-address-book.js
+++ b/mail/test/browser/addrbook/browser_addressBook.js
@@ -21,27 +21,19 @@ var {
   open_address_book_window,
   select_address_book,
   select_contacts,
   set_address_books_collapsed,
   set_address_books_expanded,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AddressBookHelpers.jsm"
 );
-var { wait_for_compose_window } = ChromeUtils.import(
+var { close_compose_window, wait_for_compose_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/ComposeHelpers.jsm"
 );
-var {
-  assert_equals,
-  assert_false,
-  assert_not_equals,
-  assert_true,
-} = ChromeUtils.import(
-  "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
-);
 var { gMockPromptService } = ChromeUtils.import(
   "resource://testing-common/mozmill/PromptHelpers.jsm"
 );
 var { plan_for_new_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
 var { XPCOMUtils } = ChromeUtils.import(
@@ -51,17 +43,17 @@ var { Services } = ChromeUtils.import("r
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var abController = null;
 var addrBook1, addrBook2, addrBook3, addrBook4, ldapBook;
 var mListA, mListB, mListC, mListD, mListE;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // Open the address book main window
   abController = open_address_book_window();
 
   // Let's add some new address books.  I'll add them
   // out of order to properly test the alphabetical
   // ordering of the address books.
   ldapBook = create_ldap_address_book("LDAP Book");
   addrBook3 = create_address_book("AB 3");
@@ -85,21 +77,21 @@ function setupModule(module) {
   // and Collected Address Book.  So let's ensure that those address books
   // exist in the tree view before executing our tests.
   abController.waitFor(
     () => abController.window.gDirectoryTreeView.rowCount == 8,
     "Timeout waiting for all 8 rows in address books list to show up in the tree view",
     1000,
     10
   );
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   close_address_book_window(abController);
-}
+});
 
 /* Test that the address book manager automatically sorts
  * address books.
  *
  * Currently, we sort address books as follows:
  * 1. All Address Books
  * 2. Personal Address Book
  * 3. Mork Address Books
@@ -117,75 +109,75 @@ function teardownModule(module) {
  *    ML B
  * AB 3
  *    ML C
  *    ML D
  * AB 4
  * LDAP Book
  * Collected Address Book
  **/
-function test_order_of_address_books() {
+add_task(function test_order_of_address_books() {
   const EXPECTED_AB_ORDER = [
     "All Address Books",
     "Personal Address Book",
     "AB 1",
     "AB 2",
     "AB 3",
     "AB 4",
     "LDAP Book",
     "Collected Addresses",
   ];
 
   for (let i = 0; i < EXPECTED_AB_ORDER.length; i++) {
     let abName = get_name_of_address_book_element_at(i);
-    assert_equals(
+    Assert.equal(
       abName,
       EXPECTED_AB_ORDER[i],
       "The address books are out of order."
     );
   }
-}
+});
 
 /* Test that the expanded and collapsed states of address books
  * in the tree persist state when closing and re-opening the
  * address book manager
  */
-function test_persist_collapsed_and_expanded_states() {
+add_task(function test_persist_collapsed_and_expanded_states() {
   // Set the state of address books 1 and 3 to expanded
   set_address_books_expanded([addrBook1, addrBook3]);
 
   // Set address book 2 to be collapsed
   set_address_books_collapsed(addrBook2);
 
   // Now close and re-open the address book
   close_address_book_window(abController);
   abController = open_address_book_window();
 
-  assert_true(is_address_book_collapsed(addrBook2));
-  assert_true(!is_address_book_collapsed(addrBook1));
-  assert_true(!is_address_book_collapsed(addrBook3));
+  Assert.ok(is_address_book_collapsed(addrBook2));
+  Assert.ok(!is_address_book_collapsed(addrBook1));
+  Assert.ok(!is_address_book_collapsed(addrBook3));
 
   // Now set the state of address books 1 and 3 to collapsed
   // and make sure 2 is expanded
   set_address_books_collapsed([addrBook1, addrBook3]);
   set_address_books_expanded(addrBook2);
 
   // Now close and re-open the address book
   close_address_book_window(abController);
   abController = open_address_book_window();
 
-  assert_true(!is_address_book_collapsed(addrBook2));
-  assert_true(is_address_book_collapsed(addrBook1));
-  assert_true(is_address_book_collapsed(addrBook3));
-}
+  Assert.ok(!is_address_book_collapsed(addrBook2));
+  Assert.ok(is_address_book_collapsed(addrBook1));
+  Assert.ok(is_address_book_collapsed(addrBook3));
+});
 
 /* Test that if we try to delete a contact, that we are given
  * a confirm prompt.
  */
-function test_deleting_contact_causes_confirm_prompt() {
+add_task(function test_deleting_contact_causes_confirm_prompt() {
   // Register the Mock Prompt Service
   gMockPromptService.register();
 
   // Create a contact that we'll try to delete
   let contact1 = create_contact("test@example.com", "Sammy Jenkis", true);
   let toDelete = [contact1];
 
   let bundle = Services.strings.createBundle(
@@ -204,51 +196,51 @@ function test_deleting_contact_causes_co
   // contact should not be deleted.
   gMockPromptService.returnValue = false;
 
   // Now attempt to delete the contact
   select_contacts(toDelete);
   abController.keypress(null, "VK_DELETE", {});
 
   let promptState = gMockPromptService.promptState;
-  assert_not_equals(null, promptState, "Expected a prompt state");
+  Assert.notEqual(null, promptState, "Expected a prompt state");
   // Was a confirm displayed?
-  assert_equals("confirm", promptState.method);
+  Assert.equal("confirm", promptState.method);
   // Was the right message displayed?
-  assert_equals(confirmSingle, promptState.text);
+  Assert.equal(confirmSingle, promptState.text);
   // The contact should not have been deleted.
-  assert_equals(abController.window.gAbView.rowCount, totalEntries);
+  Assert.equal(abController.window.gAbView.rowCount, totalEntries);
 
   gMockPromptService.reset();
 
   // Now we'll return true on confirm so that
   // the contact is deleted.
   gMockPromptService.returnValue = true;
   select_contacts(toDelete);
   abController.keypress(null, "VK_DELETE", {});
 
   promptState = gMockPromptService.promptState;
-  assert_not_equals(null, promptState, "Expected a prompt state");
+  Assert.notEqual(null, promptState, "Expected a prompt state");
   // Was a confirm displayed?
-  assert_equals("confirm", promptState.method);
+  Assert.equal("confirm", promptState.method);
   // Was the right message displayed?
-  assert_equals(confirmSingle, promptState.text);
+  Assert.equal(confirmSingle, promptState.text);
   // The contact should have been deleted.
-  assert_equals(
+  Assert.equal(
     abController.window.gAbView.rowCount,
     totalEntries - toDelete.length
   );
 
   gMockPromptService.unregister();
-}
+});
 
 /* Test that if we try to delete multiple contacts, that we are give
  * a confirm prompt.
  */
-function test_deleting_contacts_causes_confirm_prompt() {
+add_task(function test_deleting_contacts_causes_confirm_prompt() {
   // Register the Mock Prompt Service
   gMockPromptService.register();
 
   // Create some contacts that we'll try to delete.
   let contact2 = create_contact("test2@example.com", "Leonard Shelby", true);
   let contact3 = create_contact(
     "test3@example.com",
     "John Edward Gammell",
@@ -276,99 +268,99 @@ function test_deleting_contacts_causes_c
   // contact should not be deleted.
   gMockPromptService.returnValue = false;
 
   // Now attempt to delete the contact
   select_contacts(toDelete);
   abController.keypress(null, "VK_DELETE", {});
 
   let promptState = gMockPromptService.promptState;
-  assert_not_equals(null, promptState, "Expected a prompt state");
+  Assert.notEqual(null, promptState, "Expected a prompt state");
   // Was a confirm displayed?
-  assert_equals("confirm", promptState.method);
+  Assert.equal("confirm", promptState.method);
   // Was the right message displayed?
-  assert_equals(confirmMultiple, promptState.text);
+  Assert.equal(confirmMultiple, promptState.text);
   // The contact should not have been deleted.
-  assert_equals(abController.window.gAbView.rowCount, totalEntries);
+  Assert.equal(abController.window.gAbView.rowCount, totalEntries);
 
   gMockPromptService.reset();
 
   // Now we'll return true on confirm so that
   // the contact is deleted.
   gMockPromptService.returnValue = true;
   select_contacts(toDelete);
   abController.keypress(null, "VK_DELETE", {});
 
   promptState = gMockPromptService.promptState;
-  assert_not_equals(null, promptState, "Expected a prompt state");
+  Assert.notEqual(null, promptState, "Expected a prompt state");
   // Was a confirm displayed?
-  assert_equals("confirm", promptState.method);
+  Assert.equal("confirm", promptState.method);
   // Was the right message displayed?
-  assert_equals(confirmMultiple, promptState.text);
+  Assert.equal(confirmMultiple, promptState.text);
   // The contact should have been deleted.
-  assert_equals(
+  Assert.equal(
     abController.window.gAbView.rowCount,
     totalEntries - toDelete.length
   );
 
   gMockPromptService.unregister();
-}
+});
 
 /* Tests that attempting to delete a mailing list causes a
  * confirmation dialog to be brought up, and that deletion
  * actually works if the user clicks "OK".
  */
-function test_deleting_mailing_lists() {
+add_task(function test_deleting_mailing_lists() {
   // Register our Mock Prompt Service
   gMockPromptService.register();
 
   // Create a new mailing list, and add it to one of our
   // address books
   let newList = create_mailing_list("Delete Me!");
   let addedList = addrBook1.addMailList(newList);
 
   // Make sure it got added.
-  assert_true(addrBook1.hasDirectory(addedList));
+  Assert.ok(addrBook1.hasDirectory(addedList));
 
   // Let's click "cancel" on the confirm dialog box
   // first.
   gMockPromptService.returnValue = false;
 
   abController.window.AbDeleteDirectory(addedList.URI);
 
   let promptState = gMockPromptService.promptState;
-  assert_not_equals(null, promptState, "Expected a prompt state");
+  Assert.notEqual(null, promptState, "Expected a prompt state");
 
   // Test that the confirmation dialog was brought up.
-  assert_equals("confirm", promptState.method);
+  Assert.equal("confirm", promptState.method);
 
   // Ensure that the mailing list was not removed.
-  assert_true(addrBook1.hasDirectory(addedList));
+  Assert.ok(addrBook1.hasDirectory(addedList));
 
   // This time, let's click "OK" on the confirm dialog box
   gMockPromptService.reset();
   gMockPromptService.returnValue = true;
 
   abController.window.AbDeleteDirectory(addedList.URI);
 
   // Test that the confirmation dialog was brought up.
   promptState = gMockPromptService.promptState;
-  assert_not_equals(null, promptState, "Expected a prompt state");
-  assert_equals("confirm", promptState.method);
+  Assert.notEqual(null, promptState, "Expected a prompt state");
+  Assert.equal("confirm", promptState.method);
 
   // Ensure that the mailing list was removed.
-  assert_false(addrBook1.hasDirectory(addedList));
+  Assert.ok(!addrBook1.hasDirectory(addedList));
 
   gMockPromptService.unregister();
-}
+});
 
 /* Tests that we can send mail to a mailing list by selecting the
  * mailing list in the tree, and clicking "Write"
  */
-function test_writing_to_mailing_list() {
+add_task(function test_writing_to_mailing_list() {
   // Create a new mailing list, and add it to one of our
   // address books
   let newList = create_mailing_list("Some Mailing List");
   let addedList = addrBook1.addMailList(newList);
 
   // Create some contacts that we'll try to contact
   let contacts = [
     create_contact("test2@example.com", "Leonard Shelby", true),
@@ -392,12 +384,14 @@ function test_writing_to_mailing_list() 
   plan_for_new_window("msgcompose");
   // ... and click the "Write" button
   abController.click(abController.eid("button-newmessage"));
   let composeWin = wait_for_compose_window(abController);
   let to = composeWin.window.gMsgCompose.compFields.to;
 
   // Make sure we're writing to all contacts in the mailing list.
   for (let contact of contacts) {
-    assert_true(to.includes(contact.primaryEmail));
-    assert_true(to.includes(contact.displayName));
+    Assert.ok(to.includes(contact.primaryEmail));
+    Assert.ok(to.includes(contact.displayName));
   }
-}
+
+  close_compose_window(composeWin);
+});
copy from mail/test/mozmill/addrbook/test-address-book-panes.js
copy to mail/test/browser/addrbook/browser_addressBookPanes.js
--- a/mail/test/mozmill/addrbook/test-address-book-panes.js
+++ b/mail/test/browser/addrbook/browser_addressBookPanes.js
@@ -12,32 +12,39 @@ var {
   close_address_book_window,
   open_address_book_window,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AddressBookHelpers.jsm"
 );
 
 var abController;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // Open the address book main window
   abController = open_address_book_window();
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   // Make sure the panes are all visible now that we're
   // done these tests.
   toggle_directory_pane();
   toggle_contact_pane();
 
   assert_directory_pane_visibility(true);
   assert_contact_pane_visibility(true);
 
   close_address_book_window(abController);
-}
+
+  Assert.report(
+    false,
+    undefined,
+    undefined,
+    "Test ran to completion successfully"
+  );
+});
 
 /**
  * Helper function to toggle a pane.
  *
  * @param splitterId the id of the splitter to toggle
  */
 function _help_toggle_pane(splitterId) {
   abController.window.togglePaneSplitter(splitterId);
@@ -99,38 +106,38 @@ function assert_directory_pane_visibilit
 function assert_contact_pane_visibility(visible) {
   _help_assert_pane_visibility(
     "CardViewOuterBox",
     "menu_showCardPane",
     visible
   );
 }
 
-function test_hide_directory_pane() {
+add_task(function test_hide_directory_pane() {
   toggle_directory_pane();
   assert_directory_pane_visibility(false);
-}
+});
 
-function test_show_directory_pane() {
+add_task(function test_show_directory_pane() {
   toggle_directory_pane();
   assert_directory_pane_visibility(true);
-}
+});
 
-function test_hide_contact_pane() {
+add_task(function test_hide_contact_pane() {
   toggle_contact_pane();
   assert_contact_pane_visibility(false);
-}
+});
 
-function test_show_contact_pane() {
+add_task(function test_show_contact_pane() {
   toggle_contact_pane();
   assert_contact_pane_visibility(true);
-}
+});
 
-function test_persist_panes() {
+add_task(function test_persist_panes() {
   toggle_directory_pane();
   toggle_contact_pane();
 
   close_address_book_window(abController);
   abController = open_address_book_window();
 
   assert_directory_pane_visibility(false);
   assert_contact_pane_visibility(false);
-}
+});
copy from mail/test/mozmill/addrbook/test-update-mailing-list.js
copy to mail/test/browser/addrbook/browser_updateMailingList.js
--- a/mail/test/mozmill/addrbook/test-update-mailing-list.js
+++ b/mail/test/browser/addrbook/browser_updateMailingList.js
@@ -18,25 +18,25 @@ var {
   delete_address_book,
   edit_selected_contact,
   open_address_book_window,
   select_address_book,
   select_contacts,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AddressBookHelpers.jsm"
 );
-var { assert_equals, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
-function test_contact_in_mailing_list_updated() {
+add_task(function test_contact_in_mailing_list_updated() {
   const kOldAddress = "before@example.com";
   const kNewAddress = "after@example.com";
 
   // Create some address book to work with...
   let ab = create_address_book("Some Address Book");
   // And a contact...
   let contact = create_contact(kOldAddress, "Some Contact", true);
   // And our mailing list.
@@ -60,21 +60,21 @@ function test_contact_in_mailing_list_up
 
   // Because the current address book is kind of lame, in order
   // to see whether or not the mailing list contact was updated,
   // we have to get a fresh copy of the address book...
   ab = MailServices.ab.getDirectory(ab.URI);
 
   // Ensure that the primary email address for the contact changed
   // in the mailing list as well.
-  assert_equals(
+  Assert.equal(
     1,
     ml.addressLists.length,
     "There should only be one contact in the mailing list"
   );
   let mlContact = ml.addressLists.queryElementAt(0, Ci.nsIAbCard);
-  assert_equals(kNewAddress, mlContact.primaryEmail);
+  Assert.equal(kNewAddress, mlContact.primaryEmail);
 
   // Destroy the address book that we created.
   delete_address_book(ab);
 
   close_address_book_window(abw);
-}
+});
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/attachment/browser.ini
@@ -0,0 +1,19 @@
+[DEFAULT]
+prefs =
+  browser.tabs.remote.autostart=false
+  ldap_2.servers.osx.description=
+  ldap_2.servers.osx.dirType=-1
+  ldap_2.servers.osx.uri=
+  mail.provider.suppress_dialog_on_startup=true
+  mail.spotlight.firstRunDone=true
+  mail.winsearch.firstRunDone=true
+  mailnews.start_page.override_url=about:blank
+  mailnews.start_page.url=about:blank
+subsuite = thunderbird
+support-files = data/**
+
+[browser_attachment.js]
+[browser_attachmentEvents.js]
+[browser_attachmentInPlainMsg.js]
+[browser_attachmentMenus.js]
+[browser_attachmentSize.js]
copy from mail/test/mozmill/attachment/test-attachment.js
copy to mail/test/browser/attachment/browser_attachment.js
--- a/mail/test/mozmill/attachment/test-attachment.js
+++ b/mail/test/browser/attachment/browser_attachment.js
@@ -4,32 +4,30 @@
 
 /**
  * Checks various attachments display correctly
  */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
 var EventUtils = ChromeUtils.import(
-  "chrome://mozmill/content/stdlib/EventUtils.jsm"
+  "resource://testing-common/mozmill/EventUtils.jsm"
 );
 
 var { close_compose_window, open_compose_with_forward } = ChromeUtils.import(
   "resource://testing-common/mozmill/ComposeHelpers.jsm"
 );
 var {
   add_message_to_folder,
   assert_attachment_list_focused,
-  assert_equals,
   assert_message_pane_focused,
   assert_selected_and_displayed,
-  assert_true,
   be_in_folder,
   close_popup,
   create_folder,
   create_message,
   mc,
   msgGen,
   plan_to_wait_for_folder_events,
   select_click_row,
@@ -61,17 +59,17 @@ var textAttachment =
   "of human values and compassion and simple warmth will return, and when " +
   "that happens someone like myself who has gone through an ordeal and who " +
   "genuinely needs hot coffee to pick him up and keep him functioning when " +
   "he has to function will get the hot coffee whether he happens to have a " +
   "poscred readily available or not.";
 
 var binaryAttachment = textAttachment;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   folder = create_folder("AttachmentA");
 
   var attachedMessage = msgGen.makeMessage({
     body: { body: "I'm an attached email!" },
     attachments: [
       { body: textAttachment, filename: "inner attachment.txt", format: "" },
     ],
   });
@@ -178,169 +176,169 @@ function setupModule(module) {
         },
       ],
     });
   }
 
   for (let i = 0; i < messages.length; i++) {
     add_message_to_folder(folder, create_message(messages[i]));
   }
-}
+});
 
 /**
  * Set the pref to ensure that the attachments pane starts out (un)expanded
  *
  * @param expand true if the attachment pane should start out expanded,
  *        false otherwise
  */
 function ensure_starts_expanded(expand) {
   Services.prefs.setBoolPref(
     "mailnews.attachments.display.start_expanded",
     expand
   );
 }
 
-function test_attachment_view_collapsed() {
+add_task(function test_attachment_view_collapsed() {
   be_in_folder(folder);
 
   select_click_row(0);
   assert_selected_and_displayed(0);
 
   if (!mc.e("attachmentView").collapsed) {
     throw new Error("Attachment pane expanded when it shouldn't be!");
   }
-}
+});
 
-function test_attachment_view_expanded() {
+add_task(function test_attachment_view_expanded() {
   be_in_folder(folder);
 
   for (let i = 1; i < messages.length; i++) {
     select_click_row(i);
     assert_selected_and_displayed(i);
 
     if (mc.e("attachmentView").collapsed) {
       throw new Error(
         "Attachment pane collapsed (on message #" + i + " when it shouldn't be!"
       );
     }
   }
-}
+});
 
-function test_attachment_name_sanitization() {
+add_task(function test_attachment_name_sanitization() {
   be_in_folder(folder);
 
   let attachmentList = mc.e("attachmentList");
 
   for (let i = 0; i < messages.length; i++) {
     if ("attachments" in messages[i]) {
       select_click_row(i);
       assert_selected_and_displayed(i);
 
       let attachments = messages[i].attachments;
       if (messages[i].attachments.length == 1) {
-        assert_equals(
+        Assert.equal(
           mc.e("attachmentName").value,
           attachments[0].sanitizedFilename || attachments[0].filename
         );
       }
 
       for (let j = 0; j < attachments.length; j++) {
-        assert_equals(
+        Assert.equal(
           attachmentList.getItemAtIndex(j).getAttribute("name"),
           attachments[j].sanitizedFilename || attachments[j].filename
         );
       }
     }
   }
-}
+});
 
-function test_long_attachment_name() {
+add_task(function test_long_attachment_name() {
   be_in_folder(folder);
 
   select_click_row(4);
   assert_selected_and_displayed(4);
 
   let messagepaneBox = mc.e("messagepanebox");
   let attachmentBar = mc.e("attachmentBar");
 
-  assert_true(
+  Assert.ok(
     messagepaneBox.getBoundingClientRect().width >=
       attachmentBar.getBoundingClientRect().width,
     "Attachment bar has expanded off the edge of the window!"
   );
-}
+});
 
 /**
  * Make sure that, when opening attached messages, we only show the attachments
  * "beneath" the attached message (as opposed to all attachments for the root
  * message).
  */
-function test_attached_message_attachments() {
+add_task(function test_attached_message_attachments() {
   be_in_folder(folder);
 
   select_click_row(5);
   assert_selected_and_displayed(5);
 
   // Make sure we have the expected number of attachments in the root message:
   // an outer text attachment, an attached email, and an inner text attachment.
-  assert_equals(mc.e("attachmentList").itemCount, 3);
+  Assert.equal(mc.e("attachmentList").itemCount, 3);
 
   // Open the attached email.
   plan_for_new_window("mail:messageWindow");
   mc.e("attachmentList")
     .getItemAtIndex(1)
     .attachment.open();
   let msgc = wait_for_new_window("mail:messageWindow");
   wait_for_message_display_completion(msgc, true);
 
   // Make sure we have the expected number of attachments in the attached
   // message: just an inner text attachment.
-  assert_equals(msgc.e("attachmentList").itemCount, 1);
+  Assert.equal(msgc.e("attachmentList").itemCount, 1);
 
   close_window(msgc);
-}
+});
 
-function test_attachment_name_click() {
+add_task(function test_attachment_name_click() {
   be_in_folder(folder);
 
   select_click_row(1);
   assert_selected_and_displayed(1);
 
   let attachmentList = mc.e("attachmentList");
 
-  assert_true(
+  Assert.ok(
     attachmentList.collapsed,
     "Attachment list should start out collapsed!"
   );
 
   // Ensure the open dialog appears when clicking on the attachment name and
   // that the attachment list doesn't expand.
   plan_for_modal_dialog("unknownContentType", function() {});
   mc.click(mc.eid("attachmentName"));
   wait_for_modal_dialog("unknownContentType");
-  assert_true(
+  Assert.ok(
     attachmentList.collapsed,
     "Attachment list should not expand when clicking on attachmentName!"
   );
-}
+});
 
 /**
  * Test that right-clicking on a particular element opens the expected context
  * menu.
  *
  * @param elementId the id of the element to right click on
  * @param contextMenuId the id of the context menu that should appear
  */
 function subtest_attachment_right_click(elementId, contextMenuId) {
   mc.rightClick(mc.eid(elementId));
   wait_for_popup_to_open(mc.e(contextMenuId));
   close_popup(mc, mc.eid(contextMenuId));
 }
 
-function test_attachment_right_click_single() {
+add_task(function test_attachment_right_click_single() {
   be_in_folder(folder);
 
   select_click_row(1);
   assert_selected_and_displayed(1);
 
   subtest_attachment_right_click("attachmentIcon", "attachmentItemContext");
   subtest_attachment_right_click("attachmentCount", "attachmentItemContext");
   subtest_attachment_right_click("attachmentName", "attachmentItemContext");
@@ -353,19 +351,19 @@ function test_attachment_right_click_sin
   subtest_attachment_right_click(
     "attachmentSaveAllSingle",
     "attachment-toolbar-context-menu"
   );
   subtest_attachment_right_click(
     "attachmentBar",
     "attachment-toolbar-context-menu"
   );
-}
+});
 
-function test_attachment_right_click_multiple() {
+add_task(function test_attachment_right_click_multiple() {
   be_in_folder(folder);
 
   select_click_row(3);
   assert_selected_and_displayed(3);
 
   subtest_attachment_right_click("attachmentIcon", "attachmentListContext");
   subtest_attachment_right_click("attachmentCount", "attachmentListContext");
   subtest_attachment_right_click("attachmentSize", "attachmentListContext");
@@ -377,156 +375,156 @@ function test_attachment_right_click_mul
   subtest_attachment_right_click(
     "attachmentSaveAllMultiple",
     "attachment-toolbar-context-menu"
   );
   subtest_attachment_right_click(
     "attachmentBar",
     "attachment-toolbar-context-menu"
   );
-}
+});
 
 /**
  * Test that clicking on various elements in the attachment bar toggles the
  * attachment list.
  *
  * @param elementId the id of the element to click
  */
 function subtest_attachment_list_toggle(elementId) {
   let attachmentList = mc.e("attachmentList");
   let element = mc.eid(elementId);
 
   mc.click(element);
-  assert_true(
+  Assert.ok(
     !attachmentList.collapsed,
     `Attachment list should be expanded after clicking ${elementId}!`
   );
   assert_attachment_list_focused();
 
   mc.click(element);
-  assert_true(
+  Assert.ok(
     attachmentList.collapsed,
     `Attachment list should be collapsed after clicking ${elementId} again!`
   );
   assert_message_pane_focused();
 }
 
-function test_attachment_list_expansion() {
+add_task(function test_attachment_list_expansion() {
   be_in_folder(folder);
 
   select_click_row(1);
   assert_selected_and_displayed(1);
 
-  assert_true(
+  Assert.ok(
     mc.e("attachmentList").collapsed,
     "Attachment list should start out collapsed!"
   );
 
   subtest_attachment_list_toggle("attachmentToggle");
   subtest_attachment_list_toggle("attachmentIcon");
   subtest_attachment_list_toggle("attachmentCount");
   subtest_attachment_list_toggle("attachmentSize");
   subtest_attachment_list_toggle("attachmentBar");
 
   // Ensure that clicking the "Save All" button doesn't expand the attachment
   // list.
   mc.click(
-    new elementslib.Elem(
+    new elib.Elem(
       mc
         .e("attachmentSaveAllSingle")
         .querySelector(".toolbarbutton-menubutton-dropmarker")
     )
   );
-  assert_true(
+  Assert.ok(
     mc.e("attachmentList").collapsed,
     "Attachment list should be collapsed after clicking save button!"
   );
-}
+});
 
-function test_attachment_list_starts_expanded() {
+add_task(function test_attachment_list_starts_expanded() {
   ensure_starts_expanded(true);
   be_in_folder(folder);
 
   select_click_row(2);
   assert_selected_and_displayed(2);
 
-  assert_true(
+  Assert.ok(
     !mc.e("attachmentList").collapsed,
     "Attachment list should start out expanded!"
   );
-}
+});
 
-function test_selected_attachments_are_cleared() {
+add_task(function test_selected_attachments_are_cleared() {
   ensure_starts_expanded(false);
   be_in_folder(folder);
   // First, select the message with two attachments.
   select_click_row(3);
 
   // Expand the attachment list.
   mc.click(mc.eid("attachmentToggle"));
 
   // Select both the attachments.
   let attachmentList = mc.e("attachmentList");
-  assert_equals(
+  Assert.equal(
     attachmentList.selectedItems.length,
     1,
     "On first load the first item should be selected"
   );
 
   // We can just click on the first element, but the second one needs a
   // ctrl-click (or cmd-click for those Mac-heads among us).
   mc.click(new elib.Elem(attachmentList.children[0]), 5, 5);
   EventUtils.synthesizeMouse(
     attachmentList.children[1],
     5,
     5,
     { accelKey: true },
     mc.window
   );
 
-  assert_equals(
+  Assert.equal(
     attachmentList.selectedItems.length,
     2,
     "We had the wrong number of selected items after selecting some!"
   );
 
   // Switch to the message with one attachment, and make sure there are no
   // selected attachments.
   select_click_row(2);
 
   // Expand the attachment list again.
   mc.click(mc.eid("attachmentToggle"));
 
-  assert_equals(
+  Assert.equal(
     attachmentList.selectedItems.length,
     1,
     "After loading a new message the first item should be selected"
   );
-}
+});
 
-function test_select_all_attachments_key() {
+add_task(function test_select_all_attachments_key() {
   be_in_folder(folder);
 
   // First, select the message with two attachments.
   select_none();
   select_click_row(3);
 
   // Expand the attachment list.
   mc.click(mc.eid("attachmentToggle"));
 
   let attachmentList = mc.e("attachmentList");
   mc.keypress(new elib.Elem(attachmentList), "a", { accelKey: true });
-  assert_equals(
+  Assert.equal(
     attachmentList.selectedItems.length,
     2,
     "Should have selected all attachments!"
   );
-}
+});
 
-function test_delete_attachment_key() {
+add_task(function test_delete_attachment_key() {
   be_in_folder(folder);
 
   // First, select the message with two attachments.
   select_none();
   select_click_row(3);
 
   // Expand the attachment list.
   mc.click(mc.eid("attachmentToggle"));
@@ -542,19 +540,19 @@ function test_delete_attachment_key() {
   wait_for_modal_dialog("commonDialog");
 
   // Try deleting with the shift-delete key combo.
   plan_for_modal_dialog("commonDialog", function(cdc) {
     cdc.window.document.documentElement.cancelDialog();
   });
   mc.keypress(firstAttachment, "VK_DELETE", { shiftKey: true });
   wait_for_modal_dialog("commonDialog");
-}
+});
 
-function test_attachments_compose_menu() {
+add_task(function test_attachments_compose_menu() {
   be_in_folder(folder);
 
   // First, select the message with two attachments.
   select_none();
   select_click_row(3);
 
   let cwc = open_compose_with_forward();
   let attachment = cwc.e("attachmentBucket");
@@ -584,61 +582,61 @@ function test_attachments_compose_menu()
         element = element.parentNode;
       }
     }
   }
 
   // Click on a portion of the attachmentBucket that will focus it, but not
   // bring up the file picker
   force_focus("attachmentBucket");
-  assert_equals(
+  Assert.equal(
     "Remove Attachments",
     cwc.e("cmd_delete").getAttribute("label"),
     "attachmentBucket is focused!"
   );
 
   // Select 1 attachment, and
   // focus the subject to see the label change and to execute isCommandEnabled
   attachment.selectedIndex = 0;
   force_focus("msgSubject");
-  assert_equals(
+  Assert.equal(
     "Delete",
     cwc.e("cmd_delete").getAttribute("label"),
     "attachmentBucket is not focused!"
   );
 
   // Focus back to the attachmentBucket
   force_focus("attachmentBucket");
-  assert_equals(
+  Assert.equal(
     "Remove Attachment",
     cwc.e("cmd_delete").getAttribute("label"),
     "Only 1 attachment is selected!"
   );
 
   // Select multiple attachments, and focus the identity for the same purpose
   attachment.selectAll();
   force_focus("msgIdentity");
-  assert_equals(
+  Assert.equal(
     "Delete",
     cwc.e("cmd_delete").getAttribute("label"),
     "attachmentBucket is not focused!"
   );
 
   // Focus back to the attachmentBucket
   force_focus("attachmentBucket");
-  assert_equals(
+  Assert.equal(
     "Remove Attachments",
     cwc.e("cmd_delete").getAttribute("label"),
     "Multiple attachments are selected!"
   );
 
   close_compose_window(cwc);
-}
+});
 
-function test_delete_from_toolbar() {
+add_task(function test_delete_from_toolbar() {
   be_in_folder(folder);
 
   // First, select the message with two attachments.
   select_none();
   select_click_row(3);
 
   // Expand the attachment list.
   mc.click(mc.eid("attachmentToggle"));
@@ -646,9 +644,9 @@ function test_delete_from_toolbar() {
   let firstAttachment = new elib.Elem(mc.e("attachmentList").firstElementChild);
   mc.click(firstAttachment, 5, 5);
 
   // Make sure clicking the "Delete" toolbar button with an attachment focused
   // deletes the *message*.
   plan_to_wait_for_folder_events("DeleteOrMoveMsgCompleted");
   mc.click(mc.eid("hdrTrashButton"));
   wait_for_folder_events();
-}
+});
copy from mail/test/mozmill/attachment/test-attachment-events.js
copy to mail/test/browser/attachment/browser_attachmentEvents.js
--- a/mail/test/mozmill/attachment/test-attachment-events.js
+++ b/mail/test/browser/attachment/browser_attachmentEvents.js
@@ -1,24 +1,26 @@
 /* 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/. */
 
 /**
  * Ensures that attachment events are fired properly
  */
 
+/* globals gFolderTreeView */
+
 "use strict";
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
 var { select_attachments } = ChromeUtils.import(
   "resource://testing-common/mozmill/AttachmentHelpers.jsm"
 );
-var { assert_equals, assert_true, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var {
   add_attachments,
   close_compose_window,
   open_compose_new_mail,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var { gMockPromptService } = ChromeUtils.import(
@@ -29,78 +31,74 @@ var { Services } = ChromeUtils.import("r
 var { fixIterator } = ChromeUtils.import(
   "resource:///modules/iteratorUtils.jsm"
 );
 
 var kAttachmentsAdded = "attachments-added";
 var kAttachmentsRemoved = "attachments-removed";
 var kAttachmentRenamed = "attachment-renamed";
 
-var gPath;
-
-function setupModule(module) {
-  gPath = os.getFileForPath(__file__);
-}
-
 /**
  * Test that the attachments-added event is fired when we add a single
  * attachment.
  */
-function test_attachments_added_on_single() {
+add_task(function test_attachments_added_on_single() {
+  gFolderTreeView.selectFolder(gFolderTreeView._enumerateFolders[1]);
+
   // Prepare to listen for attachments-added
   let eventCount = 0;
   let lastEvent;
   let listener = function(event) {
     eventCount++;
     lastEvent = event;
   };
 
   // Open up the compose window
   let cw = open_compose_new_mail(mc);
   cw.e("attachmentBucket").addEventListener(kAttachmentsAdded, listener);
 
   // Attach a single file
   add_attachments(cw, "http://www.example.com/1", 0, false);
 
   // Make sure we only saw the event once
-  assert_equals(1, eventCount);
+  Assert.equal(1, eventCount);
 
   // Make sure that we were passed the right subject
   let subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(
     "http://www.example.com/1",
     subjects.queryElementAt(0, Ci.nsIMsgAttachment).url
   );
 
   // Make sure that we can get that event again if we
   // attach more files.
   add_attachments(cw, "http://www.example.com/2", 0, false);
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
   subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(
     "http://www.example.com/2",
     subjects.queryElementAt(0, Ci.nsIMsgAttachment).url
   );
 
   // And check that we don't receive the event if we try to attach a file
   // that's already attached.
   add_attachments(cw, "http://www.example.com/2", null, false);
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
 
   cw.e("attachmentBucket").removeEventListener(kAttachmentsAdded, listener);
   close_compose_window(cw);
-}
+});
 
 /**
  * Test that the attachments-added event is fired when we add a series
  * of files all at once.
  */
-function test_attachments_added_on_multiple() {
+add_task(function test_attachments_added_on_multiple() {
   // Prepare to listen for attachments-added
   let eventCount = 0;
   let lastEvent;
   let listener = function(event) {
     eventCount++;
     lastEvent = event;
   };
 
@@ -111,25 +109,25 @@ function test_attachments_added_on_multi
   // Open the compose window and add the attachments
   let cw = open_compose_new_mail(mc);
   cw.e("attachmentBucket").addEventListener(kAttachmentsAdded, listener);
 
   add_attachments(cw, attachmentUrls, null, false);
 
   // Make sure we only saw a single attachments-added for this group
   // of files.
-  assert_equals(1, eventCount);
+  Assert.equal(1, eventCount);
 
   // Now make sure we got passed the right subjects for the event
   let subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(2, subjects.length);
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(2, subjects.length);
 
   for (let attachment of fixIterator(subjects, Ci.nsIMsgAttachment)) {
-    assert_true(attachmentUrls.includes(attachment.url));
+    Assert.ok(attachmentUrls.includes(attachment.url));
   }
 
   // Close the compose window - let's try again with 3 attachments.
   cw.e("attachmentBucket").removeEventListener(kAttachmentsAdded, listener);
   close_compose_window(cw);
 
   attachmentUrls = [
     "http://www.example.com/1",
@@ -138,41 +136,41 @@ function test_attachments_added_on_multi
   ];
 
   // Open the compose window and attach the files, and ensure that we saw
   // the attachments-added event
   cw = open_compose_new_mail(mc);
   cw.e("attachmentBucket").addEventListener(kAttachmentsAdded, listener);
 
   add_attachments(cw, attachmentUrls, null, false);
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
 
   // Make sure that we got the right subjects back
   subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(3, subjects.length);
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(3, subjects.length);
 
   for (let attachment of fixIterator(subjects, Ci.nsIMsgAttachment)) {
-    assert_true(attachmentUrls.includes(attachment.url));
+    Assert.ok(attachmentUrls.includes(attachment.url));
   }
 
   // Make sure we don't fire the event again if we try to attach the same
   // files.
   add_attachments(cw, attachmentUrls, null, false);
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
 
   cw.e("attachmentBucket").removeEventListener(kAttachmentsAdded, listener);
   close_compose_window(cw);
-}
+});
 
 /**
  * Test that the attachments-removed event is fired when removing a
  * single file.
  */
-function test_attachments_removed_on_single() {
+add_task(function test_attachments_removed_on_single() {
   // Prepare to listen for attachments-removed
   let eventCount = 0;
   let lastEvent;
   let listener = function(event) {
     eventCount++;
     lastEvent = event;
   };
 
@@ -183,51 +181,51 @@ function test_attachments_removed_on_sin
   add_attachments(cw, "http://www.example.com/1");
 
   // Now select that attachment and delete it
   select_attachments(cw, 0);
   // We need to hold a reference to removedAttachment here because
   // the delete routine nulls it out from the attachmentitem.
   cw.window.goDoCommand("cmd_delete");
   // Make sure we saw the event
-  assert_equals(1, eventCount);
+  Assert.equal(1, eventCount);
   // And make sure we were passed the right attachment item as the
   // subject.
   let subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(1, subjects.length);
-  assert_equals(
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(1, subjects.length);
+  Assert.equal(
     subjects.queryElementAt(0, Ci.nsIMsgAttachment).url,
     "http://www.example.com/1"
   );
 
   // Ok, let's attach it again, and remove it again to ensure that
   // we still see the event.
   add_attachments(cw, "http://www.example.com/2");
   select_attachments(cw, 0);
   cw.window.goDoCommand("cmd_delete");
 
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
   subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(1, subjects.length);
-  assert_equals(
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(1, subjects.length);
+  Assert.equal(
     subjects.queryElementAt(0, Ci.nsIMsgAttachment).url,
     "http://www.example.com/2"
   );
 
   cw.e("attachmentBucket").removeEventListener(kAttachmentsRemoved, listener);
   close_compose_window(cw);
-}
+});
 
 /**
  * Test that the attachments-removed event is fired when removing multiple
  * files all at once.
  */
-function test_attachments_removed_on_multiple() {
+add_task(function test_attachments_removed_on_multiple() {
   // Prepare to listen for attachments-removed
   let eventCount = 0;
   let lastEvent;
   let listener = function(event) {
     eventCount++;
     lastEvent = event;
   };
 
@@ -246,44 +244,44 @@ function test_attachments_removed_on_mul
 
   let removedAttachmentUrls = removedAttachmentItems.map(
     aAttachment => aAttachment.attachment.url
   );
 
   cw.window.goDoCommand("cmd_delete");
 
   // We should have seen the attachments-removed event exactly once.
-  assert_equals(1, eventCount);
+  Assert.equal(1, eventCount);
 
   // Now let's make sure we got passed back the right attachment items
   // as the event subject
   let subjects = lastEvent.detail;
-  assert_true(subjects instanceof Ci.nsIMutableArray);
-  assert_equals(3, subjects.length);
+  Assert.ok(subjects instanceof Ci.nsIMutableArray);
+  Assert.equal(3, subjects.length);
 
   for (let attachment of fixIterator(subjects, Ci.nsIMsgAttachment)) {
-    assert_true(removedAttachmentUrls.includes(attachment.url));
+    Assert.ok(removedAttachmentUrls.includes(attachment.url));
   }
 
   // Ok, let's attach and remove some again to ensure that we still see the event.
   add_attachments(cw, ["http://www.example.com/1", "http://www.example.com/2"]);
 
   select_attachments(cw, 0, 1);
   cw.window.goDoCommand("cmd_delete");
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
 
   cw.e("attachmentBucket").removeEventListener(kAttachmentsRemoved, listener);
   close_compose_window(cw);
-}
+});
 
 /**
  * Test that we don't see the attachments-removed event if no attachments
  * are selected when hitting "Delete"
  */
-function test_no_attachments_removed_on_none() {
+add_task(function test_no_attachments_removed_on_none() {
   // Prepare to listen for attachments-removed
   let eventCount = 0;
   let listener = function(event) {
     eventCount++;
   };
 
   // Open the compose window and add some attachments.
   let cw = open_compose_new_mail(mc);
@@ -295,27 +293,27 @@ function test_no_attachments_removed_on_
     "http://www.example.com/3",
   ]);
 
   // Choose no attachments
   cw.e("attachmentBucket").clearSelection();
   // Run the delete command
   cw.window.goDoCommand("cmd_delete");
   // Make sure we didn't see the attachments_removed event.
-  assert_equals(0, eventCount);
+  Assert.equal(0, eventCount);
   cw.e("attachmentBucket").removeEventListener(kAttachmentsRemoved, listener);
 
   close_compose_window(cw);
-}
+});
 
 /**
  * Test that we see the attachment-renamed event when an attachments
  * name is changed.
  */
-function test_attachment_renamed() {
+add_task(function test_attachment_renamed() {
   // Here's what we'll rename some files to.
   const kRenameTo1 = "Renamed-1";
   const kRenameTo2 = "Renamed-2";
   const kRenameTo3 = "Renamed-3";
 
   // Prepare to listen for attachment-renamed
   let eventCount = 0;
   let lastEvent;
@@ -341,72 +339,72 @@ function test_attachment_renamed() {
     "http://www.example.com/2",
     "http://www.example.com/3",
   ]);
 
   select_attachments(cw, 0);
   cw.window.goDoCommand("cmd_renameAttachment");
 
   // Ensure that we saw the attachment-renamed event
-  assert_equals(1, eventCount);
+  Assert.equal(1, eventCount);
   // Ensure that the event mentions the right attachment
   let renamedAttachment1 = lastEvent.target.attachment;
   let originalName1 = lastEvent.detail;
-  assert_true(renamedAttachment1 instanceof Ci.nsIMsgAttachment);
-  assert_equals(kRenameTo1, renamedAttachment1.name);
-  assert_true(renamedAttachment1.url.includes("http://www.example.com/1"));
-  assert_equals("www.example.com/1", originalName1);
+  Assert.ok(renamedAttachment1 instanceof Ci.nsIMsgAttachment);
+  Assert.equal(kRenameTo1, renamedAttachment1.name);
+  Assert.ok(renamedAttachment1.url.includes("http://www.example.com/1"));
+  Assert.equal("www.example.com/1", originalName1);
 
   // Ok, let's try renaming the same attachment.
   gMockPromptService.reset();
   gMockPromptService.inoutValue = kRenameTo2;
   gMockPromptService.returnValue = true;
 
   select_attachments(cw, 0);
   cw.window.goDoCommand("cmd_renameAttachment");
 
-  assert_equals(2, eventCount);
+  Assert.equal(2, eventCount);
   let renamedAttachment2 = lastEvent.target.attachment;
   let originalName2 = lastEvent.detail;
-  assert_true(renamedAttachment2 instanceof Ci.nsIMsgAttachment);
-  assert_equals(kRenameTo2, renamedAttachment2.name);
-  assert_true(renamedAttachment2.url.includes("http://www.example.com/1"));
-  assert_equals(kRenameTo1, originalName2);
+  Assert.ok(renamedAttachment2 instanceof Ci.nsIMsgAttachment);
+  Assert.equal(kRenameTo2, renamedAttachment2.name);
+  Assert.ok(renamedAttachment2.url.includes("http://www.example.com/1"));
+  Assert.equal(kRenameTo1, originalName2);
 
   // Ok, let's rename another attachment
   gMockPromptService.reset();
   gMockPromptService.inoutValue = kRenameTo3;
   gMockPromptService.returnValue = true;
 
   // We'll select the second attachment this time.
   select_attachments(cw, 1);
   cw.window.goDoCommand("cmd_renameAttachment");
 
   // Ensure we saw the attachment-renamed event
-  assert_equals(3, eventCount);
+  Assert.equal(3, eventCount);
   // Ensure that the event mentions the right attachment
   let renamedAttachment3 = lastEvent.target.attachment;
   let originalName3 = lastEvent.detail;
-  assert_true(renamedAttachment3 instanceof Ci.nsIMsgAttachment);
-  assert_equals(kRenameTo3, renamedAttachment3.name);
-  assert_true(renamedAttachment3.url.includes("http://www.example.com/2"));
-  assert_equals("www.example.com/2", originalName3);
+  Assert.ok(renamedAttachment3 instanceof Ci.nsIMsgAttachment);
+  Assert.equal(kRenameTo3, renamedAttachment3.name);
+  Assert.ok(renamedAttachment3.url.includes("http://www.example.com/2"));
+  Assert.equal("www.example.com/2", originalName3);
 
   // Unregister the Mock Prompt service, and remove our observer.
   cw.e("attachmentBucket").removeEventListener(kAttachmentRenamed, listener);
 
   close_compose_window(cw);
   gMockPromptService.unregister();
-}
+});
 
 /**
  * Test that the attachment-renamed event is not fired if we set the
  * filename to be blank.
  */
-function test_no_attachment_renamed_on_blank() {
+add_task(function test_no_attachment_renamed_on_blank() {
   // Prepare to listen for attachment-renamed
   let eventCount = 0;
   let listener = function(event) {
     eventCount++;
   };
 
   // Register the Mock Prompt Service to return the empty string when
   // prompted.
@@ -425,13 +423,13 @@ function test_no_attachment_renamed_on_b
     "http://www.example.com/2",
     "http://www.example.com/3",
   ]);
 
   select_attachments(cw, 0);
   cw.window.goDoCommand("cmd_renameAttachment");
 
   // Ensure that we didn't see the attachment-renamed event.
-  assert_equals(0, eventCount);
+  Assert.equal(0, eventCount);
   cw.e("attachmentBucket").removeEventListener(kAttachmentRenamed, listener);
   close_compose_window(cw);
   gMockPromptService.unregister();
-}
+});
copy from mail/test/mozmill/attachment/test-attachment-in-plain-msg.js
copy to mail/test/browser/attachment/browser_attachmentInPlainMsg.js
--- a/mail/test/mozmill/attachment/test-attachment-in-plain-msg.js
+++ b/mail/test/browser/attachment/browser_attachmentInPlainMsg.js
@@ -1,57 +1,51 @@
 /* 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/. */
 
 "use strict";
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
 var { wait_for_element_visible } = ChromeUtils.import(
   "resource://testing-common/mozmill/DOMHelpers.jsm"
 );
-var {
-  assert_equals,
-  assert_false,
-  assert_true,
-  open_message_from_file,
-} = ChromeUtils.import(
+var { open_message_from_file } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { close_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 /**
  * Bug 1358565
  * Check that a non-empty image is shown as attachment and is detected as non-empty
  * when message is viewed as plain text.
  */
-async function test_attachment_not_empty() {
+add_task(async function test_attachment_not_empty() {
   Services.prefs.setBoolPref("mailnews.display.prefer_plaintext", true);
 
-  let thisFilePath = os.getFileForPath(__file__);
-  let file = os.getFileForPath(os.abspath("./bug1358565.eml", thisFilePath));
+  let file = new FileUtils.File(getTestFilePath("data/bug1358565.eml"));
 
   let msgc = open_message_from_file(file);
 
   wait_for_element_visible(msgc, "attachmentToggle");
   msgc.click(msgc.eid("attachmentToggle"));
 
   wait_for_element_visible(msgc, "attachmentList");
-  assert_equals(msgc.e("attachmentList").itemCount, 1);
+  Assert.equal(msgc.e("attachmentList").itemCount, 1);
 
   let attachmentElem = msgc.e("attachmentList").getItemAtIndex(0);
-  assert_equals(attachmentElem.attachment.contentType, "image/jpeg");
-  assert_equals(attachmentElem.attachment.name, "bug.png");
-  assert_true(attachmentElem.attachment.hasFile);
-  assert_false(
-    await attachmentElem.attachment.isEmpty(),
+  Assert.equal(attachmentElem.attachment.contentType, "image/jpeg");
+  Assert.equal(attachmentElem.attachment.name, "bug.png");
+  Assert.ok(attachmentElem.attachment.hasFile);
+  Assert.ok(
+    !(await attachmentElem.attachment.isEmpty()),
     "Attachment incorrectly determined empty"
   );
 
   close_window(msgc);
 
   Services.prefs.clearUserPref("mailnews.display.prefer_plaintext");
-}
+});
copy from mail/test/mozmill/attachment/test-attachment-menus.js
copy to mail/test/browser/attachment/browser_attachmentMenus.js
--- a/mail/test/mozmill/attachment/test-attachment-menus.js
+++ b/mail/test/browser/attachment/browser_attachmentMenus.js
@@ -4,21 +4,21 @@
 
 "use strict";
 
 var folder;
 var messenger;
 var epsilon;
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 var controller = ChromeUtils.import(
-  "chrome://mozmill/content/modules/controller.jsm"
+  "resource://testing-common/mozmill/controller.jsm"
 );
 
 var {
   create_body_part,
   create_deleted_attachment,
   create_detached_attachment,
   create_enclosure_attachment,
 } = ChromeUtils.import(
@@ -178,41 +178,41 @@ var messages = [
     menuStates: [
       { open: false, save: false, detach: false, delete_: false },
       { open: false, save: false, detach: false, delete_: false },
     ],
     allMenuStates: { open: false, save: false, detach: false, delete_: false },
   },
 ];
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger);
 
   /* Today's gory details (thanks to Jonathan Protzenko): libmime somehow
    * counts the trailing newline for an attachment MIME part. Most of the time,
    * assuming attachment has N bytes (no matter what's inside, newlines or
    * not), libmime will return N + 1 bytes. On Linux and Mac, this always
    * holds. However, on Windows, if the attachment is not encoded (that is, is
    * inline text), libmime will return N + 2 bytes.
    */
   epsilon = "@mozilla.org/windows-registry-key;1" in Cc ? 2 : 1;
 
   // set up our detached/deleted attachments
-  var thisFilePath = os.getFileForPath(__file__);
-
-  var detachedFile = os.getFileForPath(os.abspath(detachedName, thisFilePath));
+  var detachedFile = new FileUtils.File(
+    getTestFilePath(`data/${detachedName}`)
+  );
   var detached = create_body_part("Here is a file", [
     create_detached_attachment(detachedFile, "text/plain"),
   ]);
   var multiple_detached = create_body_part("Here are some files", [
     create_detached_attachment(detachedFile, "text/plain"),
     create_detached_attachment(detachedFile, "text/plain"),
   ]);
 
-  var missingFile = os.getFileForPath(os.abspath(missingName, thisFilePath));
+  var missingFile = new FileUtils.File(getTestFilePath(`data/${missingName}`));
   var missing = create_body_part(
     "Here is a file (but you deleted the external file, you silly oaf!)",
     [create_detached_attachment(missingFile, "text/plain")]
   );
   var multiple_missing = create_body_part(
     "Here are some files (but you deleted the external files, you silly oaf!)",
     [
       create_detached_attachment(missingFile, "text/plain"),
@@ -337,17 +337,17 @@ function setupModule(module) {
         break;
       case "link_multiple_enclosures_all_invalid":
         messages[i].bodyPart = multiple_enclosures_all_links_invalid;
         break;
     }
 
     add_message_to_folder(folder, create_message(messages[i]));
   }
-}
+});
 
 /**
  * Ensure that the specified element is visible/hidden
  *
  * @param id the id of the element to check
  * @param visible true if the element should be visible, false otherwise
  */
 function assert_shown(id, visible) {
@@ -381,17 +381,17 @@ function check_toolbar_menu_states_singl
   assert_shown("attachmentSaveAllSingle", true);
   assert_shown("attachmentSaveAllMultiple", false);
 
   if (expected.save === false) {
     assert_enabled("attachmentSaveAllSingle", false);
   } else {
     assert_enabled("attachmentSaveAllSingle", true);
     mc.click(
-      new elementslib.Elem(
+      new elib.Elem(
         mc
           .e("attachmentSaveAllSingle")
           .querySelector(".toolbarbutton-menubutton-dropmarker")
       )
     );
     wait_for_popup_to_open(mc.e("attachmentSaveAllSingleMenu"));
 
     try {
@@ -414,17 +414,17 @@ function check_toolbar_menu_states_multi
   assert_shown("attachmentSaveAllSingle", false);
   assert_shown("attachmentSaveAllMultiple", true);
 
   if (expected.save === false) {
     assert_enabled("attachmentSaveAllMultiple", false);
   } else {
     assert_enabled("attachmentSaveAllMultiple", true);
     mc.click(
-      new elementslib.Elem(
+      new elib.Elem(
         mc
           .e("attachmentSaveAllMultiple")
           .querySelector(".toolbarbutton-menubutton-dropmarker")
       )
     );
     wait_for_popup_to_open(mc.e("attachmentSaveAllMultipleMenu"));
 
     try {
@@ -522,14 +522,22 @@ function help_test_attachment_menus(inde
 
   check_menu_states_all(messages[index].allMenuStates);
   for (let i = 0; i < expectedStates.length; i++) {
     check_menu_states_single(i, expectedStates[i]);
   }
 }
 
 // Generate a test for each message in |messages|.
-for (let [i, message] of messages.entries()) {
-  let index = i; // make a copy to avoid passing a reference to i
-  this["test_" + message.name] = function() {
-    help_test_attachment_menus(index);
-  };
+for (let i = 0; i < messages.length; i++) {
+  add_task(function() {
+    help_test_attachment_menus(i);
+  });
 }
+
+add_task(() => {
+  Assert.report(
+    false,
+    undefined,
+    undefined,
+    "Test ran to completion successfully"
+  );
+});
copy from mail/test/mozmill/attachment/test-attachment-size.js
copy to mail/test/browser/attachment/browser_attachmentSize.js
--- a/mail/test/mozmill/attachment/test-attachment-size.js
+++ b/mail/test/browser/attachment/browser_attachmentSize.js
@@ -3,19 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 var folder;
 var messenger;
 var epsilon;
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 var controller = ChromeUtils.import(
-  "chrome://mozmill/content/modules/controller.jsm"
+  "resource://testing-common/mozmill/controller.jsm"
 );
 
 var {
   create_body_part,
   create_deleted_attachment,
   create_detached_attachment,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AttachmentHelpers.jsm"
@@ -170,37 +170,37 @@ var messages = [
   {
     name: "attached_message_with_attachment",
     bodyPart: null,
     attachmentSizes: [-1, textAttachment.length],
     attachmentTotalSize: { size: 0, exact: true },
   },
 ];
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger);
 
   /* Today's gory details (thanks to Jonathan Protzenko): libmime somehow
    * counts the trailing newline for an attachment MIME part. Most of the time,
    * assuming attachment has N bytes (no matter what's inside, newlines or
    * not), libmime will return N + 1 bytes. On Linux and Mac, this always
    * holds. However, on Windows, if the attachment is not encoded (that is, is
    * inline text), libmime will return N + 2 bytes.
    */
   epsilon = "@mozilla.org/windows-registry-key;1" in Cc ? 4 : 2;
 
   // set up our detached/deleted attachments
-  var thisFilePath = os.getFileForPath(__file__);
-
-  var detachedFile = os.getFileForPath(os.abspath(detachedName, thisFilePath));
+  var detachedFile = new FileUtils.File(
+    getTestFilePath(`data/${detachedName}`)
+  );
   var detached = create_body_part("Here is a file", [
     create_detached_attachment(detachedFile, "text/plain"),
   ]);
 
-  var missingFile = os.getFileForPath(os.abspath(missingName, thisFilePath));
+  var missingFile = new FileUtils.File(getTestFilePath(`data/${missingName}`));
   var missing = create_body_part(
     "Here is a file (but you deleted the external file, you silly oaf!)",
     [create_detached_attachment(missingFile, "text/plain")]
   );
 
   var deleted = create_body_part("Here is a file that you deleted", [
     create_deleted_attachment(deletedName, "text/plain"),
   ]);
@@ -250,17 +250,17 @@ function setupModule(module) {
         ]);
         messages[i].attachmentSizes[0] = attachedMessageLength;
         messages[i].attachmentTotalSize.size += attachedMessageLength;
         break;
     }
 
     add_message_to_folder(folder, create_message(messages[i]));
   }
-}
+});
 
 /**
  * Make sure that the attachment's size is what we expect
  * @param index the attachment's index, starting at 0
  * @param expectedSize the expected size of the attachment, in bytes
  */
 function check_attachment_size(index, expectedSize) {
   let list = mc.e("attachmentList");
@@ -417,14 +417,22 @@ function help_test_attachment_size(index
   check_total_attachment_size(
     expectedSizes.length,
     totalSize.size,
     totalSize.exact
   );
 }
 
 // Generate a test for each message in |messages|.
-for (let [i, message] of messages.entries()) {
-  let index = i; // make a copy to avoid passing a reference to i
-  this["test_" + message.name] = function() {
-    help_test_attachment_size(index);
-  };
+for (let i = 0; i < messages.length; i++) {
+  add_task(function() {
+    help_test_attachment_size(i);
+  });
 }
+
+add_task(() => {
+  Assert.report(
+    false,
+    undefined,
+    undefined,
+    "Test ran to completion successfully"
+  );
+});
copy from mail/test/mozmill/attachment/attachment.txt
copy to mail/test/browser/attachment/data/attachment.txt
copy from mail/test/mozmill/attachment/bug1358565.eml
copy to mail/test/browser/attachment/data/bug1358565.eml
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/cloudfile/browser.ini
@@ -0,0 +1,53 @@
+[DEFAULT]
+head = head.js
+prefs =
+  browser.tabs.remote.autostart=false
+  ldap_2.servers.osx.description=
+  ldap_2.servers.osx.dirType=-1
+  ldap_2.servers.osx.uri=
+  mail.account.account1.server=server1
+  mail.account.account2.identities=id1,id2
+  mail.account.account2.server=server2
+  mail.accountmanager.accounts=account1,account2
+  mail.accountmanager.defaultaccount=account2
+  mail.accountmanager.localfoldersserver=server1
+  mail.identity.id1.fullName=Tinderbox
+  mail.identity.id1.htmlSigFormat=false
+  mail.identity.id1.smtpServer=smtp1
+  mail.identity.id1.useremail=tinderbox@foo.invalid
+  mail.identity.id1.valid=true
+  mail.identity.id2.fullName=Tinderboxpushlog
+  mail.identity.id2.htmlSigFormat=true
+  mail.identity.id2.smtpServer=smtp1
+  mail.identity.id2.useremail=tinderboxpushlog@foo.invalid
+  mail.identity.id2.valid=true
+  mail.provider.suppress_dialog_on_startup=true
+  mail.server.server1.type=none
+  mail.server.server1.userName=nobody
+  mail.server.server2.check_new_mail=false
+  mail.server.server2.directory-rel=[ProfD]Mail/tinderbox
+  mail.server.server2.download_on_biff=true
+  mail.server.server2.hostname=tinderbox123
+  mail.server.server2.login_at_startup=false
+  mail.server.server2.name=tinderbox@foo.invalid
+  mail.server.server2.type=pop3
+  mail.server.server2.userName=tinderbox
+  mail.server.server2.whiteListAbURI=
+  mail.shell.checkDefaultClient=false
+  mail.smtp.defaultserver=smtp1
+  mail.smtpserver.smtp1.hostname=tinderbox123
+  mail.smtpserver.smtp1.username=tinderbox
+  mail.smtpservers=smtp1
+  mail.spotlight.firstRunDone=true
+  mail.winsearch.firstRunDone=true
+  mailnews.start_page.override_url=about:blank
+  mailnews.start_page.url=about:blank
+subsuite = thunderbird
+support-files =
+  data/**
+  html/**
+
+[browser_attachmentItem.js]
+[browser_attachmentUrls.js]
+[browser_manager.js]
+[browser_notifications.js]
copy from mail/test/mozmill/cloudfile/test-cloudfile-attachment-item.js
copy to mail/test/browser/cloudfile/browser_attachmentItem.js
--- a/mail/test/mozmill/cloudfile/test-cloudfile-attachment-item.js
+++ b/mail/test/browser/cloudfile/browser_attachmentItem.js
@@ -3,71 +3,75 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Tests Filelink attachment item behaviour.
  */
 
 "use strict";
 
+var mozmill = ChromeUtils.import(
+  "resource://testing-common/mozmill/mozmill.jsm"
+);
+
 var {
   gMockFilePicker,
   gMockFilePickReg,
   select_attachments,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AttachmentHelpers.jsm"
 );
 var {
-  collectFiles,
   getFile,
   gMockCloudfileManager,
   MockCloudfileAccount,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/CloudfileHelpers.jsm"
 );
 var {
   add_cloud_attachments,
   close_compose_window,
   open_compose_new_mail,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
-var { assert_false, close_popup } = ChromeUtils.import(
+var { close_popup } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
-var kAttachmentItemContextID = "msgComposeAttachmentItemContext";
-
 var { cloudFileAccounts } = ChromeUtils.import(
   "resource:///modules/cloudFileAccounts.jsm"
 );
 
-function setupModule(module) {
+var controller = mozmill.getMail3PaneController();
+var kAttachmentItemContextID = "msgComposeAttachmentItemContext";
+
+add_task(function setupModule(module) {
   gMockFilePickReg.register();
   gMockCloudfileManager.register();
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   gMockCloudfileManager.unregister();
   gMockFilePickReg.unregister();
-}
+});
 
 /**
  * Test that when an upload has been started, we can cancel and restart
  * the upload, and then cancel again.  For this test, we repeat this
  * 3 times.
  */
-function test_upload_cancel_repeat() {
+add_task(function test_upload_cancel_repeat() {
   const kFile = "./data/testFile1";
 
   // Prepare the mock file picker to return our test file.
-  let file = getFile(kFile, __file__);
+  let file = new FileUtils.File(getTestFilePath(kFile));
   gMockFilePicker.returnFiles = [file];
 
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
-  let cw = open_compose_new_mail();
+  let cw = open_compose_new_mail(controller);
 
   // We've got a compose window open, and our mock Filelink provider
   // ready.  Let's attach a file...
   cw.window.AttachFile();
 
   // Now we override the uploadFile function of the MockCloudfileAccount
   // so that we're perpetually uploading...
   let promise;
@@ -85,29 +89,30 @@ function test_upload_cancel_repeat() {
     started = false;
 
     // Select the attachment, and choose to convert it to a Filelink
     select_attachments(cw, 0)[0];
     cw.window.convertSelectedToCloudAttachment(provider);
     cw.waitFor(() => started);
 
     assert_can_cancel_upload(cw, provider, promise, file);
+    cw.sleep();
   }
 
   close_compose_window(cw);
-}
+});
 
 /**
  * Test that we can cancel a whole series of files being uploaded at once.
  */
-function test_upload_multiple_and_cancel() {
+add_task(function test_upload_multiple_and_cancel() {
   const kFiles = ["./data/testFile1", "./data/testFile2", "./data/testFile3"];
 
   // Prepare the mock file picker to return our test file.
-  let files = collectFiles(kFiles, __file__);
+  let files = collectFiles(kFiles);
   gMockFilePicker.returnFiles = files;
 
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
   let cw = open_compose_new_mail();
 
   let promise;
   provider.uploadFile = function(aFile) {
@@ -118,17 +123,17 @@ function test_upload_multiple_and_cancel
 
   add_cloud_attachments(cw, provider, false);
 
   for (let i = files.length - 1; i >= 0; --i) {
     assert_can_cancel_upload(cw, provider, promise, files[i]);
   }
 
   close_compose_window(cw);
-}
+});
 
 /**
  * Helper function that takes an upload in progress, and cancels it,
  * ensuring that the nsIMsgCloduFileProvider.uploadCanceled status message
  * is returned to the passed in listener.
  *
  * @param aController the compose window controller to use.
  * @param aProvider a MockCloudfileAccount for which the uploads have already
@@ -159,18 +164,18 @@ function assert_can_cancel_upload(
 
   // Select that attachmentitem in the bucket
   select_attachments(aController, index)[0];
 
   // Bring up the context menu, and click cancel.
   let cmd = aController.e("cmd_cancelUpload");
   aController.window.updateAttachmentItems();
 
-  assert_false(cmd.hidden);
-  assert_false(cmd.disabled);
+  Assert.ok(!cmd.hidden);
+  Assert.ok(!cmd.disabled);
   let cancelItem = aController.eid("composeAttachmentContext_cancelUploadItem");
   aController.click(cancelItem);
 
   // Close the popup, and wait for the cancellation to be complete.
   close_popup(aController, aController.eid(kAttachmentItemContextID));
   aController.waitFor(() => cancelled);
 }
 
copy from mail/test/mozmill/cloudfile/test-cloudfile-attachment-urls.js
copy to mail/test/browser/cloudfile/browser_attachmentUrls.js
--- a/mail/test/mozmill/cloudfile/test-cloudfile-attachment-urls.js
+++ b/mail/test/browser/cloudfile/browser_attachmentUrls.js
@@ -10,21 +10,17 @@
 
 var {
   gMockFilePicker,
   gMockFilePickReg,
   select_attachments,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AttachmentHelpers.jsm"
 );
-var {
-  collectFiles,
-  gMockCloudfileManager,
-  MockCloudfileAccount,
-} = ChromeUtils.import(
+var { gMockCloudfileManager, MockCloudfileAccount } = ChromeUtils.import(
   "resource://testing-common/mozmill/CloudfileHelpers.jsm"
 );
 var {
   add_cloud_attachments,
   assert_previous_text,
   get_compose_body,
   open_compose_new_mail,
   open_compose_with_forward,
@@ -33,88 +29,95 @@ var {
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
   assert_next_nodes,
   assert_previous_nodes,
   wait_for_element,
 } = ChromeUtils.import("resource://testing-common/mozmill/DOMHelpers.jsm");
 var {
   add_message_to_folder,
-  assert_equals,
-  assert_not_equals,
   assert_selected_and_displayed,
-  assert_true,
   be_in_folder,
   create_message,
   FAKE_SERVER_HOSTNAME,
   get_special_folder,
   mc,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
+var mozmill = ChromeUtils.import(
+  "resource://testing-common/mozmill/mozmill.jsm"
+);
 var { close_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
+var controller = mozmill.getMail3PaneController();
 var kUploadedFile = "attachment-uploaded";
 var kHtmlPrefKey = "mail.identity.default.compose_html";
 var kReplyOnTopKey = "mail.identity.default.reply_on_top";
 var kReplyOnTop = 1;
 var kReplyOnBottom = 0;
 var kTextNodeType = 3;
 var kSigPrefKey = "mail.identity.id1.htmlSigText";
 var kSigOnReplyKey = "mail.identity.default.sig_on_reply";
 var kSigOnForwardKey = "mail.identity.default.sig_on_fwd";
 var kDefaultSigKey = "mail.identity.id1.htmlSigText";
 var kDefaultSig = "This is my signature.\n\nCheck out my website sometime!";
 var kFiles = ["./data/testFile1", "./data/testFile2"];
 var kLines = ["This is a line of text", "and here's another!"];
 
-var gInbox, gOldHtmlPref, gOldSigPref;
+var gInbox;
+
+add_task(function setupModule(module) {
+  requestLongerTimeout(2);
 
-function setupModule(module) {
+  // These prefs can't be set in the manifest as they contain white-space.
+  Services.prefs.setStringPref(
+    "mail.identity.id1.htmlSigText",
+    "Tinderbox is soo 90ies"
+  );
+  Services.prefs.setStringPref(
+    "mail.identity.id2.htmlSigText",
+    "Tinderboxpushlog is the new <b>hotness!</b>"
+  );
+
   // For replies and forwards, we'll work off a message in the Inbox folder
   // of the fake "tinderbox" account.
   let server = MailServices.accounts.FindServer(
     "tinderbox",
     FAKE_SERVER_HOSTNAME,
     "pop3"
   );
   gInbox = get_special_folder(Ci.nsMsgFolderFlags.Inbox, false, server);
   add_message_to_folder(gInbox, create_message());
 
   gMockFilePickReg.register();
   gMockCloudfileManager.register();
 
-  // These tests assume that we default to writing mail in HTML.  We'll
-  // save the current preference, force defaulting to HTML, and restore the
-  // pref in teardownModule.
-  gOldHtmlPref = Services.prefs.getBoolPref(kHtmlPrefKey);
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
-  // Same goes for the default signature.
-  gOldSigPref = Services.prefs.getCharPref(kDefaultSigKey);
 
   // Don't create paragraphs in the test.
   // The test fails if it encounters paragraphs <p> instead of breaks <br>.
   Services.prefs.setBoolPref("mail.compose.default_to_paragraph", false);
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   gMockCloudfileManager.unregister();
   gMockFilePickReg.unregister();
-  Services.prefs.setCharPref(kDefaultSigKey, gOldSigPref);
-  Services.prefs.setBoolPref(kHtmlPrefKey, gOldHtmlPref);
+  Services.prefs.clearUserPref(kDefaultSigKey);
+  Services.prefs.clearUserPref(kHtmlPrefKey);
   Services.prefs.clearUserPref("mail.compose.default_to_paragraph");
-}
+});
 
 function setupTest() {
   // If our signature got accidentally wiped out, let's just put it back.
   Services.prefs.setCharPref(kDefaultSigKey, kDefaultSig);
 }
 
 /**
  * Given some compose window controller, wait for some Filelink URLs to be
@@ -159,17 +162,17 @@ function wait_for_attachment_urls(aContr
  * @param aText an array of strings to type into the compose window. Each
  *              string is followed by pressing the RETURN key, except for
  *              the final string.  Pass an empty array if you don't want
  *              anything typed.
  * @param aFiles an array of filename strings for files located beneath
  *               the test directory.
  */
 function prepare_some_attachments_and_reply(aText, aFiles) {
-  gMockFilePicker.returnFiles = collectFiles(aFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(aFiles);
 
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
 
   be_in_folder(gInbox);
   let msg = select_click_row(0);
   assert_selected_and_displayed(mc, msg);
 
@@ -190,17 +193,17 @@ function prepare_some_attachments_and_re
  * @param aText an array of strings to type into the compose window. Each
  *              string is followed by pressing the RETURN key, except for
  *              the final string.  Pass an empty array if you don't want
  *              anything typed.
  * @param aFiles an array of filename strings for files located beneath
  *               the test directory.
  */
 function prepare_some_attachments_and_forward(aText, aFiles) {
-  gMockFilePicker.returnFiles = collectFiles(aFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(aFiles);
 
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
 
   be_in_folder(gInbox);
   let msg = select_click_row(0);
   assert_selected_and_displayed(mc, msg);
 
@@ -268,139 +271,139 @@ function try_with_plaintext_and_html_mai
 }
 
 /**
  * Test that if we open up a composer and immediately attach a Filelink,
  * a linebreak is inserted before the containment node in order to allow
  * the user to write before the attachment URLs.  This assumes the user
  * does not have a signature already inserted into the message body.
  */
-function test_inserts_linebreak_on_empty_compose() {
+add_task(function test_inserts_linebreak_on_empty_compose() {
   try_without_signature(subtest_inserts_linebreak_on_empty_compose);
-}
+});
 
 /**
  * Subtest for test_inserts_linebreak_on_empty_compose - can be executed
  * on both plaintext and HTML compose windows.
  */
 function subtest_inserts_linebreak_on_empty_compose() {
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
   let cw = open_compose_new_mail();
   add_cloud_attachments(cw, provider);
 
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
 
   let br = root.previousSibling;
-  assert_equals(
+  Assert.equal(
     br.localName,
     "br",
     "The attachment URL containment node should be preceded by a linebreak"
   );
 
   let mailBody = get_compose_body(cw);
 
-  assert_equals(
+  Assert.equal(
     mailBody.firstChild,
     br,
     "The linebreak should be the first child of the compose body"
   );
 
   close_window(cw);
 }
 
 /**
  * Test that if we open up a composer and immediately attach a Filelink,
  * a linebreak is inserted before the containment node. This test also
  * ensures that, with a signature already in the compose window, we don't
  * accidentally insert the attachment URL containment within the signature
  * node.
  */
-function test_inserts_linebreak_on_empty_compose_with_signature() {
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+add_task(function test_inserts_linebreak_on_empty_compose_with_signature() {
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
   let cw = open_compose_new_mail();
   add_cloud_attachments(cw, provider);
   // wait_for_attachment_urls ensures that the attachment URL containment
   // node is an immediate child of the body of the message, so if this
   // succeeds, then we were not in the signature node.
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
 
   let br = assert_previous_nodes("br", root, 1);
 
   let mailBody = get_compose_body(cw);
-  assert_equals(
+  Assert.equal(
     mailBody.firstChild,
     br,
     "The linebreak should be the first child of the compose body"
   );
 
   // Now ensure that the node after the attachments is a br, and following
   // that is the signature.
   br = assert_next_nodes("br", root, 1);
 
   let pre = br.nextSibling;
-  assert_equals(
+  Assert.equal(
     pre.localName,
     "pre",
     "The linebreak should be followed by the signature pre"
   );
-  assert_true(
+  Assert.ok(
     pre.classList.contains("moz-signature"),
     "The pre should have the moz-signature class"
   );
 
   close_window(cw);
 
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
 
   // Now let's try with plaintext mail.
   cw = open_compose_new_mail();
   add_cloud_attachments(cw, provider);
   [root] = wait_for_attachment_urls(cw, kFiles.length);
 
   br = assert_previous_nodes("br", root, 1);
 
   mailBody = get_compose_body(cw);
-  assert_equals(
+  Assert.equal(
     mailBody.firstChild,
     br,
     "The linebreak should be the first child of the compose body"
   );
 
   // Now ensure that the node after the attachments is a br, and following
   // that is the signature.
   br = assert_next_nodes("br", root, 1);
 
   let div = br.nextSibling;
-  assert_equals(
+  Assert.equal(
     div.localName,
     "div",
     "The linebreak should be followed by the signature div"
   );
-  assert_true(
+  Assert.ok(
     div.classList.contains("moz-signature"),
     "The div should have the moz-signature class"
   );
 
   close_window(cw);
 
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
-}
+});
 
 /**
  * Tests that removing all Filelinks causes the root node to be removed.
  */
-function test_removing_filelinks_removes_root_node() {
+add_task(function test_removing_filelinks_removes_root_node() {
   try_with_plaintext_and_html_mail(
     subtest_removing_filelinks_removes_root_node
   );
-}
+});
 
 /**
  * Test for test_removing_filelinks_removes_root_node - can be executed
  * on both plaintext and HTML compose windows.
  */
 function subtest_removing_filelinks_removes_root_node() {
   let cw = prepare_some_attachments_and_reply([], kFiles);
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
@@ -420,90 +423,90 @@ function subtest_removing_filelinks_remo
 }
 
 /**
  * Test that if we write some text in an empty message (no signature),
  * and the selection is at the end of a line of text, attaching some Filelinks
  * causes the attachment URL container to be separated from the text by
  * two br tags.
  */
-function test_adding_filelinks_to_written_message() {
+add_task(function test_adding_filelinks_to_written_message() {
   try_without_signature(subtest_adding_filelinks_to_written_message);
-}
+});
 
 /**
  * Subtest for test_adding_filelinks_to_written_message - generalized for both
  * HTML and plaintext mail.
  */
 function subtest_adding_filelinks_to_written_message() {
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
   let cw = open_compose_new_mail();
 
   type_in_composer(cw, kLines);
   add_cloud_attachments(cw, provider);
 
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
 
   let br = root.previousSibling;
-  assert_equals(
+  Assert.equal(
     br.localName,
     "br",
     "The attachment URL containment node should be preceded by a linebreak"
   );
   br = br.previousSibling;
-  assert_equals(
+  Assert.equal(
     br.localName,
     "br",
     "The attachment URL containment node should be preceded by " +
       "two linebreaks"
   );
   close_window(cw);
 }
 
 /**
  * Tests for inserting Filelinks into a reply, when we're configured to
  * reply above the quote.
  */
-function test_adding_filelinks_to_empty_reply_above() {
+add_task(function test_adding_filelinks_to_empty_reply_above() {
   let oldReplyOnTop = Services.prefs.getIntPref(kReplyOnTopKey);
   Services.prefs.setIntPref(kReplyOnTopKey, kReplyOnTop);
 
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_reply_above,
     []
   );
   // Now with HTML mail...
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_reply_above_plaintext,
     []
   );
 
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
   Services.prefs.setIntPref(kReplyOnTopKey, oldReplyOnTop);
-}
+});
 
 /**
  * Tests for inserting Filelinks into a reply, when we're configured to
  * reply above the quote, after entering some text.
  */
-function test_adding_filelinks_to_nonempty_reply_above() {
+add_task(function test_adding_filelinks_to_nonempty_reply_above() {
   let oldReplyOnTop = Services.prefs.getIntPref(kReplyOnTopKey);
   Services.prefs.setIntPref(kReplyOnTopKey, kReplyOnTop);
 
   subtest_adding_filelinks_to_reply_above(kLines);
 
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
   subtest_adding_filelinks_to_reply_above_plaintext(kLines);
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
 
   Services.prefs.setIntPref(kReplyOnTopKey, oldReplyOnTop);
-}
+});
 
 /**
  * Subtest for test_adding_filelinks_to_reply_above for the plaintext composer.
  * Does some special casing for the weird br insertions that happens in
  * various cases.
  */
 function subtest_adding_filelinks_to_reply_above_plaintext(aText, aWithSig) {
   let cw = prepare_some_attachments_and_reply(aText, kFiles);
@@ -512,45 +515,45 @@ function subtest_adding_filelinks_to_rep
   let br;
   if (aText.length) {
     br = assert_next_nodes("br", root, 2);
   } else {
     br = assert_next_nodes("br", root, 1);
   }
 
   let div = br.nextSibling;
-  assert_equals(
+  Assert.equal(
     div.localName,
     "div",
     "The linebreak should be followed by a div"
   );
 
-  assert_true(div.classList.contains("moz-cite-prefix"));
+  Assert.ok(div.classList.contains("moz-cite-prefix"));
 
   if (aText.length) {
     br = assert_previous_nodes("br", root, 2);
   } else {
     br = assert_previous_nodes("br", root, 1);
   }
 
   if (aText.length == 0) {
     // If we didn't type anything, that br should be the first element of the
     // message body.
     let msgBody = get_compose_body(cw);
-    assert_equals(
+    Assert.equal(
       msgBody.firstChild,
       br,
       "The linebreak should have been the first element in the " +
         "message body"
     );
   } else {
     let targetText = aText[aText.length - 1];
     let textNode = br.previousSibling;
-    assert_equals(textNode.nodeType, kTextNodeType);
-    assert_equals(textNode.nodeValue, targetText);
+    Assert.equal(textNode.nodeType, kTextNodeType);
+    Assert.equal(textNode.nodeValue, targetText);
   }
 
   close_window(cw);
 }
 
 /**
  * Subtest for test_adding_filelinks_to_reply_above for the HTML composer.
  */
@@ -562,81 +565,81 @@ function subtest_adding_filelinks_to_rep
   // end of the text and the reply. Otherwise, there are two breaks.
   let br =
     aText.length > 1
       ? assert_next_nodes("br", root, 2)
       : assert_next_nodes("br", root, 1);
 
   // ... which is followed by a div with a class of "moz-cite-prefix".
   let div = br.nextSibling;
-  assert_equals(
+  Assert.equal(
     div.localName,
     "div",
     "The linebreak should be followed by a div"
   );
 
-  assert_true(div.classList.contains("moz-cite-prefix"));
+  Assert.ok(div.classList.contains("moz-cite-prefix"));
 
   close_window(cw);
 }
 
 /**
  * Tests for inserting Filelinks into a reply, when we're configured to
  * reply below the quote.
  */
-function test_adding_filelinks_to_empty_reply_below() {
+add_task(function test_adding_filelinks_to_empty_reply_below() {
   let oldReplyOnTop = Services.prefs.getIntPref(kReplyOnTopKey);
   Services.prefs.setIntPref(kReplyOnTopKey, kReplyOnBottom);
 
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_reply_below,
     []
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_plaintext_reply_below,
     []
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
 
   Services.prefs.setIntPref(kReplyOnTopKey, oldReplyOnTop);
-}
+});
 
 /**
  * Tests for inserting Filelinks into a reply, when we're configured to
  * reply below the quote, after entering some text.
  */
-function test_adding_filelinks_to_nonempty_reply_below() {
+add_task(function test_adding_filelinks_to_nonempty_reply_below() {
   let oldReplyOnTop = Services.prefs.getIntPref(kReplyOnTopKey);
   Services.prefs.setIntPref(kReplyOnTopKey, kReplyOnBottom);
 
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_reply_below,
     kLines
   );
 
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_plaintext_reply_below,
     kLines
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
 
   Services.prefs.setIntPref(kReplyOnTopKey, oldReplyOnTop);
-}
+});
 
 /**
  * Subtest for test_adding_filelinks_to_reply_below for the HTML composer.
  */
 function subtest_adding_filelinks_to_reply_below(aText, aWithSig) {
   let cw = prepare_some_attachments_and_reply(aText, kFiles);
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
   // So, we should have the root, followed by a br
   let br = root.nextSibling;
-  assert_equals(
+  Assert.equal(
     br.localName,
     "br",
     "The attachment URL containment node should be followed by a br"
   );
 
   let blockquote;
   if (aText.length) {
     // If there was any text inserted, check for 2 previous br nodes, and then
@@ -646,29 +649,29 @@ function subtest_adding_filelinks_to_rep
     blockquote = textNode.previousSibling;
   } else {
     // If no text was inserted, check for 1 previous br node, and then the
     // blockquote.
     br = assert_previous_nodes("br", root, 1);
     blockquote = br.previousSibling;
   }
 
-  assert_equals(
+  Assert.equal(
     blockquote.localName,
     "blockquote",
     "The linebreak should be preceded by a blockquote."
   );
 
   let prefix = blockquote.previousSibling;
-  assert_equals(
+  Assert.equal(
     prefix.localName,
     "div",
     "The blockquote should be preceded by the prefix div"
   );
-  assert_true(
+  Assert.ok(
     prefix.classList.contains("moz-cite-prefix"),
     "The prefix should have the moz-cite-prefix class"
   );
 
   close_window(cw);
 }
 
 /**
@@ -694,118 +697,118 @@ function subtest_adding_filelinks_to_pla
     // will be the span.
     span = br.previousSibling;
     // Sometimes we need to skip one more linebreak.
     if (span.localName != "span") {
       span = span.previousSibling;
     }
   }
 
-  assert_equals(
+  Assert.equal(
     span.localName,
     "span",
     "The linebreak should be preceded by a span."
   );
 
   let prefix = span.previousSibling;
-  assert_equals(
+  Assert.equal(
     prefix.localName,
     "div",
     "The blockquote should be preceded by the prefix div"
   );
-  assert_true(
+  Assert.ok(
     prefix.classList.contains("moz-cite-prefix"),
     "The prefix should have the moz-cite-prefix class"
   );
 
   close_window(cw);
 }
 
 /**
  * Tests Filelink insertion on an inline-forward compose window with nothing
  * typed into it.
  */
-function test_adding_filelinks_to_empty_forward() {
+add_task(function test_adding_filelinks_to_empty_forward() {
   Services.prefs.setIntPref(kReplyOnTopKey, kReplyOnTop);
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_forward,
     []
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_forward,
     []
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
-}
+});
 
 /**
  * Tests Filelink insertion on an inline-forward compose window with some
  * text typed into it.
  */
-function test_adding_filelinks_to_forward() {
+add_task(function test_adding_filelinks_to_forward() {
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_forward,
     kLines
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, false);
   try_with_and_without_signature_in_reply_or_fwd(
     subtest_adding_filelinks_to_forward,
     kLines
   );
   Services.prefs.setBoolPref(kHtmlPrefKey, true);
-}
+});
 
 /**
  * Subtest for both test_adding_filelinks_to_empty_forward and
  * test_adding_filelinks_to_forward - ensures that the inserted Filelinks
  * are positioned correctly.
  */
 function subtest_adding_filelinks_to_forward(aText, aWithSig) {
   let cw = prepare_some_attachments_and_forward(aText, kFiles);
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
 
   let br = assert_next_nodes("br", root, 1);
   let forwardDiv = br.nextSibling;
-  assert_equals(forwardDiv.localName, "div");
-  assert_true(forwardDiv.classList.contains("moz-forward-container"));
+  Assert.equal(forwardDiv.localName, "div");
+  Assert.ok(forwardDiv.classList.contains("moz-forward-container"));
 
   if (aText.length) {
     // If there was text typed in, it should be separated from the root by two
     // br's
     let br = assert_previous_nodes("br", root, 2);
     assert_previous_text(br.previousSibling, aText);
   } else {
     // Otherwise, there's only 1 br, and that br should be the first element
     // of the message body.
     let br = assert_previous_nodes("br", root, 1);
     let mailBody = get_compose_body(cw);
-    assert_equals(br, mailBody.firstChild);
+    Assert.equal(br, mailBody.firstChild);
   }
 
   close_window(cw);
 }
 
 /**
  * Test that if we convert a Filelink from one provider to another, that the
  * old Filelink is removed, and a new Filelink is added for the new provider.
  * We test this on both HTML and plaintext mail.
  */
-function test_converting_filelink_updates_urls() {
+add_task(function test_converting_filelink_updates_urls() {
   try_with_plaintext_and_html_mail(subtest_converting_filelink_updates_urls);
-}
+});
 
 /**
  * Subtest for test_converting_filelink_updates_urls that creates two
  * storage provider accounts, uploads files to one, converts them to the
  * other, and ensures that the attachment links in the message body get
  * get updated.
  */
 function subtest_converting_filelink_updates_urls() {
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let providerA = new MockCloudfileAccount();
   let providerB = new MockCloudfileAccount();
   providerA.init("providerA");
   providerB.init("providerB");
 
   let cw = open_compose_new_mail();
   add_cloud_attachments(cw, providerA);
 
@@ -815,58 +818,54 @@ function subtest_converting_filelink_upd
   for (let i = 0; i < kFiles.length; ++i) {
     let url = urls[i];
     select_attachments(cw, i);
     cw.window.convertSelectedToCloudAttachment(providerB);
     [, , urls] = wait_for_attachment_urls(cw, kFiles.length);
 
     let newUrl = urls[i];
 
-    assert_not_equals(
-      url,
-      newUrl,
-      "The original URL should have been replaced"
-    );
+    Assert.notEqual(url, newUrl, "The original URL should have been replaced");
   }
 
   close_window(cw);
 }
 
 /**
  * Test that if we convert a Filelink to a normal attachment that the
  * Filelink is removed from the message body.
  */
-function test_converting_filelink_to_normal_removes_url() {
+add_task(function test_converting_filelink_to_normal_removes_url() {
   try_with_plaintext_and_html_mail(
     subtest_converting_filelink_to_normal_removes_url
   );
-}
+});
 
 /**
  * Subtest for test_converting_filelink_to_normal_removes_url that adds
  * some Filelinks to an email, and then converts those Filelinks back into
  * normal attachments, checking to ensure that the links are removed from
  * the body of the email.
  */
 function subtest_converting_filelink_to_normal_removes_url() {
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
 
   let cw = open_compose_new_mail();
   add_cloud_attachments(cw, provider);
 
   let [root, list] = wait_for_attachment_urls(cw, kFiles.length);
 
   for (let i = 0; i < kFiles.length; ++i) {
     select_attachments(cw, i);
     cw.window.convertSelectedToRegularAttachment();
 
     let urls = list.querySelectorAll(".cloudAttachmentItem");
-    assert_equals(urls.length, kFiles.length - (i + 1));
+    Assert.equal(urls.length, kFiles.length - (i + 1));
   }
 
   // At this point, the root should also have been removed.
   let mailBody = get_compose_body(cw);
   root = mailBody.querySelector("#cloudAttachmentListRoot");
   if (root) {
     throw new Error("Should not have found the cloudAttachmentListRoot");
   }
@@ -874,62 +873,62 @@ function subtest_converting_filelink_to_
   close_window(cw);
 }
 
 /**
  * Tests that if the user manually removes the Filelinks from the message body
  * that it doesn't break future Filelink insertions. Tests both HTML and
  * plaintext composers.
  */
-function test_filelinks_work_after_manual_removal() {
+add_task(function test_filelinks_work_after_manual_removal() {
   try_with_plaintext_and_html_mail(subtest_filelinks_work_after_manual_removal);
-}
+});
 
 /**
  * Subtest that first adds some Filelinks to the message body, removes them,
  * and then adds another Filelink ensuring that the new URL is successfully
  * inserted.
  */
 function subtest_filelinks_work_after_manual_removal() {
   // Insert some Filelinks...
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
   let cw = open_compose_new_mail();
   add_cloud_attachments(cw, provider);
 
   let [root] = wait_for_attachment_urls(cw, kFiles.length);
 
   // Now remove the root node from the document body
   root.remove();
 
-  gMockFilePicker.returnFiles = collectFiles(["./data/testFile3"], __file__);
+  gMockFilePicker.returnFiles = collectFiles(["./data/testFile3"]);
   add_cloud_attachments(cw, provider);
   [root] = wait_for_attachment_urls(cw, 1);
 
   close_window(cw);
 }
 
 /**
  * Test that if the users selection caret is on a newline when the URL
  * insertion occurs, that the caret does not move when the insertion is
  * complete. Tests both HTML and plaintext composers.
  */
-function test_insertion_restores_caret_point() {
+add_task(function test_insertion_restores_caret_point() {
   try_with_plaintext_and_html_mail(subtest_insertion_restores_caret_point);
-}
+});
 
 /**
  * Subtest that types some things into the composer, finishes on two
  * linebreaks, inserts some Filelink URLs, and then types some more,
  * ensuring that the selection is where we expect it to be.
  */
 function subtest_insertion_restores_caret_point() {
   // Insert some Filelinks...
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
 
   let cw = open_compose_new_mail();
 
   // Put the selection at the beginning of the document...
   let editor = cw.window.GetCurrentEditor();
   editor.beginningOfDocument();
copy from mail/test/mozmill/cloudfile/test-cloudfile-manager.js
copy to mail/test/browser/cloudfile/browser_manager.js
--- a/mail/test/mozmill/cloudfile/test-cloudfile-manager.js
+++ b/mail/test/browser/cloudfile/browser_manager.js
@@ -4,56 +4,74 @@
 
 /**
  * Tests the richlistbox in the manager for attachment storage
  * services
  */
 
 "use strict";
 
+var elementslib = ChromeUtils.import(
+  "resource://testing-common/mozmill/elementslib.jsm"
+);
+var mozmill = ChromeUtils.import(
+  "resource://testing-common/mozmill/mozmill.jsm"
+);
+
 var { gMockCloudfileManager } = ChromeUtils.import(
   "resource://testing-common/mozmill/CloudfileHelpers.jsm"
 );
-var { content_tab_e, gMockExtProtSvc, gMockExtProtSvcReg } = ChromeUtils.import(
+var {
+  content_tab_e,
+  content_tab_eid,
+  gMockExtProtSvc,
+  gMockExtProtSvcReg,
+} = ChromeUtils.import(
   "resource://testing-common/mozmill/ContentTabHelpers.jsm"
 );
-var { assert_equals, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { close_pref_tab, open_pref_tab } = ChromeUtils.import(
   "resource://testing-common/mozmill/PrefTabHelpers.jsm"
 );
 var { wait_for_frame_load } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+var controller = mozmill.getMail3PaneController();
 var kTestAccountType = "mock";
-var kRootURL = collector.addHttpResource("../cloudfile/html", "");
-var kSettingsWithLink = kRootURL + "settings-with-link.xhtml";
+var kSettingsWithLink =
+  "chrome://mochitests/content/browser/comm/mail/test/browser/cloudfile/html/settings-with-link.xhtml";
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   gMockCloudfileManager.register(kTestAccountType, {
     managementURL: kSettingsWithLink,
   });
 
   // Let's set up a few dummy accounts;
   create_dummy_account("someKey1", kTestAccountType, "carl's Account");
   create_dummy_account("someKey2", kTestAccountType, "Amber's Account");
   create_dummy_account("someKey3", kTestAccountType, "alice's Account");
   create_dummy_account("someKey4", kTestAccountType, "Bob's Account");
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   Services.prefs
     .QueryInterface(Ci.nsIPrefBranch)
     .deleteBranch("mail.cloud_files.accounts");
   gMockCloudfileManager.unregister(kTestAccountType);
-}
+
+  let tabmail = document.getElementById("tabmail");
+  if (tabmail.tabModes.preferencesTab.tabs.length == 1) {
+    tabmail.closeTab(tabmail.tabModes.preferencesTab.tabs[0]);
+  }
+});
 
 function create_dummy_account(aKey, aType, aDisplayName) {
   Services.prefs.setCharPref(
     "mail.cloud_files.accounts." + aKey + ".type",
     aType
   );
 
   Services.prefs.setCharPref(
@@ -66,54 +84,60 @@ function destroy_account(aKey) {
   Services.prefs.clearUserPref("mail.cloud_files.accounts." + aKey);
 }
 
 /**
  * Tests that we load the accounts and display them in the
  * account richlistbox in the correct order (by displayName,
  * case-insensitive)
  */
-function test_load_accounts_and_properly_order() {
-  let prefTab = open_pref_tab("paneCompose");
+add_task(function test_load_accounts_and_properly_order() {
+  let prefTab = open_pref_tab("paneCompose", "compositionAttachmentsCategory");
+  mc.sleep();
 
   let richList = content_tab_e(prefTab, "cloudFileView");
-  assert_equals(4, richList.itemCount, "Should be displaying 4 accounts");
+  Assert.equal(4, richList.itemCount, "Should be displaying 4 accounts");
 
   // Since we're sorting alphabetically by the displayName,
   // case-insensitive, the items should be ordered with the
   // following accountKeys:
   //
   // someKey3, someKey2, someKey4, someKey1
   const kExpected = ["someKey3", "someKey2", "someKey4", "someKey1"];
 
   for (let [index, expectedKey] of kExpected.entries()) {
     let item = richList.getItemAtIndex(index);
-    assert_equals(expectedKey, item.value, "The account list is out of order");
+    Assert.equal(expectedKey, item.value, "The account list is out of order");
   }
 
   close_pref_tab(prefTab);
-}
+});
 
 /**
  * Tests that a link in the management pane is loaded in
  * a browser and not in the management pane.
  */
-test_external_link.__force_skip__ = true;
-function test_external_link() {
+add_task(function test_external_link() {
   gMockExtProtSvcReg.register();
 
-  let prefTab = open_pref_tab("paneCompose");
-  content_tab_e(prefTab, "cloudFileView").selectedIndex = 0;
+  let prefTab = open_pref_tab("paneCompose", "compositionAttachmentsCategory");
+  mc.sleep();
+  mc.click(content_tab_eid(prefTab, "cloudFileView"));
+  mc.click(content_tab_eid(prefTab, "cloudFileView"), 5, 5);
 
-  let iframe = content_tab_e(prefTab, "cloudFileSettingsWrapper")
-    .firstElementChild;
+  let iframe;
+  mc.waitFor(() => {
+    iframe = content_tab_e(prefTab, "cloudFileSettingsWrapper")
+      .firstElementChild;
+    return !!iframe;
+  });
   wait_for_frame_load(iframe, kSettingsWithLink + "?accountId=someKey3");
   mc.click(new elementslib.ID(iframe.contentDocument, "a"));
 
   let targetHref = "https://www.example.com/";
   mc.waitFor(
     () => gMockExtProtSvc.urlLoaded(targetHref),
     `Timed out waiting for the link ${targetHref} to be opened in the default browser.`
   );
   close_pref_tab(prefTab);
 
   gMockExtProtSvcReg.unregister();
-}
+});
copy from mail/test/mozmill/cloudfile/test-cloudfile-notifications.js
copy to mail/test/browser/cloudfile/browser_notifications.js
--- a/mail/test/mozmill/cloudfile/test-cloudfile-notifications.js
+++ b/mail/test/browser/cloudfile/browser_notifications.js
@@ -10,75 +10,77 @@
 
 var {
   gMockFilePicker,
   gMockFilePickReg,
   select_attachments,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/AttachmentHelpers.jsm"
 );
-var {
-  collectFiles,
-  gMockCloudfileManager,
-  MockCloudfileAccount,
-} = ChromeUtils.import(
+var { gMockCloudfileManager, MockCloudfileAccount } = ChromeUtils.import(
   "resource://testing-common/mozmill/CloudfileHelpers.jsm"
 );
 var {
   add_attachments,
   add_cloud_attachments,
   close_compose_window,
   open_compose_new_mail,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
+var mozmill = ChromeUtils.import(
+  "resource://testing-common/mozmill/mozmill.jsm"
+);
 var {
   assert_notification_displayed,
   close_notification,
   wait_for_notification_to_stop,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/NotificationBoxHelpers.jsm"
 );
 var { gMockPromptService } = ChromeUtils.import(
   "resource://testing-common/mozmill/PromptHelpers.jsm"
 );
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { cloudFileAccounts } = ChromeUtils.import(
   "resource:///modules/cloudFileAccounts.jsm"
 );
 
+var controller = mozmill.getMail3PaneController();
 var maxSize, oldInsertNotificationPref;
 
 var kOfferThreshold = "mail.compose.big_attachments.threshold_kb";
 var kInsertNotificationPref =
   "mail.compose.big_attachments.insert_notification";
 
 var kBoxId = "compose-notification-bottom";
 
-function setupModule(module) {
+add_task(function setupModule(module) {
+  requestLongerTimeout(2);
+
   gMockCloudfileManager.register();
   gMockFilePickReg.register();
 
   maxSize = Services.prefs.getIntPref(kOfferThreshold, 0) * 1024;
   oldInsertNotificationPref = Services.prefs.getBoolPref(
     kInsertNotificationPref
   );
   Services.prefs.setBoolPref(kInsertNotificationPref, true);
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   gMockCloudfileManager.unregister();
   gMockFilePickReg.unregister();
   Services.prefs.setBoolPref(
     kInsertNotificationPref,
     oldInsertNotificationPref
   );
-}
+});
 
 /**
  * A helper function to assert that the Filelink offer notification is
  * either displayed or not displayed.
  *
  * @param aController the controller of the compose window to check.
  * @param aDisplayed true if the notification should be displayed, false
  *                   otherwise.
@@ -138,65 +140,65 @@ function close_upload_notification(aCont
 
 /**
  * A helper function to close the Filelink privacy warning notification.
  */
 function close_privacy_warning_notification(aController) {
   close_notification(aController, kBoxId, "bigAttachmentPrivacyWarning");
 }
 
-function test_no_notification_for_small_file() {
+add_task(function test_no_notification_for_small_file() {
   let cwc = open_compose_new_mail(mc);
   add_attachments(cwc, "http://www.example.com/1", 0);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/2", 1);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/3", 100);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/4", 500);
   assert_cloudfile_notification_displayed(cwc, false);
 
   close_compose_window(cwc);
-}
+});
 
-function test_notification_for_big_files() {
+add_task(function test_notification_for_big_files() {
   let cwc = open_compose_new_mail(mc);
   add_attachments(cwc, "http://www.example.com/1", maxSize);
   assert_cloudfile_notification_displayed(cwc, true);
 
   add_attachments(cwc, "http://www.example.com/2", maxSize + 1000);
   assert_cloudfile_notification_displayed(cwc, true);
 
   add_attachments(cwc, "http://www.example.com/3", maxSize + 10000);
   assert_cloudfile_notification_displayed(cwc, true);
 
   add_attachments(cwc, "http://www.example.com/4", maxSize + 100000);
   assert_cloudfile_notification_displayed(cwc, true);
 
   close_compose_window(cwc);
-}
+});
 
-function test_graduate_to_notification() {
+add_task(function test_graduate_to_notification() {
   let cwc = open_compose_new_mail(mc);
   add_attachments(cwc, "http://www.example.com/1", maxSize - 100);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/2", maxSize - 25);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/3", maxSize);
   assert_cloudfile_notification_displayed(cwc, true);
 
   close_compose_window(cwc);
-}
+});
 
-function test_no_notification_if_disabled() {
+add_task(function test_no_notification_if_disabled() {
   Services.prefs.setBoolPref("mail.cloud_files.enabled", false);
   let cwc = open_compose_new_mail(mc);
 
   add_attachments(cwc, "http://www.example.com/1", maxSize);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/2", maxSize + 1000);
   assert_cloudfile_notification_displayed(cwc, false);
@@ -204,85 +206,85 @@ function test_no_notification_if_disable
   add_attachments(cwc, "http://www.example.com/3", maxSize + 10000);
   assert_cloudfile_notification_displayed(cwc, false);
 
   add_attachments(cwc, "http://www.example.com/4", maxSize + 100000);
   assert_cloudfile_notification_displayed(cwc, false);
 
   close_compose_window(cwc);
   Services.prefs.setBoolPref("mail.cloud_files.enabled", true);
-}
+});
 
 /**
  * Tests that if we upload a single file, we get the link insertion
  * notification bar displayed (unless preffed off).
  */
-function test_link_insertion_notification_single() {
-  gMockFilePicker.returnFiles = collectFiles(["./data/testFile1"], __file__);
+add_task(function test_link_insertion_notification_single() {
+  gMockFilePicker.returnFiles = collectFiles(["./data/testFile1"]);
   let provider = new MockCloudfileAccount();
   provider.init("aKey");
 
   let cwc = open_compose_new_mail(mc);
   add_cloud_attachments(cwc, provider);
 
   assert_upload_notification_displayed(cwc, true);
   close_upload_notification(cwc);
 
   Services.prefs.setBoolPref(kInsertNotificationPref, false);
-  gMockFilePicker.returnFiles = collectFiles(["./data/testFile2"], __file__);
+  gMockFilePicker.returnFiles = collectFiles(["./data/testFile2"]);
   add_cloud_attachments(cwc, provider);
 
   assert_upload_notification_displayed(cwc, false);
   Services.prefs.setBoolPref(kInsertNotificationPref, true);
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Tests that if we upload multiple files, we get the link insertion
  * notification bar displayed (unless preffed off).
  */
-function test_link_insertion_notification_multiple() {
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile1", "./data/testFile2"],
-    __file__
-  );
+add_task(function test_link_insertion_notification_multiple() {
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile1",
+    "./data/testFile2",
+  ]);
   let provider = new MockCloudfileAccount();
   provider.init("aKey");
 
   let cwc = open_compose_new_mail(mc);
   add_cloud_attachments(cwc, provider);
 
   assert_upload_notification_displayed(cwc, true);
   close_upload_notification(cwc);
 
   Services.prefs.setBoolPref(kInsertNotificationPref, false);
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile3", "./data/testFile4"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile3",
+    "./data/testFile4",
+  ]);
   add_cloud_attachments(cwc, provider);
 
   assert_upload_notification_displayed(cwc, false);
   Services.prefs.setBoolPref(kInsertNotificationPref, true);
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Tests that the link insertion notification bar goes away even
  * if we hit an uploading error.
  */
-function test_link_insertion_goes_away_on_error() {
+add_task(function test_link_insertion_goes_away_on_error() {
   gMockPromptService.register();
   gMockPromptService.returnValue = false;
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile1", "./data/testFile2"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile1",
+    "./data/testFile2",
+  ]);
   let provider = new MockCloudfileAccount();
   provider.init("aKey");
 
   provider.uploadFile = function(aFile) {
     return new Promise((resolve, reject) => {
       cwc.window.setTimeout(() =>
         reject(cloudFileAccounts.constants.uploadErr)
       );
@@ -292,29 +294,29 @@ function test_link_insertion_goes_away_o
   let cwc = open_compose_new_mail(mc);
   add_cloud_attachments(cwc, provider, false);
 
   assert_upload_notification_displayed(cwc, true);
   wait_for_notification_to_stop(cwc, kBoxId, "bigAttachmentUploading");
 
   close_compose_window(cwc);
   gMockPromptService.unregister();
-}
+});
 
 /**
  * Test that we do not show the Filelink offer notification if we convert
  * a Filelink back into a normal attachment.
  */
-function test_no_offer_on_conversion() {
+add_task(function test_no_offer_on_conversion() {
   const kFiles = ["./data/testFile1", "./data/testFile2"];
   // Set the notification threshold to 0 to ensure that we get it.
   Services.prefs.setIntPref(kOfferThreshold, 0);
 
   // Insert some Filelinks...
-  gMockFilePicker.returnFiles = collectFiles(kFiles, __file__);
+  gMockFilePicker.returnFiles = collectFiles(kFiles);
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
 
   // Override uploadFile to succeed instantaneously so that we don't have
   // to worry about waiting for the onStopRequest method being called
   // asynchronously.
   provider.uploadFile = function(aFile) {
     return Promise.resolve({
@@ -331,31 +333,31 @@ function test_no_offer_on_conversion() {
   cw.window.convertSelectedToRegularAttachment();
 
   assert_cloudfile_notification_displayed(cw, false);
 
   close_compose_window(cw);
 
   // Now put the old threshold back.
   Services.prefs.setIntPref(kOfferThreshold, maxSize);
-}
+});
 
 /**
  * Test that when we kick off an upload via the offer notification, then
  * the upload notification is shown.
  */
-function test_offer_then_upload_notifications() {
+add_task(function test_offer_then_upload_notifications() {
   const kFiles = ["./data/testFile1", "./data/testFile2"];
   // Set the notification threshold to 0 to ensure that we get it.
   Services.prefs.setIntPref(kOfferThreshold, 0);
 
   // We're going to add attachments to the attachmentbucket, and we'll
   // use the add_attachments helper function to do it.  First, retrieve
   // some file URIs...
-  let fileURIs = collectFiles(kFiles, __file__).map(
+  let fileURIs = collectFiles(kFiles).map(
     file => Services.io.newFileURI(file).spec
   );
 
   // Create our mock provider
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
 
   // Override uploadFile to succeed instantaneously so that we don't have
@@ -384,29 +386,29 @@ function test_offer_then_upload_notifica
   assert_cloudfile_notification_displayed(cw, false);
   // And the upload notification should be displayed.
   assert_upload_notification_displayed(cw, true);
 
   close_compose_window(cw);
 
   // Now put the old threshold back.
   Services.prefs.setIntPref(kOfferThreshold, maxSize);
-}
+});
 
 /**
  * Test that when we first upload some files, we get the privacy warning
  * message. We should only get this the first time.
  */
-function test_privacy_warning_notification() {
+add_task(function test_privacy_warning_notification() {
   gMockPromptService.register();
   gMockPromptService.returnValue = false;
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile1", "./data/testFile2"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile1",
+    "./data/testFile2",
+  ]);
   let provider = new MockCloudfileAccount();
   provider.init("aKey");
 
   provider.uploadFile = function(aFile, aListener) {
     return new Promise(resolve =>
       cwc.window.setTimeout(() => {
         resolve({
           id: 1,
@@ -422,38 +424,38 @@ function test_privacy_warning_notificati
 
   // Assert that the warning is displayed.
   assert_privacy_warning_notification_displayed(cwc, true);
 
   // Close the privacy warning notification...
   close_privacy_warning_notification(cwc);
 
   // And now upload some more files. We shouldn't get the warning again.
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile3", "./data/testFile4"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile3",
+    "./data/testFile4",
+  ]);
   add_cloud_attachments(cwc, provider, false);
   assert_privacy_warning_notification_displayed(cwc, false);
 
   close_compose_window(cwc);
   gMockPromptService.unregister();
-}
+});
 
 /**
  * Test that the privacy warning notification does not persist when closing
  * and re-opening a compose window.
  */
-function test_privacy_warning_notification_no_persist() {
+add_task(function test_privacy_warning_notification_no_persist() {
   gMockPromptService.register();
   gMockPromptService.returnValue = false;
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile1", "./data/testFile2"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile1",
+    "./data/testFile2",
+  ]);
   let provider = new MockCloudfileAccount();
   provider.init("aKey");
 
   provider.uploadFile = function(aFile, aListener) {
     return new Promise(resolve =>
       cwc.window.setTimeout(() => {
         resolve({
           id: 1,
@@ -476,29 +478,29 @@ function test_privacy_warning_notificati
   // Open a new compose window
   cwc = open_compose_new_mail(mc);
 
   // We shouldn't be displaying the privacy warning.
   assert_privacy_warning_notification_displayed(cwc, false);
 
   close_compose_window(cwc);
   gMockPromptService.unregister();
-}
+});
 
 /**
  * Test that if we close the privacy warning in a composer, it will still
  * spawn in a new one.
  */
-function test_privacy_warning_notification_open_after_close() {
+add_task(function test_privacy_warning_notification_open_after_close() {
   gMockPromptService.register();
   gMockPromptService.returnValue = false;
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile1", "./data/testFile2"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile1",
+    "./data/testFile2",
+  ]);
   let provider = new MockCloudfileAccount();
   provider.init("aKey");
 
   provider.uploadFile = function(aFile, aListener) {
     return new Promise(resolve =>
       cwc.window.setTimeout(() => {
         resolve({
           id: 1,
@@ -518,23 +520,30 @@ function test_privacy_warning_notificati
   // Close the privacy warning notification...
   close_privacy_warning_notification(cwc);
 
   close_compose_window(cwc);
 
   // Open a new compose window
   cwc = open_compose_new_mail(mc);
 
-  gMockFilePicker.returnFiles = collectFiles(
-    ["./data/testFile3", "./data/testFile4"],
-    __file__
-  );
+  gMockFilePicker.returnFiles = collectFiles([
+    "./data/testFile3",
+    "./data/testFile4",
+  ]);
   add_cloud_attachments(cwc, provider);
 
   assert_upload_notification_displayed(cwc, true);
   wait_for_notification_to_stop(cwc, kBoxId, "bigAttachmentUploading");
 
   // Assert that the privacy warning notification is displayed again.
   assert_privacy_warning_notification_displayed(cwc, true);
 
   close_compose_window(cwc);
   gMockPromptService.unregister();
-}
+
+  Assert.report(
+    false,
+    undefined,
+    undefined,
+    "Test ran to completion successfully"
+  );
+});
copy from mail/test/mozmill/cloudfile/data/testFile1
copy to mail/test/browser/cloudfile/data/testFile1
copy from mail/test/mozmill/cloudfile/data/testFile2
copy to mail/test/browser/cloudfile/data/testFile2
copy from mail/test/mozmill/cloudfile/data/testFile3
copy to mail/test/browser/cloudfile/data/testFile3
copy from mail/test/mozmill/cloudfile/data/testFile4
copy to mail/test/browser/cloudfile/data/testFile4
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/cloudfile/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 collectFiles(files) {
+  return files.map(filename => new FileUtils.File(getTestFilePath(filename)));
+}
copy from mail/test/mozmill/cloudfile/html/settings-with-link.xhtml
copy to mail/test/browser/cloudfile/html/settings-with-link.xhtml
new file mode 100644
--- /dev/null
+++ b/mail/test/browser/composition/browser.ini
@@ -0,0 +1,78 @@
+[DEFAULT]
+prefs =
+  browser.tabs.remote.autostart=false
+  ldap_2.servers.osx.description=
+  ldap_2.servers.osx.dirType=-1
+  ldap_2.servers.osx.uri=
+  mail.provider.suppress_dialog_on_startup=true
+  mail.shell.checkDefaultClient=false
+  mail.spotlight.firstRunDone=true
+  mail.winsearch.firstRunDone=true
+  mailnews.start_page.override_url=about:blank
+  mailnews.start_page.url=about:blank
+  mail.account.account1.server=server1
+  mail.account.account2.identities=id1,id2
+  mail.account.account2.server=server2
+  mail.accountmanager.accounts=account1,account2
+  mail.accountmanager.defaultaccount=account2
+  mail.accountmanager.localfoldersserver=server1
+  mail.identity.id1.fullName=Tinderbox
+  mail.identity.id1.htmlSigFormat=false
+  mail.identity.id1.smtpServer=smtp1
+  mail.identity.id1.useremail=tinderbox@foo.invalid
+  mail.identity.id1.valid=true
+  mail.identity.id2.fullName=Tinderboxpushlog
+  mail.identity.id2.htmlSigFormat=true
+  mail.identity.id2.smtpServer=smtp1
+  mail.identity.id2.useremail=tinderboxpushlog@foo.invalid
+  mail.identity.id2.valid=true
+  mail.server.server1.type=none
+  mail.server.server1.userName=nobody
+  mail.server.server2.check_new_mail=false
+  mail.server.server2.directory-rel=[ProfD]Mail/tinderbox
+  mail.server.server2.download_on_biff=true
+  mail.server.server2.hostname=tinderbox123
+  mail.server.server2.login_at_startup=false
+  mail.server.server2.name=tinderbox@foo.invalid
+  mail.server.server2.type=pop3
+  mail.server.server2.userName=tinderbox
+  mail.server.server2.whiteListAbURI=
+  mail.smtp.defaultserver=smtp1
+  mail.smtpserver.smtp1.hostname=tinderbox123
+  mail.smtpserver.smtp1.username=tinderbox
+  mail.smtpservers=smtp1
+subsuite = thunderbird
+support-files = data/**
+
+[browser_addressWidgets.js]
+[browser_attachment.js]
+[browser_attachmentReminder.js]
+[browser_base64Display.js]
+[browser_blockedContent.js]
+[browser_charsetEdit.js]
+[browser_charsetUpgrade.js]
+[browser_cp932Display.js]
+[browser_draftIdentity.js]
+skip-if = os == "mac"
+reason = See bug 1413851.
+[browser_drafts.js]
+[browser_emlActions.js]
+[browser_focus.js]
+[browser_forwardHeaders.js]
+[browser_forwardRFC822Attach.js]
+[browser_forwardUTF8.js]
+[browser_forwardedContent.js]
+[browser_forwardedEmlActions.js]
+[browser_imageDisplay.js]
+[browser_imageInsertionDialog.js]
+[browser_multipartRelated.js]
+[browser_newmsgComposeIdentity.js]
+[browser_replyAddresses.js]
+[browser_replyFormatFlowed.js]
+[browser_replyMultipartCharset.js]
+[browser_replySignature.js]
+[browser_saveChangesOnQuit.js]
+[browser_sendButton.js]
+[browser_sendFormat.js]
+[browser_signatureInit.js]
+[browser_signatureUpdating.js]
copy from mail/test/mozmill/composition/test-address-widgets.js
copy to mail/test/browser/composition/browser_addressWidgets.js
--- a/mail/test/mozmill/composition/test-address-widgets.js
+++ b/mail/test/browser/composition/browser_addressWidgets.js
@@ -1,81 +1,76 @@
 /* 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 proper enabling of addressing widgets.
  */
 
+/* globals gFolderTreeView */
+
 "use strict";
 
 var { close_compose_window, open_compose_new_mail } = ChromeUtils.import(
   "resource://testing-common/mozmill/ComposeHelpers.jsm"
 );
-var {
-  assert_equals,
-  assert_false,
-  assert_not_equals,
-  assert_true,
-  be_in_folder,
-  FAKE_SERVER_HOSTNAME,
-} = ChromeUtils.import(
+var { be_in_folder, FAKE_SERVER_HOSTNAME } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
 var { fixIterator } = ChromeUtils.import(
   "resource:///modules/iteratorUtils.jsm"
 );
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var cwc = null; // compose window controller
 var accountPOP3 = null;
 var accountNNTP = null;
 var originalAccountCount;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
+  gFolderTreeView._tree.focus();
+
   // Ensure we're in the tinderbox account as that has the right identities set
   // up for this test.
   let server = MailServices.accounts.FindServer(
     "tinderbox",
     FAKE_SERVER_HOSTNAME,
     "pop3"
   );
   accountPOP3 = MailServices.accounts.FindAccountForServer(server);
 
   // There may be pre-existing accounts from other tests.
   originalAccountCount = MailServices.accounts.allServers.length;
-}
-
-function teardownModule(module) {}
+});
 
 /**
  * Check if the address type items are in the wished state.
  *
  * @param aItemsEnabled  List of item values that should be enabled (uncollapsed).
  */
 function check_address_types_state(aItemsEnabled) {
   let addr_types = cwc
     .e("addressingWidget")
     .querySelectorAll("menuitem[value]");
   for (let item of addr_types) {
-    assert_true(
+    Assert.ok(
       item.collapsed != aItemsEnabled.includes(item.getAttribute("value"))
     );
   }
 
   // Even if the currently selected type is collaped,
   // the containing menulist should never be collapsed.
   let addr_lists = cwc.e("addressingWidget").querySelectorAll("menulist");
   for (let list in addr_lists) {
-    assert_false(list.collapsed);
-    assert_false(list.disabled);
+    Assert.ok(!list.collapsed);
+    Assert.ok(!list.disabled);
   }
 }
 
 /**
  * With only a POP3 account, no News related address types should be enabled.
  */
 function check_mail_address_types() {
   check_address_types_state(["addr_to", "addr_cc", "addr_reply", "addr_bcc"]);
@@ -103,41 +98,41 @@ function add_NNTP_account() {
 
   let identity = MailServices.accounts.createIdentity();
   identity.email = "tinderbox2@example.invalid";
 
   accountNNTP = MailServices.accounts.createAccount();
   accountNNTP.incomingServer = nntpServer;
   accountNNTP.addIdentity(identity);
   // Now there should be 1 more account.
-  assert_equals(
+  Assert.equal(
     MailServices.accounts.allServers.length,
     originalAccountCount + 1
   );
 }
 
 function remove_NNTP_account() {
   // Remove our NNTP account to leave the profile clean.
   MailServices.accounts.removeAccount(accountNNTP);
   // There should be only the original accounts left.
-  assert_equals(MailServices.accounts.allServers.length, originalAccountCount);
+  Assert.equal(MailServices.accounts.allServers.length, originalAccountCount);
 }
 
 /**
  * Bug 399446 & bug 922614
  * Test that the allowed address types depend on the account type
  * we are sending from.
  */
-function test_address_types() {
+add_task(function test_address_types() {
   // Be sure there is no NNTP account yet.
   for (let account of fixIterator(
     MailServices.accounts.accounts,
     Ci.nsIMsgAccount
   )) {
-    assert_not_equals(
+    Assert.notEqual(
       account.incomingServer.type,
       "nntp",
       "There is a NNTP account existing unexpectedly"
     );
   }
 
   // Open compose window on the existing POP3 account.
   be_in_folder(accountPOP3.incomingServer.rootFolder);
@@ -186,9 +181,9 @@ function test_address_types() {
 
   remove_NNTP_account();
 
   // Now the NNTP account is lost, so we should be back to mail only addressees.
   be_in_folder(accountPOP3.incomingServer.rootFolder);
   cwc = open_compose_new_mail();
   check_mail_address_types();
   close_compose_window(cwc);
-}
+});
copy from mail/test/mozmill/composition/test-attachment.js
copy to mail/test/browser/composition/browser_attachment.js
--- a/mail/test/mozmill/composition/test-attachment.js
+++ b/mail/test/browser/composition/browser_attachment.js
@@ -4,31 +4,30 @@
 
 /**
  * Tests attachment handling functionality of the message compose window.
  */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
 var {
   add_attachments,
   close_compose_window,
   delete_attachment,
   open_compose_new_mail,
   open_compose_with_forward,
   open_compose_with_forward_as_attachments,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
   add_message_to_folder,
-  assert_equals,
   be_in_folder,
   create_folder,
   create_message,
   select_click_row,
 
   wait_for_popup_to_open,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
@@ -56,17 +55,17 @@ var rawAttachment =
 
 var b64Attachment =
   "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwS" +
   "FlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA" +
   "A5SURBVCiRY/z//z8DKYCJJNXkaGBgYGD4D8NQ5zUgiTVAxeBqSLaBkVRPM0KtIhrQ3km0jwe" +
   "SNQAAlmAY+71EgFoAAAAASUVORK5CYII=";
 var b64Size = 188;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   folder = create_folder("ComposeAttachmentA");
 
   messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger);
 
   isWindows = "@mozilla.org/windows-registry-key;1" in Cc;
 
   /* Today's gory details (thanks to Jonathan Protzenko): libmime somehow
    * counts the trailing newline for an attachment MIME part. Most of the time,
@@ -99,17 +98,17 @@ function setupModule(module) {
         },
       ],
     },
   ];
 
   for (let i = 0; i < messages.length; i++) {
     add_message_to_folder(folder, create_message(messages[i]));
   }
-}
+});
 
 /**
  * Make sure that the attachment's size is what we expect
  * @param controller the controller for the compose window
  * @param index the attachment to examine, as an index into the listbox
  * @param expectedSize the expected size of the attachment, in bytes
  */
 function check_attachment_size(controller, index, expectedSize) {
@@ -197,187 +196,186 @@ function check_total_attachment_size(con
         ") does not " +
         "match expected value (" +
         expectedFormattedSize +
         ")"
     );
   }
 }
 
-function test_file_attachment() {
+add_task(function test_file_attachment() {
   let cwc = open_compose_new_mail();
 
   let url = filePrefix + "some/file/here.txt";
   let size = 1234;
 
   add_attachments(cwc, url, size);
   check_attachment_size(cwc, 0, size);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
-function test_webpage_attachment() {
+add_task(function test_webpage_attachment() {
   let cwc = open_compose_new_mail();
 
   add_attachments(cwc, "http://www.mozilla.org/");
   check_no_attachment_size(cwc, 0);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
-function test_multiple_attachments() {
+add_task(function test_multiple_attachments() {
   let cwc = open_compose_new_mail();
 
   let files = [
     { name: "foo.txt", size: 1234 },
     { name: "bar.txt", size: 5678 },
     { name: "baz.txt", size: 9012 },
   ];
   for (let i = 0; i < files.length; i++) {
     add_attachments(cwc, filePrefix + files[i].name, files[i].size);
     check_attachment_size(cwc, i, files[i].size);
   }
 
   check_total_attachment_size(cwc, files.length);
   close_compose_window(cwc);
-}
+});
 
-function test_delete_attachments() {
+add_task(function test_delete_attachments() {
   let cwc = open_compose_new_mail();
 
   let files = [
     { name: "foo.txt", size: 1234 },
     { name: "bar.txt", size: 5678 },
     { name: "baz.txt", size: 9012 },
   ];
   for (let i = 0; i < files.length; i++) {
     add_attachments(cwc, filePrefix + files[i].name, files[i].size);
     check_attachment_size(cwc, i, files[i].size);
   }
 
   delete_attachment(cwc, 0);
   check_total_attachment_size(cwc, files.length - 1);
 
   close_compose_window(cwc);
-}
+});
 
 function subtest_rename_attachment(cwc) {
   cwc.e("loginTextbox").value = "renamed.txt";
   cwc.window.document.documentElement.getButton("accept").doCommand();
 }
 
-function test_rename_attachment() {
+add_task(function test_rename_attachment() {
   let cwc = open_compose_new_mail();
 
   let url = filePrefix + "some/file/here.txt";
   let size = 1234;
 
   add_attachments(cwc, url, size);
 
   // Now, rename the attachment.
   let bucket = cwc.e("attachmentBucket");
   let node = bucket.querySelector("richlistitem.attachmentItem");
   cwc.click(new elib.Elem(node));
   plan_for_modal_dialog("commonDialog", subtest_rename_attachment);
   cwc.window.RenameSelectedAttachment();
   wait_for_modal_dialog("commonDialog");
 
-  assert_equals(node.getAttribute("name"), "renamed.txt");
+  Assert.equal(node.getAttribute("name"), "renamed.txt");
 
   check_attachment_size(cwc, 0, size);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
 function subtest_open_attachment(cwc) {
   cwc.window.document.documentElement.getButton("cancel").doCommand();
 }
 
-function test_open_attachment() {
+add_task(function test_open_attachment() {
   let cwc = open_compose_new_mail();
 
   // set up our external file for attaching
-  let thisFilePath = os.getFileForPath(__file__);
-  let file = os.getFileForPath(os.abspath("./attachment.txt", thisFilePath));
+  let file = new FileUtils.File(getTestFilePath("data/attachment.txt"));
   let fileHandler = Services.io
     .getProtocolHandler("file")
     .QueryInterface(Ci.nsIFileProtocolHandler);
   let url = fileHandler.getURLSpecFromFile(file);
   let size = file.fileSize;
 
   add_attachments(cwc, url, size);
 
   // Now, open the attachment.
   let bucket = cwc.e("attachmentBucket");
   let node = bucket.querySelector("richlistitem.attachmentItem");
   plan_for_modal_dialog("unknownContentType", subtest_open_attachment);
   cwc.doubleClick(new elib.Elem(node));
   wait_for_modal_dialog("unknownContentType");
 
   close_compose_window(cwc);
-}
+});
 
-function test_forward_raw_attachment() {
+add_task(function test_forward_raw_attachment() {
   be_in_folder(folder);
   select_click_row(1);
 
   let cwc = open_compose_with_forward();
   check_attachment_size(cwc, 0, rawAttachment.length);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
-function test_forward_b64_attachment() {
+add_task(function test_forward_b64_attachment() {
   be_in_folder(folder);
   select_click_row(2);
 
   let cwc = open_compose_with_forward();
   check_attachment_size(cwc, 0, b64Size);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
-function test_forward_message_as_attachment() {
+add_task(function test_forward_message_as_attachment() {
   be_in_folder(folder);
   let curMessage = select_click_row(0);
 
   let cwc = open_compose_with_forward_as_attachments();
   check_attachment_size(cwc, 0, curMessage.messageSize);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
-function test_forward_message_with_attachments_as_attachment() {
+add_task(function test_forward_message_with_attachments_as_attachment() {
   be_in_folder(folder);
   let curMessage = select_click_row(1);
 
   let cwc = open_compose_with_forward_as_attachments();
   check_attachment_size(cwc, 0, curMessage.messageSize);
   check_total_attachment_size(cwc, 1);
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Check that the compose window has the attachments we expect.
  *
  * @param aController  The controller for the compose window
  * @param aNames       An array of attachment names that are expected
  */
 function check_attachment_names(aController, aNames) {
   let bucket = aController.e("attachmentBucket");
-  assert_equals(aNames.length, bucket.itemCount);
+  Assert.equal(aNames.length, bucket.itemCount);
   for (let i = 0; i < aNames.length; i++) {
-    assert_equals(bucket.getItemAtIndex(i).getAttribute("name"), aNames[i]);
+    Assert.equal(bucket.getItemAtIndex(i).getAttribute("name"), aNames[i]);
   }
 }
 
 /**
  * Execute a test of opening and closing reorderAttachmentsPanel via keyboard.
  *
  * @param aCwc        The controller for the compose window
  * @param aActions    An array of objects specifying an action of opening the
@@ -437,17 +435,17 @@ function subtest_reordering(
   let panel;
 
   // Create a set of attachments for the test.
   const size = 1234;
   for (let name of aInitialAttachmentNames) {
     add_attachments(aCwc, filePrefix + name, size);
   }
   aCwc.sleep(0);
-  assert_equals(aCwc.window.attachmentsCount(), aInitialAttachmentNames.length);
+  Assert.equal(aCwc.window.attachmentsCount(), aInitialAttachmentNames.length);
   check_attachment_names(aCwc, aInitialAttachmentNames);
 
   if (aOpenPanel) {
     // Bring up the reordering panel.
     aCwc.window.showReorderAttachmentsPanel();
     aCwc.sleep(0);
     panel = aCwc.e("reorderAttachmentsPanel");
     wait_for_popup_to_open(panel);
@@ -483,17 +481,17 @@ function subtest_reordering(
   aCwc.window.RemoveAllAttachments();
 }
 
 /**
  * Bug 663695, Bug 1417856, Bug 1426344, Bug 1425891, Bug 1427037.
  * Check basic and advanced attachment reordering operations.
  * This is the main function of this test.
  */
-function test_attachment_reordering() {
+add_task(function test_attachment_reordering() {
   let cwc = open_compose_new_mail();
   let editorEl = cwc.window.GetCurrentEditorElement();
   let bucket = cwc.e("attachmentBucket");
   let panel = cwc.e("reorderAttachmentsPanel");
   // const openReorderPanelModifiers =
   //   (AppConstants.platform == "macosx") ? { controlKey: true }
   //                                       : { altKey: true };
 
@@ -502,17 +500,17 @@ function test_attachment_reordering() {
 
   // Create two attachments as otherwise the reordering panel won't open.
   const size = 1234;
   const initialAttachmentNames_0 = ["A1", "A2"];
   for (let name of initialAttachmentNames_0) {
     add_attachments(cwc, filePrefix + name, size);
     cwc.sleep(0);
   }
-  assert_equals(cwc.window.attachmentsCount(), initialAttachmentNames_0.length);
+  Assert.equal(cwc.window.attachmentsCount(), initialAttachmentNames_0.length);
   check_attachment_names(cwc, initialAttachmentNames_0);
 
   // Show 'Reorder Attachments' panel via mouse clicks.
   cwc.rightClick(new elib.Elem(bucket.getItemAtIndex(1)));
   cwc.click_menus_in_sequence(cwc.e("msgComposeAttachmentItemContext"), [
     { id: "composeAttachmentContext_reorderItem" },
   ]);
   wait_for_popup_to_open(panel);
@@ -966,12 +964,12 @@ function test_attachment_reordering() {
   // Check 4 (Alt+Y keyboard shortcut for sorting) without panel.
   subtest_reordering(cwc, initialAttachmentNames_4, reorderActions_4, false);
   // Check 4 (Alt+Y keyboard shortcut for sorting) with panel open.
   subtest_reordering(cwc, initialAttachmentNames_4, reorderActions_4);
   // XXX When the root problem of bug 1425891 has been found and fixed, we should
   // test here if the panel stays open as it should, esp. on Windows.
 
   close_compose_window(cwc);
-}
+});
 
 // XXX: Test attached emails dragged onto composer and files pulled from other
 // emails (this probably requires better drag-and-drop support from Mozmill)
copy from mail/test/mozmill/composition/test-attachment-reminder.js
copy to mail/test/browser/composition/browser_attachmentReminder.js
--- a/mail/test/mozmill/composition/test-attachment-reminder.js
+++ b/mail/test/browser/composition/browser_attachmentReminder.js
@@ -3,26 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Tests that the attachment reminder works properly.
  */
 
 "use strict";
 
+var elementslib = ChromeUtils.import(
+  "resource://testing-common/mozmill/elementslib.jsm"
+);
+
 var {
   add_attachments,
   close_compose_window,
   open_compose_new_mail,
   setup_msg_contents,
   wait_for_compose_window,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
-  assert_equals,
-  assert_true,
   be_in_folder,
   get_special_folder,
   mc,
   press_delete,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
@@ -54,22 +56,24 @@ var { MailServices } = ChromeUtils.impor
 );
 
 var kBoxId = "compose-notification-bottom";
 var kNotificationId = "attachmentReminder";
 var kReminderPref = "mail.compose.attachment_reminder";
 var gDrafts;
 var gOutbox;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
+  requestLongerTimeout(4);
+
   gDrafts = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
   gOutbox = get_special_folder(Ci.nsMsgFolderFlags.Queue);
 
-  assert_true(Services.prefs.getBoolPref(kReminderPref));
-}
+  Assert.ok(Services.prefs.getBoolPref(kReminderPref));
+});
 
 /**
  * Check if the attachment reminder bar is in the wished state.
  *
  * @param aCwc    A compose window controller.
  * @param aShown  True for expecting the bar to be shown, false otherwise.
  *
  * @return        If the bar is shown, return the notification object.
@@ -110,23 +114,23 @@ function wait_for_reminder_state(aCwc, a
 /**
  * Check whether the manual reminder is in the proper state.
  *
  * @param aCwc      A compose window controller.
  * @param aChecked  Whether the reminder should be enabled.
  */
 function assert_manual_reminder_state(aCwc, aChecked) {
   const remindCommand = "cmd_remindLater";
-  assert_equals(
+  Assert.equal(
     aCwc.e("button-attachPopup_remindLaterItem").getAttribute("command"),
     remindCommand
   );
 
   let checkedValue = aChecked ? "true" : "false";
-  assert_equals(aCwc.e(remindCommand).getAttribute("checked"), checkedValue);
+  Assert.equal(aCwc.e(remindCommand).getAttribute("checked"), checkedValue);
 }
 
 /**
  * Returns the keywords string currently shown in the notification message.
  *
  * @param aCwc A compose window controller.
  */
 function get_reminder_keywords(aCwc) {
@@ -137,17 +141,17 @@ function get_reminder_keywords(aCwc) {
   return notification
     .querySelector("#attachmentKeywords")
     .getAttribute("value");
 }
 
 /**
  * Test that the attachment reminder works, in general.
  */
-function test_attachment_reminder_appears_properly() {
+add_task(function test_attachment_reminder_appears_properly() {
   let cwc = open_compose_new_mail();
 
   // There should be no notification yet.
   assert_automatic_reminder_state(cwc, false);
 
   setup_msg_contents(
     cwc,
     "test@example.org",
@@ -181,23 +185,23 @@ function test_attachment_reminder_appear
   plan_for_modal_dialog("commonDialog", click_oh_i_did);
   cwc.click(cwc.eid("button-send"));
   wait_for_modal_dialog("commonDialog");
 
   // After confirming the reminder the menuitem should get disabled.
   assert_manual_reminder_state(cwc, false);
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Test that the alert appears normally, but not after closing the
  * notification.
  */
-function test_attachment_reminder_dismissal() {
+add_task(function test_attachment_reminder_dismissal() {
   let cwc = open_compose_new_mail();
 
   // There should be no notification yet.
   assert_automatic_reminder_state(cwc, false);
 
   setup_msg_contents(
     cwc,
     "test@example.org",
@@ -205,39 +209,39 @@ function test_attachment_reminder_dismis
     "Hi there, remember the attachment! " +
       "Yes, there is a file test.doc attached! " +
       "Do check it, test.doc is a nice attachment."
   );
 
   // Give the notification time to appear.
   wait_for_reminder_state(cwc, true);
 
-  assert_equals(get_reminder_keywords(cwc), "test.doc, attachment, attached");
+  Assert.equal(get_reminder_keywords(cwc), "test.doc, attachment, attached");
 
   // We didn't click the "Remind Me Later" - the alert should pop up
   // on send anyway.
   plan_for_modal_dialog("commonDialog", click_oh_i_did);
   cwc.click(cwc.eid("button-send"));
   wait_for_modal_dialog("commonDialog");
 
   let notification = assert_automatic_reminder_state(cwc, true);
 
   notification.close();
   assert_automatic_reminder_state(cwc, false);
 
   click_send_and_handle_send_error(cwc);
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Bug 938829
  * Check that adding an attachment actually hides the notification.
  */
-function test_attachment_reminder_with_attachment() {
+add_task(function test_attachment_reminder_with_attachment() {
   let cwc = open_compose_new_mail();
 
   // There should be no notification yet.
   assert_automatic_reminder_state(cwc, false);
 
   setup_msg_contents(
     cwc,
     "test@example.org",
@@ -246,17 +250,17 @@ function test_attachment_reminder_with_a
   );
 
   // Give the notification time to appear. It should.
   wait_for_reminder_state(cwc, true);
 
   // Add an attachment.
   let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
   file.append("panacea.dat");
-  assert_true(
+  Assert.ok(
     file.exists(),
     "The required file panacea.dat was not found in the profile."
   );
   let attachment = [cwc.window.FileToAttachment(file)];
   cwc.window.AddAttachments(attachment);
 
   // The notification should hide.
   wait_for_reminder_state(cwc, false);
@@ -267,25 +271,25 @@ function test_attachment_reminder_with_a
   // Give the notification time to appear. It shouldn't.
   wait_for_reminder_state(cwc, false);
 
   cwc.window.RemoveAllAttachments();
 
   // After removing the attachment, notification should come back
   // with all the keywords, even those input while having an attachment.
   wait_for_reminder_state(cwc, true);
-  assert_equals(get_reminder_keywords(cwc), "attachment, attached");
+  Assert.equal(get_reminder_keywords(cwc), "attachment, attached");
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Test that the mail.compose.attachment_reminder_aggressive pref works.
  */
-function test_attachment_reminder_aggressive_pref() {
+add_task(function test_attachment_reminder_aggressive_pref() {
   const kPref = "mail.compose.attachment_reminder_aggressive";
   Services.prefs.setBoolPref(kPref, false);
 
   let cwc = open_compose_new_mail();
 
   // There should be no notification yet.
   assert_automatic_reminder_state(cwc, false);
 
@@ -300,23 +304,23 @@ function test_attachment_reminder_aggres
   click_send_and_handle_send_error(cwc);
 
   close_compose_window(cwc);
 
   // Now reset the pref back to original value.
   if (Services.prefs.prefHasUserValue(kPref)) {
     Services.prefs.clearUserPref(kPref);
   }
-}
+});
 
 /**
  * Test that clicking "No, Send Now" in the attachment reminder alert
  * works.
  */
-function test_no_send_now_sends() {
+add_task(function test_no_send_now_sends() {
   let cwc = open_compose_new_mail();
 
   setup_msg_contents(
     cwc,
     "test@example.org",
     "will the 'No, Send Now' button work?",
     "Hello, I got your attachment!"
   );
@@ -328,17 +332,17 @@ function test_no_send_now_sends() {
   cwc.click(cwc.eid("button-send"));
   wait_for_modal_dialog("commonDialog");
 
   // After clicking "Send Now" sending is proceeding, just handle the error.
   click_send_and_handle_send_error(cwc, true);
 
   // We're now back in the compose window, let's close it then.
   close_compose_window(cwc);
-}
+});
 
 /**
  * Click the manual reminder in the menu.
  *
  * @param aCwc            A compose window controller.
  * @param aExpectedState  A boolean specifying what is the expected state
  *                        of the reminder menuitem after the click.
  */
@@ -357,17 +361,17 @@ function click_manual_reminder(aCwc, aEx
   wait_for_window_focused(aCwc.window);
   assert_manual_reminder_state(aCwc, aExpectedState);
 }
 
 /**
  * Bug 521128
  * Test proper behaviour of the manual reminder.
  */
-function test_manual_attachment_reminder() {
+add_task(function test_manual_attachment_reminder() {
   // Open a sample message with no attachment keywords.
   let cwc = open_compose_new_mail();
   setup_msg_contents(
     cwc,
     "test@example.invalid",
     "Testing manual reminder!",
     "Some body..."
   );
@@ -425,24 +429,23 @@ function test_manual_attachment_reminder
 
   // Now try to send again, there should be no more alert.
   click_send_and_handle_send_error(cwc);
 
   close_compose_window(cwc);
 
   // Delete the leftover draft message.
   press_delete();
-}
-test_manual_attachment_reminder.EXCLUDED_PLATFORMS = ["winnt", "linux"]; // See bug 1535292.
+}).__skipMe = AppConstants.platform == "linux"; // See bug 1535292.
 
 /**
  * Bug 938759
  * Test hiding of the automatic notification if the manual reminder is set.
  */
-function test_manual_automatic_attachment_reminder_interaction() {
+add_task(function test_manual_automatic_attachment_reminder_interaction() {
   // Open a blank message compose
   let cwc = open_compose_new_mail();
   // This one should have the reminder disabled.
   assert_manual_reminder_state(cwc, false);
   // There should be no attachment notification.
   assert_automatic_reminder_state(cwc, false);
 
   // Add some attachment keywords.
@@ -476,20 +479,20 @@ function test_manual_automatic_attachmen
   setup_msg_contents(cwc, "", "", " No keywords here.");
   // Give the notification time to appear. It shouldn't.
   wait_for_reminder_state(cwc, false);
 
   // Add some more text with a new keyword.
   setup_msg_contents(cwc, "", "", " Do you find it attached?");
   // Give the notification time to appear. It should now.
   wait_for_reminder_state(cwc, true);
-  assert_equals(get_reminder_keywords(cwc), "attachment, attached");
+  Assert.equal(get_reminder_keywords(cwc), "attachment, attached");
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Assert if there is any notification in the compose window.
  *
  * @param aCwc         Compose Window Controller
  * @param aValue       True if notification should exist.
  *                     False otherwise.
  */
@@ -499,17 +502,17 @@ function assert_any_notification(aCwc, a
     throw new Error("Notification in wrong state");
   }
 }
 
 /**
  * Bug 989653
  * Send filelink attachment should not trigger the attachment reminder.
  */
-function test_attachment_vs_filelink_reminder() {
+add_task(function test_attachment_vs_filelink_reminder() {
   // Open a blank message compose
   let cwc = open_compose_new_mail();
   setup_msg_contents(
     cwc,
     "test@example.invalid",
     "Testing Filelink notification",
     "There is no body. I hope you don't mind!"
   );
@@ -526,23 +529,23 @@ function test_attachment_vs_filelink_rem
 
   // The filelink attachment proposal should be up but not the attachment
   // reminder and it should also not interfere with the sending of the message.
   wait_for_notification_to_show(cwc, kBoxId, "bigAttachment");
   assert_automatic_reminder_state(cwc, false);
 
   click_send_and_handle_send_error(cwc);
   close_window(cwc);
-}
+});
 
 /**
  * Bug 944643
  * Test the attachment reminder coming up when keyword is in subject line.
  */
-function test_attachment_reminder_in_subject() {
+add_task(function test_attachment_reminder_in_subject() {
   // Open a blank message compose
   let cwc = open_compose_new_mail();
   // This one should have the reminder disabled.
   assert_manual_reminder_state(cwc, false);
   // There should be no attachment notification.
   assert_automatic_reminder_state(cwc, false);
 
   // Add some attachment keyword in subject.
@@ -550,33 +553,33 @@ function test_attachment_reminder_in_sub
     cwc,
     "test@example.invalid",
     "Testing attachment reminder!",
     "There is no keyword in this body..."
   );
 
   // The automatic attachment notification should pop up.
   wait_for_reminder_state(cwc, true);
-  assert_equals(get_reminder_keywords(cwc), "attachment");
+  Assert.equal(get_reminder_keywords(cwc), "attachment");
 
   // Now clear the subject
   delete_all_existing(cwc, cwc.eid("msgSubject"));
 
   // Give the notification time to disappear.
   wait_for_reminder_state(cwc, false);
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Bug 944643
  * Test the attachment reminder coming up when keyword is in subject line
  * and also body.
  */
-function test_attachment_reminder_in_subject_and_body() {
+add_task(function test_attachment_reminder_in_subject_and_body() {
   // Open a blank message compose
   let cwc = open_compose_new_mail();
   // This one should have the reminder disabled.
   assert_manual_reminder_state(cwc, false);
   // There should be no attachment notification.
   assert_automatic_reminder_state(cwc, false);
 
   // Add some attachment keyword in subject.
@@ -584,35 +587,35 @@ function test_attachment_reminder_in_sub
     cwc,
     "test@example.invalid",
     "Testing attachment reminder!",
     "There should be an attached file in this body..."
   );
 
   // The automatic attachment notification should pop up.
   wait_for_reminder_state(cwc, true);
-  assert_equals(get_reminder_keywords(cwc), "attachment, attached");
+  Assert.equal(get_reminder_keywords(cwc), "attachment, attached");
 
   // Now clear only the subject
   delete_all_existing(cwc, cwc.eid("msgSubject"));
 
   // Give the notification some time. It should not disappear,
   // just reduce the keywords list.
   wait_for_reminder_state(cwc, true, true);
-  assert_equals(get_reminder_keywords(cwc), "attached");
+  Assert.equal(get_reminder_keywords(cwc), "attached");
 
   close_compose_window(cwc);
-}
+});
 
 /**
  * Bug 1099866
  * Test proper behaviour of attachment reminder when keyword reminding
  * is turned off.
  */
-function test_disabled_attachment_reminder() {
+add_task(function test_disabled_attachment_reminder() {
   Services.prefs.setBoolPref(kReminderPref, false);
 
   // Open a sample message with no attachment keywords.
   let cwc = open_compose_new_mail();
   setup_msg_contents(
     cwc,
     "test@example.invalid",
     "Testing disabled keyword reminder!",
@@ -640,23 +643,23 @@ function test_disabled_attachment_remind
   assert_automatic_reminder_state(cwc, false);
 
   // There should be no attachment message upon send.
   click_send_and_handle_send_error(cwc);
 
   close_compose_window(cwc);
 
   Services.prefs.setBoolPref(kReminderPref, true);
-}
+});
 
 /**
  * Bug 833909
  * Test reminder comes up when a draft with keywords is opened.
  */
-function test_reminder_in_draft() {
+add_task(function test_reminder_in_draft() {
   // Open a sample message with no attachment keywords.
   let cwc = open_compose_new_mail();
   setup_msg_contents(
     cwc,
     "test@example.invalid",
     "Testing draft reminder!",
     "Some body..."
   );
@@ -694,23 +697,23 @@ function test_reminder_in_draft() {
 
   // Give the notification time to appear.
   wait_for_reminder_state(cwc, true);
 
   close_compose_window(cwc);
 
   // Delete the leftover draft message.
   press_delete();
-}
+});
 
 /**
  * Bug 942436
  * Test that the reminder can be turned off for the current message.
  */
-function test_disabling_attachment_reminder() {
+add_task(function test_disabling_attachment_reminder() {
   // Open a sample message with attachment keywords.
   let cwc = open_compose_new_mail();
   setup_msg_contents(
     cwc,
     "test@example.invalid",
     "Testing turning off the reminder",
     "Some attachment keywords here..."
   );
@@ -772,17 +775,17 @@ function test_disabling_attachment_remin
 
   select_click_row(0);
   // Delete the leftover outgoing message.
   press_delete();
 
   // Get back to the mail account for other tests.
   let mail = MailServices.accounts.defaultAccount.incomingServer.rootFolder;
   be_in_folder(mail);
-}
+});
 
 /**
  * Click the send button and handle the send error dialog popping up.
  * It will return us back to the compose window.
  *
  * @param aController
  * @param aAlreadySending  Set this to true if sending was already triggered
  *                         by other means.
copy from mail/test/mozmill/composition/test-base64-display.js
copy to mail/test/browser/composition/browser_base64Display.js
--- a/mail/test/mozmill/composition/test-base64-display.js
+++ b/mail/test/browser/composition/browser_base64Display.js
@@ -3,31 +3,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Tests that messages with "broken" base64 are correctly displayed.
  */
 
 "use strict";
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
-var { assert_true, open_message_from_file } = ChromeUtils.import(
+var { open_message_from_file } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { close_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
-function test_base64_display() {
-  let file = os.getFileForPath(
-    os.abspath("./base64-with-whitespace.eml", os.getFileForPath(__file__))
+add_task(function test_base64_display() {
+  let file = new FileUtils.File(
+    getTestFilePath("data/base64-with-whitespace.eml")
   );
   let msgc = open_message_from_file(file);
   let bodyText = msgc.e("messagepane").contentDocument.querySelector("body")
     .textContent;
   close_window(msgc);
 
-  assert_true(
+  Assert.ok(
     bodyText.includes("abcdefghijklmnopqrstuvwxyz"),
     "Decoded base64 text not found in message."
   );
-}
+});
copy from mail/test/mozmill/composition/test-blocked-content.js
copy to mail/test/browser/composition/browser_blockedContent.js
--- a/mail/test/mozmill/composition/test-blocked-content.js
+++ b/mail/test/browser/composition/browser_blockedContent.js
@@ -3,26 +3,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Tests that we do the right thing wrt. blocked resources during composition.
  */
 
 "use strict";
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
 var {
   get_msg_source,
   open_compose_new_mail,
   setup_msg_contents,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
-  assert_false,
-  assert_true,
   be_in_folder,
   get_special_folder,
   press_delete,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { wait_for_notification_to_show } = ChromeUtils.import(
@@ -38,19 +36,19 @@ var { MailServices } = ChromeUtils.impor
 );
 var { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
 
 var gOutboxFolder;
 
 var kBoxId = "compose-notification-bottom";
 var kNotificationId = "blockedContent";
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   gOutboxFolder = get_special_folder(Ci.nsMsgFolderFlags.Queue);
-}
+});
 
 function putHTMLOnClipboard(html) {
   let trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
     Ci.nsITransferable
   );
 
   // Register supported data flavors
   trans.init(null);
@@ -64,44 +62,44 @@ function putHTMLOnClipboard(html) {
 
   Services.clipboard.setData(trans, null, Ci.nsIClipboard.kGlobalClipboard);
 }
 
 /**
  * Test that accessing file: URLs will block when appropriate, and load
  * the content when appropriate.
  */
-function test_paste_file_urls() {
+add_task(function test_paste_file_urls() {
   let cwc = open_compose_new_mail();
   setup_msg_contents(
     cwc,
     "someone@example.com",
     "testing html paste",
     "See these images- one broken one not\n"
   );
 
-  const fname = "./tb-logo.png";
-  let file = os.getFileForPath(os.abspath(fname, os.getFileForPath(__file__)));
+  const fname = "data/tb-logo.png";
+  let file = new FileUtils.File(getTestFilePath(fname));
   let fileHandler = Services.io
     .getProtocolHandler("file")
     .QueryInterface(Ci.nsIFileProtocolHandler);
 
   let dest = OS.Path.join(OS.Constants.Path.tmpDir, file.leafName);
   let tmpFile;
   let tmpFileURL;
   OS.File.remove(dest, { ignoreAbsent: true })
     .then(function() {
       return OS.File.copy(file.path, dest);
     })
     .then(function() {
       return OS.File.setDates(dest, null, null);
     })
     .then(function() {
       tmpFile = os.getFileForPath(dest);
-      assert_true(tmpFile.exists(), "tmpFile's not there at " + dest);
+      Assert.ok(tmpFile.exists(), "tmpFile's not there at " + dest);
 
       tmpFileURL = fileHandler.getURLSpecFromFile(tmpFile);
       putHTMLOnClipboard(
         "<img id='bad-img' src='file://foo/non-existant' alt='bad' /> and " +
           "<img id='tmp-img' src='" +
           tmpFileURL +
           "' alt='tmp' />"
       );
@@ -127,27 +125,25 @@ function test_paste_file_urls() {
   plan_for_window_close(cwc);
   cwc.window.goDoCommand("cmd_sendLater");
   wait_for_window_close();
 
   be_in_folder(gOutboxFolder);
   let outMsg = select_click_row(0);
   let outMsgContent = get_msg_source(outMsg);
 
-  assert_true(
+  Assert.ok(
     outMsgContent.includes("file://foo/non-existant"),
     "non-existant file not in content=" + outMsgContent
   );
 
-  assert_false(
-    outMsgContent.includes(tmpFileURL),
+  Assert.ok(
+    !outMsgContent.includes(tmpFileURL),
     "tmp file url still in content=" + outMsgContent
   );
 
-  assert_true(
+  Assert.ok(
     outMsgContent.includes('id="tmp-img" src="cid:'),
     "tmp-img should be cid after send; content=" + outMsgContent
   );
 
   press_delete(); // Delete the msg from Outbox.
-}
-
-function teardownModule(module) {}
+});
copy from mail/test/mozmill/composition/test-charset-edit.js
copy to mail/test/browser/composition/browser_charsetEdit.js
--- a/mail/test/mozmill/composition/test-charset-edit.js
+++ b/mail/test/browser/composition/browser_charsetEdit.js
@@ -5,29 +5,28 @@
 /**
  * Tests that we do the right thing wrt. message encoding when editing or
  * replying to messages.
  */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
-var utils = ChromeUtils.import("chrome://mozmill/content/modules/utils.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
+var utils = ChromeUtils.import("resource://testing-common/mozmill/utils.jsm");
 
 var {
   close_compose_window,
   open_compose_with_reply,
   wait_for_compose_window,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
   add_message_to_folder,
-  assert_equals,
   assert_selected_and_displayed,
   be_in_folder,
   create_message,
   get_special_folder,
   mc,
   press_delete,
   select_click_row,
   SyntheticPartLeaf,
@@ -44,31 +43,31 @@ var { plan_for_new_window } = ChromeUtil
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 var { MimeParser } = ChromeUtils.import("resource:///modules/mimeParser.jsm");
 
 var gDrafts;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   gDrafts = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
 
   // Ensure reply charset isn't UTF-8, otherwise there's no need to upgrade,
   // which is what this test tests.
   let str = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(
     Ci.nsIPrefLocalizedString
   );
   str.data = "windows-1252";
   Services.prefs.setComplexValue(
     "mailnews.send_default_charset",
     Ci.nsIPrefLocalizedString,
     str
   );
-}
+});
 
 /**
  * Helper to get the full message content.
  *
  * @param aMsgHdr: nsIMsgDBHdr object whose text body will be read
  * @param aGetText: if true, return header objects. if false, return body data.
  * @return Map(partnum -> message headers)
  */
@@ -104,85 +103,85 @@ function getMsgHeaders(aMsgHdr, aGetText
   return aGetText ? handler._text : handler._data;
 }
 
 /**
  * Test that if we reply to a message in an invalid charset, we don't try to compose
  * in that charset. Instead, we should be using the default charset (set to
  * not be UTF-8 in this test).
  */
-function test_wrong_reply_charset() {
+add_task(function test_wrong_reply_charset() {
   let folder = gDrafts;
   let msg0 = create_message({
     bodyPart: new SyntheticPartLeaf("Some text", {
       charset: "invalid-charset",
     }),
   });
   add_message_to_folder(folder, msg0);
   be_in_folder(folder);
   let msg = select_click_row(0);
   assert_selected_and_displayed(mc, msg);
-  assert_equals(getMsgHeaders(msg).get("").charset, "invalid-charset");
+  Assert.equal(getMsgHeaders(msg).get("").charset, "invalid-charset");
 
   let rwc = open_compose_with_reply();
   // Ctrl+S = save as draft.
   rwc.keypress(null, "s", { shiftKey: false, accelKey: true });
   close_compose_window(rwc);
 
   let draftMsg = select_click_row(1);
-  assert_equals(getMsgHeaders(draftMsg).get("").charset, "windows-1252");
+  Assert.equal(getMsgHeaders(draftMsg).get("").charset, "windows-1252");
   press_delete(mc); // Delete message
 
   // Edit the original message. Charset should be windows-1252 now.
   msg = select_click_row(0);
 
   // Wait for the notification with the Edit button.
   wait_for_notification_to_show(mc, "mail-notification-top", "draftMsgContent");
 
   plan_for_new_window("msgcompose");
   mc.click(
     mc.eid("mail-notification-top", { tagName: "button", label: "Edit" })
   );
   rwc = wait_for_compose_window();
   rwc.keypress(null, "s", { shiftKey: false, accelKey: true });
   close_compose_window(rwc);
   msg = select_click_row(0);
-  assert_equals(getMsgHeaders(msg).get("").charset, "windows-1252");
+  Assert.equal(getMsgHeaders(msg).get("").charset, "windows-1252");
   press_delete(mc); // Delete message
-}
+});
 
 /**
  * Test that replying to bad charsets don't screw up the existing text.
  */
-function test_no_mojibake() {
+add_task(function test_no_mojibake() {
   let folder = gDrafts;
   let nonASCII = "ケツァルコアトル";
   let UTF7 = "+MLEwxDChMOswszCiMMgw6w-";
   let msg0 = create_message({
     bodyPart: new SyntheticPartLeaf(UTF7, { charset: "utf-7" }),
   });
   add_message_to_folder(folder, msg0);
   be_in_folder(folder);
   let msg = select_click_row(0);
   assert_selected_and_displayed(mc, msg);
-  assert_equals(getMsgHeaders(msg).get("").charset, "utf-7");
-  assert_equals(
+  Assert.equal(getMsgHeaders(msg).get("").charset, "utf-7");
+  Assert.equal(
     getMsgHeaders(msg, true)
       .get("")
       .trim(),
     nonASCII
   );
 
   let rwc = open_compose_with_reply();
   // Ctrl+S = save as draft.
   rwc.keypress(null, "s", { shiftKey: false, accelKey: true });
   close_compose_window(rwc);
 
   let draftMsg = select_click_row(1);
-  assert_equals(
+  Assert.equal(
     getMsgHeaders(draftMsg)
       .get("")
       .charset.toUpperCase(),
     "UTF-8"
   );
   let text = getMsgHeaders(draftMsg, true).get("");
   // Delete message first before throwing so subsequent tests are not affected.
   press_delete(mc);
@@ -199,26 +198,26 @@ function test_no_mojibake() {
   plan_for_new_window("msgcompose");
   mc.click(
     mc.eid("mail-notification-top", { tagName: "button", label: "Edit" })
   );
   rwc = wait_for_compose_window();
   rwc.keypress(null, "s", { shiftKey: false, accelKey: true });
   close_compose_window(rwc);
   msg = select_click_row(0);
-  assert_equals(
+  Assert.equal(
     getMsgHeaders(msg)
       .get("")
       .charset.toUpperCase(),
     "UTF-8"
   );
-  assert_equals(
+  Assert.equal(
     getMsgHeaders(msg, true)
       .get("")
       .trim(),
     nonASCII
   );
   press_delete(mc); // Delete message
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   Services.prefs.clearUserPref("mailnews.send_default_charset");
-}
+});
copy from mail/test/mozmill/composition/test-charset-upgrade.js
copy to mail/test/browser/composition/browser_charsetUpgrade.js
--- a/mail/test/mozmill/composition/test-charset-upgrade.js
+++ b/mail/test/browser/composition/browser_charsetUpgrade.js
@@ -11,18 +11,16 @@
 
 var {
   get_msg_source,
   open_compose_new_mail,
   setup_msg_contents,
   type_in_composer,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
-  assert_equals,
-  assert_true,
   be_in_folder,
   get_special_folder,
   press_delete,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { plan_for_window_close, wait_for_window_close } = ChromeUtils.import(
@@ -32,17 +30,17 @@ var { plan_for_window_close, wait_for_wi
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var gDrafts;
 var gOutbox;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   gDrafts = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
   gOutbox = get_special_folder(Ci.nsMsgFolderFlags.Queue);
 
   // Ensure reply charset isn't UTF-8, otherwise there's no need to upgrade,
   //  which is what this test tests.
   let str = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(
     Ci.nsIPrefLocalizedString
   );
@@ -53,23 +51,23 @@ function setupModule(module) {
     str
   );
 
   // Don't create paragraphs in the test.
   // When creating a paragraph, the test fails to retrieve the
   // original character set windows-1252. Until we understand why,
   // we run without paragraphs.
   Services.prefs.setBoolPref("mail.compose.default_to_paragraph", false);
-}
+});
 
 /**
  * Test that if all characters don't fit the current charset selection,
  * we upgrade properly to UTF-8. In HTML composition.
  */
-function test_encoding_upgrade_html_compose() {
+add_task(function test_encoding_upgrade_html_compose() {
   Services.prefs.setBoolPref("mail.identity.default.compose_html", true);
   let compWin = open_compose_new_mail();
 
   setup_msg_contents(
     compWin,
     "someone@example.com",
     "encoding upgrade test - html mode",
     "so far, this is latin1\n"
@@ -77,17 +75,17 @@ function test_encoding_upgrade_html_comp
 
   // Ctrl+S = save as draft.
   compWin.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   be_in_folder(gDrafts);
   let draftMsg = select_click_row(0);
 
   // Charset should still be the default.
-  assert_equals(draftMsg.Charset, "windows-1252");
+  Assert.equal(draftMsg.Charset, "windows-1252");
 
   // We could pass "windows-1252", but the message is ASCII.
   let draftMsgContent = get_msg_source(draftMsg);
   if (!draftMsgContent.includes('content="text/html; charset=windows-1252"')) {
     throw new Error(
       "Expected content type not in msg; draftMsgContent=" + draftMsgContent
     );
   }
@@ -104,17 +102,17 @@ function test_encoding_upgrade_html_comp
   type_in_composer(compWin, ["content need to be upgraded to utf-8 now."]);
 
   // Ctrl+S = save as draft.
   compWin.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   be_in_folder(gDrafts);
   let draftMsg2 = select_click_row(0);
   // Charset should have be upgraded to UTF-8.
-  assert_equals(draftMsg2.Charset, "UTF-8");
+  Assert.equal(draftMsg2.Charset, "UTF-8");
 
   let draftMsg2Content = get_msg_source(draftMsg2, "UTF-8");
   if (!draftMsg2Content.includes('content="text/html; charset=UTF-8"')) {
     throw new Error(
       "Expected content type not in msg; draftMsg2Content=" + draftMsg2Content
     );
   }
 
@@ -136,42 +134,42 @@ function test_encoding_upgrade_html_comp
   let outMsgContent = get_msg_source(outMsg, "UTF-8");
 
   // This message should be multipart/alternative.
   if (!outMsgContent.includes("Content-Type: multipart/alternative")) {
     throw new Error("Expected multipart/alternative; content=" + outMsgContent);
   }
 
   let chinesePlainIdx = outMsgContent.indexOf(CHINESE);
-  assert_true(
+  Assert.ok(
     chinesePlainIdx > 0,
     "chinesePlainIdx=" + chinesePlainIdx + ", outMsgContent=" + outMsgContent
   );
 
   let chineseHTMLIdx = outMsgContent.indexOf(CHINESE, chinesePlainIdx);
-  assert_true(
+  Assert.ok(
     chineseHTMLIdx > 0,
     "chineseHTMLIdx=" + chineseHTMLIdx + ", outMsgContent=" + outMsgContent
   );
 
   // Make sure the actual html also got the content type set correctly.
   if (!outMsgContent.includes('content="text/html; charset=UTF-8"')) {
     throw new Error(
       "Expected content type not in html; outMsgContent=" + outMsgContent
     );
   }
 
   press_delete(); // Delete the msg from Outbox.
-}
+});
 
 /**
  * Test that if all characters don't fit the current charset selection,
  * we upgrade properly to UTF-8. In plaintext composition.
  */
-function test_encoding_upgrade_plaintext_compose() {
+add_task(function test_encoding_upgrade_plaintext_compose() {
   Services.prefs.setBoolPref("mail.identity.default.compose_html", false);
   let compWin = open_compose_new_mail();
   Services.prefs.setBoolPref("mail.identity.default.compose_html", true);
 
   setup_msg_contents(
     compWin,
     "someone-else@example.com",
     "encoding upgrade test - plaintext",
@@ -180,31 +178,31 @@ function test_encoding_upgrade_plaintext
 
   // Ctrl+S = Save as Draft.
   compWin.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   be_in_folder(gDrafts);
   let draftMsg = select_click_row(0);
 
   // Charset should still be the default.
-  assert_equals(draftMsg.Charset, "windows-1252");
+  Assert.equal(draftMsg.Charset, "windows-1252");
 
   const CHINESE = "漢皇重色思傾國漢皇重色思傾國";
   type_in_composer(compWin, [
     "enter some plain text chinese: " + CHINESE,
     "content need to be upgraded to utf-8 now.",
   ]);
 
   // Ctrl+S = Save as Draft.
   compWin.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   be_in_folder(gDrafts);
   let draftMsg2 = select_click_row(0);
   // Charset should have be upgraded to UTF-8.
-  assert_equals(draftMsg2.Charset, "UTF-8");
+  Assert.equal(draftMsg2.Charset, "UTF-8");
 
   let draftMsg2Content = get_msg_source(draftMsg2, "UTF-8");
   if (draftMsg2Content.includes("<html>")) {
     throw new Error(
       "Plaintext draft contained <html>; " +
         "draftMsg2Content=" +
         draftMsg2Content
     );
@@ -237,15 +235,15 @@ function test_encoding_upgrade_plaintext
       "Chinese text not in msg; CHINESE=" +
         CHINESE +
         ", outMsgContent=" +
         outMsgContent
     );
   }
 
   press_delete(); // Delete the msg from Outbox.
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   Services.prefs.clearUserPref("mailnews.send_default_charset");
   Services.prefs.clearUserPref("mail.compose.default_to_paragraph");
   Services.prefs.clearUserPref("mail.identity.default.compose_html");
-}
+});
copy from mail/test/mozmill/composition/test-cp932-display.js
copy to mail/test/browser/composition/browser_cp932Display.js
--- a/mail/test/mozmill/composition/test-cp932-display.js
+++ b/mail/test/browser/composition/browser_cp932Display.js
@@ -3,36 +3,34 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Tests that messages in cp932, Thunderbirds alias for Shift_JIS, are correctly displayed.
  */
 
 "use strict";
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
-var { assert_true, open_message_from_file } = ChromeUtils.import(
+var { open_message_from_file } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 var { close_window } = ChromeUtils.import(
   "resource://testing-common/mozmill/WindowHelpers.jsm"
 );
 
-function test_cp932_display() {
-  let file = os.getFileForPath(
-    os.abspath("./charset-cp932.eml", os.getFileForPath(__file__))
-  );
+add_task(function test_cp932_display() {
+  let file = new FileUtils.File(getTestFilePath("data/charset-cp932.eml"));
   let msgc = open_message_from_file(file);
   let subjectText = msgc.e("expandedsubjectBox").textContent;
   let bodyText = msgc.e("messagepane").contentDocument.querySelector("body")
     .textContent;
   close_window(msgc);
 
-  assert_true(
+  Assert.ok(
     subjectText.includes("ここに本文がきます。"),
     "Decoded cp932 text not found in message subject."
   );
-  assert_true(
+  Assert.ok(
     bodyText.includes("ここに本文がきます。"),
     "Decoded cp932 text not found in message body."
   );
-}
+});
copy from mail/test/mozmill/composition/test-draft-identity.js
copy to mail/test/browser/composition/browser_draftIdentity.js
--- a/mail/test/mozmill/composition/test-draft-identity.js
+++ b/mail/test/browser/composition/browser_draftIdentity.js
@@ -8,17 +8,16 @@
  */
 
 "use strict";
 
 var { close_compose_window, open_compose_from_draft } = ChromeUtils.import(
   "resource://testing-common/mozmill/ComposeHelpers.jsm"
 );
 var {
-  assert_equals,
   be_in_folder,
   get_special_folder,
   mc,
   press_delete,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
@@ -41,17 +40,17 @@ var gIdentities = [
   { email: "x@example.invalid" },
   { email: "y@example.invalid", fullname: "User Y" },
   { email: "y@example.invalid", fullname: "User YY", label: "YY" },
   { email: "y+y@example.invalid", fullname: "User Y" },
   { email: "z@example.invalid", fullname: "User Z", label: "Label Z" },
   { email: "a+b@example.invalid", fullname: "User A" },
 ];
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   // Now set up an account with some identities.
   let acctMgr = MailServices.accounts;
   gAccount = acctMgr.createAccount();
   gAccount.incomingServer = acctMgr.createIncomingServer(
     "nobody",
     "Draft Identity Testing",
     "pop3"
   );
@@ -70,17 +69,17 @@ function setupModule(module) {
     gAccount.addIdentity(identity);
     id.key = identity.key;
     id.name = identity.identityName;
   }
 
   acctMgr.defaultAccount = gAccount;
 
   gDrafts = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
-}
+});
 
 /**
  * Create a new templated draft message in the drafts folder.
  *
  * @return {integer}  The index (position) of the created message in the drafts folder.
  */
 function create_draft(aFrom, aIdKey) {
   let msgCount = gDrafts.getTotalMessages(false);
@@ -106,52 +105,52 @@ function create_draft(aFrom, aIdKey) {
     "Content-Type: text/plain; charset=utf-8\n" +
     "Content-Transfer-Encoding: 8bit\n" +
     "\n" +
     "Testing draft identity.\n";
 
   gDrafts.QueryInterface(Ci.nsIMsgLocalMailFolder).addMessage(source);
   let msgCountNew = gDrafts.getTotalMessages(false);
 
-  assert_equals(msgCountNew, msgCount + 1);
+  Assert.equal(msgCountNew, msgCount + 1);
   return msgCountNew - 1;
 }
 
 /**
  * Helper to check that a suitable From identity was set up in the given
  * composer window.
  *
  * @param cwc             Compose window controller.
  * @param aIdentityKey    The key of the expected identity.
  * @param aFrom           The expected displayed From address.
  */
 function checkCompIdentity(cwc, aIdentityKey, aFrom) {
-  assert_equals(
+  Assert.equal(
     cwc.window.getCurrentAccountKey(),
     gAccount.key,
     "The From account is not correctly selected"
   );
-  assert_equals(
+  Assert.equal(
     cwc.window.getCurrentIdentityKey(),
     aIdentityKey,
     "The From identity is not correctly selected"
   );
-  assert_equals(
+  Assert.equal(
     cwc.window.GetMsgIdentityElement().value,
     aFrom,
     "The From value was initialized to an unexpected value"
   );
 }
 
 /**
  * Bug 394216
  * Test that starting a new message from a draft with various combinations
  * of From and X-Identity-Key gets the expected initial identity selected.
  */
-function test_draft_identity_selection() {
+add_task(function test_draft_identity_selection() {
   let tests = [
     // X-Identity-Key header exists:
     // 1. From header matches X-Identity-Key identity exactly
     {
       idIndex: 1,
       warning: false,
       draftIdKey: gIdentities[1].key,
       draftFrom: gIdentities[1].name,
@@ -271,20 +270,19 @@ function test_draft_identity_selection()
   cwc.click(cwc.eid("msgIdentity"));
   cwc.click_menus_in_sequence(cwc.e("msgIdentityPopup"),
                               [ { identitykey: gIdentities[0].key } ]);
 
   wait_for_notification_to_stop(cwc, "compose-notification-bottom",
                                 "identityWarning");
   close_compose_window(cwc, false);
 */
-}
-test_draft_identity_selection.EXCLUDED_PLATFORMS = ["darwin"]; // See bug 1413851.
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   for (let id = 1; id < gIdentities.length; id++) {
     gAccount.removeIdentity(
       MailServices.accounts.getIdentity(gIdentities[id].key)
     );
   }
 
   // The last identity of an account can't be removed so clear all its prefs
   // which effectively destroys it.
@@ -294,9 +292,9 @@ function teardownModule(module) {
 
   // Clear our drafts.
   be_in_folder(gDrafts);
   let draftCount;
   while ((draftCount = gDrafts.getTotalMessages(false)) > 0) {
     press_delete();
     mc.waitFor(() => gDrafts.getTotalMessages(false) < draftCount);
   }
-}
+});
copy from mail/test/mozmill/composition/test-drafts.js
copy to mail/test/browser/composition/browser_drafts.js
--- a/mail/test/mozmill/composition/test-drafts.js
+++ b/mail/test/browser/composition/browser_drafts.js
@@ -4,29 +4,27 @@
 
 /**
  * Tests draft related functionality:
  * - that we don't allow opening multiple copies of a draft.
  */
 
 "use strict";
 
-var utils = ChromeUtils.import("chrome://mozmill/content/modules/utils.jsm");
+var utils = ChromeUtils.import("resource://testing-common/mozmill/utils.jsm");
 
 var {
   close_compose_window,
   get_compose_body,
   get_msg_source,
   open_compose_new_mail,
   setup_msg_contents,
   wait_for_compose_window,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
-  assert_equals,
-  assert_true,
   be_in_folder,
   get_special_folder,
   make_new_sets_in_folder,
   mc,
   press_delete,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
@@ -41,25 +39,25 @@ var { plan_for_new_window, wait_for_wind
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var kBoxId = "mail-notification-top";
 var draftsFolder;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   draftsFolder = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
-}
+});
 
 /**
  * Bug 349547.
  * Tests that we only open one compose window for one instance of a draft.
  */
-function test_open_draft_again() {
+add_task(function test_open_draft_again() {
   make_new_sets_in_folder(draftsFolder, [{ count: 1 }]);
   be_in_folder(draftsFolder);
   select_click_row(0);
 
   // Wait for the notification with the Edit button.
   wait_for_notification_to_show(mc, kBoxId, "draftMsgContent");
 
   plan_for_new_window("msgcompose");
@@ -73,39 +71,39 @@ function test_open_draft_again() {
     cwins++;
   }
 
   // click edit in main win again
   mc.click(mc.eid(kBoxId, { tagName: "button", label: "Edit" }));
 
   mc.sleep(1000); // wait a sec to see if it caused a new window
 
-  assert_true(
+  Assert.ok(
     Services.ww.activeWindow == cwc.window,
     "the original draft composition window should have got focus (again)"
   );
 
   let cwins2 = 0;
   let e2 = Services.wm.getEnumerator("msgcompose");
   while (e2.hasMoreElements()) {
     e2.getNext();
     cwins2++;
   }
 
-  assert_true(cwins2 > 0, "No compose window open!");
-  assert_equals(cwins, cwins2, "The number of compose windows changed!");
+  Assert.ok(cwins2 > 0, "No compose window open!");
+  Assert.equal(cwins, cwins2, "The number of compose windows changed!");
 
   // Type something and save, then check that we only have one draft.
   cwc.type(cwc.eid("content-frame"), "Hello!");
   cwc.keypress(null, "s", { shiftKey: false, accelKey: true });
   close_compose_window(cwc);
-  assert_equals(draftsFolder.getTotalMessages(false), 1);
+  Assert.equal(draftsFolder.getTotalMessages(false), 1);
 
   press_delete(mc); // clean up after ourselves
-}
+});
 
 /**
  * Bug 1202165
  * Test that the user set delivery format is preserved in a draft message.
  */
 function internal_check_delivery_format(editDraft) {
   let cwc = open_compose_new_mail();
 
@@ -120,17 +118,17 @@ function internal_check_delivery_format(
   if (!mc.mozmillModule.isMac) {
     cwc.click(cwc.eid("optionsMenu"));
     cwc.click_menus_in_sequence(cwc.e("optionsMenuPopup"), [
       { id: "outputFormatMenu" },
       { id: "format_both" },
     ]);
   } else {
     // On OS X the main menu seems not accessible for clicking from mozmill.
-    assert_true(
+    Assert.ok(
       cwc
         .e("outputFormatMenu")
         .getAttribute("oncommand")
         .startsWith("OutputFormatMenuSelect(")
     );
     cwc.window.OutputFormatMenuSelect(cwc.e("format_both"));
   }
 
@@ -146,20 +144,20 @@ function internal_check_delivery_format(
       let formatMenu = cwc.click_menus_in_sequence(
         cwc.e("optionsMenuPopup"),
         [{ id: "outputFormatMenu" }],
         true
       );
       let formatItem = cwc
         .e("outputFormatMenuPopup")
         .querySelector("[name=output_format][checked=true]");
-      assert_equals(formatItem.id, aMenuItemId);
+      Assert.equal(formatItem.id, aMenuItemId);
       cwc.close_popup_sequence(formatMenu);
     } else {
-      assert_equals(cwc.window.gSendFormat, aValue);
+      Assert.equal(cwc.window.gSendFormat, aValue);
     }
   }
 
   cwc.window.SaveAsDraft();
   utils.waitFor(
     () => !cwc.window.gSaveOperationInProgress && !cwc.window.gWindowLock,
     "Saving of draft did not finish"
   );
@@ -194,58 +192,58 @@ function internal_check_delivery_format(
   // Check if format value was restored.
   assert_format_value("format_both", Ci.nsIMsgCompSendFormat.Both);
 
   close_compose_window(cwc);
 
   press_delete(mc); // clean up the created draft
 }
 
-function test_save_delivery_format_with_edit_draft() {
+add_task(function test_save_delivery_format_with_edit_draft() {
   internal_check_delivery_format(true);
-}
+});
 
-function test_save_delivery_format_with_edit_template() {
+add_task(function test_save_delivery_format_with_edit_template() {
   internal_check_delivery_format(false);
-}
+});
 
 /**
  * Tests that 'Edit as New' leaves the original message in drafts folder.
  */
-function test_edit_as_new_in_draft() {
+add_task(function test_edit_as_new_in_draft() {
   make_new_sets_in_folder(draftsFolder, [{ count: 1 }]);
   be_in_folder(draftsFolder);
 
-  assert_equals(draftsFolder.getTotalMessages(false), 1);
+  Assert.equal(draftsFolder.getTotalMessages(false), 1);
 
   select_click_row(0);
 
   // Wait for the notification with the Edit button.
   wait_for_notification_to_show(mc, kBoxId, "draftMsgContent");
 
   plan_for_new_window("msgcompose");
   mc.keypress(null, "e", { shiftKey: false, accelKey: true });
   let cwc = wait_for_compose_window();
 
   cwc.type(cwc.eid("content-frame"), "Hello!");
   cwc.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   close_compose_window(cwc);
-  assert_equals(draftsFolder.getTotalMessages(false), 2);
+  Assert.equal(draftsFolder.getTotalMessages(false), 2);
 
   // Clean up the created drafts and count again.
   press_delete(mc);
   press_delete(mc);
-  assert_equals(draftsFolder.getTotalMessages(false), 0);
-}
+  Assert.equal(draftsFolder.getTotalMessages(false), 0);
+});
 
 /**
  * Tests Content-Language header.
  */
-function test_content_language_header() {
+add_task(function test_content_language_header() {
   let cwc = open_compose_new_mail();
 
   setup_msg_contents(
     cwc,
     "test@example.invalid",
     "Testing Content-Language header",
     "Hello, we speak en-US"
   );
@@ -263,27 +261,27 @@ function test_content_language_header() 
   let draftMsgContent = get_msg_source(draftMsg);
 
   // Check for a single line that contains our header.
   if (
     !draftMsgContent
       .split("\n")
       .some(line => line.trim() == "Content-Language: en-US")
   ) {
-    assert_true(false, "Failed to find Content-Language: en-US");
+    Assert.ok(false, "Failed to find Content-Language: en-US");
   }
 
   // Clean up the created draft.
   press_delete(mc);
-}
+});
 
 /**
  * Tests space stuffing of plaintext message.
  */
-function test_remove_space_stuffing_format_flowed() {
+add_task(function test_remove_space_stuffing_format_flowed() {
   // Prepare for plaintext email.
   let oldHtmlPref = Services.prefs.getBoolPref(
     "mail.identity.default.compose_html"
   );
   Services.prefs.setBoolPref("mail.identity.default.compose_html", false);
 
   let cwc = open_compose_new_mail();
 
@@ -311,18 +309,17 @@ function test_remove_space_stuffing_form
   wait_for_notification_to_show(mc, kBoxId, "draftMsgContent");
 
   plan_for_new_window("msgcompose");
   mc.click(mc.eid(kBoxId, { tagName: "button", label: "Edit" }));
   cwc = wait_for_compose_window();
 
   let bodyText = get_compose_body(cwc).innerHTML;
   if (!bodyText.includes("NoSpace<br> OneSpace<br>  TwoSpaces")) {
-    assert_true(false, "Something went wrong with space stuffing");
+    Assert.ok(false, "Something went wrong with space stuffing");
   }
+  close_compose_window(cwc);
 
   // Clean up the created draft.
   press_delete(mc);
 
   Services.prefs.setBoolPref("mail.identity.default.compose_html", oldHtmlPref);
-}
-
-function teardownModule() {}
+});
copy from mail/test/mozmill/composition/test-eml-actions.js
copy to mail/test/browser/composition/browser_emlActions.js
--- a/mail/test/mozmill/composition/test-eml-actions.js
+++ b/mail/test/browser/composition/browser_emlActions.js
@@ -4,28 +4,27 @@
 
 /**
  * Tests that actions such as replying to an .eml works properly.
  */
 
 "use strict";
 
 var elib = ChromeUtils.import(
-  "chrome://mozmill/content/modules/elementslib.jsm"
+  "resource://testing-common/mozmill/elementslib.jsm"
 );
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
 var {
   close_compose_window,
   get_compose_body,
   open_compose_with_forward,
   open_compose_with_reply,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
-  assert_equals,
   be_in_folder,
   get_special_folder,
   open_message_from_file,
   press_delete,
   select_click_row,
 } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
@@ -34,29 +33,27 @@ var { close_window } = ChromeUtils.impor
 );
 
 var { MailServices } = ChromeUtils.import(
   "resource:///modules/MailServices.jsm"
 );
 
 var gDrafts;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   gDrafts = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
-}
+});
 
 /**
  * Test that replying to an opened .eml message works, and that the reply can
  * be saved as a draft.
  */
-function test_reply_to_eml_save_as_draft() {
+add_task(function test_reply_to_eml_save_as_draft() {
   // Open an .eml file.
-  let file = os.getFileForPath(
-    os.abspath("./testmsg.eml", os.getFileForPath(__file__))
-  );
+  let file = new FileUtils.File(getTestFilePath("data/testmsg.eml"));
   let msgc = open_message_from_file(file);
 
   let replyWin = open_compose_with_reply(msgc);
 
   // Ctrl+S saves as draft.
   replyWin.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   // Drafts folder should exist now.
@@ -64,27 +61,25 @@ function test_reply_to_eml_save_as_draft
   let draftMsg = select_click_row(0);
   if (!draftMsg) {
     throw new Error("No draft saved!");
   }
   press_delete(); // Delete the draft.
 
   close_compose_window(replyWin); // close compose window
   close_window(msgc); // close base .eml message
-}
+});
 
 /**
  * Test that forwarding an opened .eml message works, and that the forward can
  * be saved as a draft.
  */
-function test_forward_eml_save_as_draft() {
+add_task(function test_forward_eml_save_as_draft() {
   // Open an .eml file.
-  let file = os.getFileForPath(
-    os.abspath("./testmsg.eml", os.getFileForPath(__file__))
-  );
+  let file = new FileUtils.File(getTestFilePath("data/testmsg.eml"));
   let msgc = open_message_from_file(file);
 
   let replyWin = open_compose_with_forward(msgc);
 
   // Ctrl+S saves as draft.
   replyWin.keypress(null, "s", { shiftKey: false, accelKey: true });
 
   // Drafts folder should exist now.
@@ -92,43 +87,41 @@ function test_forward_eml_save_as_draft(
   let draftMsg = select_click_row(0);
   if (!draftMsg) {
     throw new Error("No draft saved!");
   }
   press_delete(); // Delete the draft.
 
   close_compose_window(replyWin); // close compose window
   close_window(msgc); // close base .eml message
-}
+});
 
 /**
  * Test that MIME encoded subject is decoded when replying to an opened .eml.
  */
-function test_reply_eml_subject() {
+add_task(function test_reply_eml_subject() {
   // Open an .eml file whose subject is encoded.
-  let file = os.getFileForPath(
-    os.abspath("./mime-encoded-subject.eml", os.getFileForPath(__file__))
+  let file = new FileUtils.File(
+    getTestFilePath("data/mime-encoded-subject.eml")
   );
   let msgc = open_message_from_file(file);
 
   let replyWin = open_compose_with_reply(msgc);
 
-  assert_equals(replyWin.e("msgSubject").value, "Re: \u2200a\u220aA");
+  Assert.equal(replyWin.e("msgSubject").value, "Re: \u2200a\u220aA");
   close_compose_window(replyWin); // close compose window
   close_window(msgc); // close base .eml message
-}
+});
 
 /**
  * Test that replying to a base64 encoded .eml works.
  */
-function test_reply_to_base64_eml() {
+add_task(function test_reply_to_base64_eml() {
   // Open an .eml file.
-  let file = os.getFileForPath(
-    os.abspath("./base64-encoded-msg.eml", os.getFileForPath(__file__))
-  );
+  let file = new FileUtils.File(getTestFilePath("data/base64-encoded-msg.eml"));
   let msgc = open_message_from_file(file);
 
   let compWin = open_compose_with_reply(msgc);
 
   let bodyText = get_compose_body(compWin).textContent;
   const message = "You have decoded this text from base64.";
   if (!bodyText.includes(message)) {
     throw new Error(
@@ -136,26 +129,24 @@ function test_reply_to_base64_eml() {
         message +
         ", bodyText=" +
         bodyText
     );
   }
 
   close_compose_window(compWin);
   close_window(msgc);
-}
+});
 
 /**
  * Test that forwarding a base64 encoded .eml works.
  */
-function test_forward_base64_eml() {
+add_task(function test_forward_base64_eml() {
   // Open an .eml file.
-  let file = os.getFileForPath(
-    os.abspath("./base64-encoded-msg.eml", os.getFileForPath(__file__))
-  );
+  let file = new FileUtils.File(getTestFilePath("data/base64-encoded-msg.eml"));
   let msgc = open_message_from_file(file);
 
   let compWin = open_compose_with_forward(msgc);
 
   let bodyText = get_compose_body(compWin).textContent;
   const message = "You have decoded this text from base64.";
   if (!bodyText.includes(message)) {
     throw new Error(
@@ -163,9 +154,9 @@ function test_forward_base64_eml() {
         message +
         ", bodyText=" +
         bodyText
     );
   }
 
   close_compose_window(compWin);
   close_window(msgc);
-}
+});
copy from mail/test/mozmill/composition/test-focus.js
copy to mail/test/browser/composition/browser_focus.js
--- a/mail/test/mozmill/composition/test-focus.js
+++ b/mail/test/browser/composition/browser_focus.js
@@ -8,17 +8,17 @@
 
 "use strict";
 
 var {
   add_attachments,
   close_compose_window,
   open_compose_new_mail,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
-var { assert_equals, mc } = ChromeUtils.import(
+var { mc } = ChromeUtils.import(
   "resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
 );
 
 /**
  * Check that it's possible to cycle through the compose window's important
  * elements forward and backward.
  *
  * @param controller the compose window controller
@@ -33,61 +33,61 @@ function check_element_cycling(controlle
   let contentElement = controller.window.content;
   let identityElement = controller.e("msgIdentity");
 
   let key = ctrlTab ? "VK_TAB" : "VK_F6";
 
   // We start on the addressing widget and go from there.
 
   controller.keypress(null, key, { ctrlKey: ctrlTab });
-  assert_equals(subjectElement, controller.window.WhichElementHasFocus());
+  Assert.equal(subjectElement, controller.window.WhichElementHasFocus());
   if (attachmentsExpanded) {
     controller.keypress(null, key, { ctrlKey: ctrlTab });
-    assert_equals(attachmentElement, controller.window.WhichElementHasFocus());
+    Assert.equal(attachmentElement, controller.window.WhichElementHasFocus());
   }
   controller.keypress(null, key, { ctrlKey: ctrlTab });
-  assert_equals(contentElement, controller.window.WhichElementHasFocus());
+  Assert.equal(contentElement, controller.window.WhichElementHasFocus());
   controller.keypress(null, key, { ctrlKey: ctrlTab });
-  assert_equals(identityElement, controller.window.WhichElementHasFocus());
+  Assert.equal(identityElement, controller.window.WhichElementHasFocus());
   controller.keypress(null, key, { ctrlKey: ctrlTab });
   mc.sleep(0); // Focusing the addressing element happens in a timeout...
-  assert_equals(addressingElement, controller.window.WhichElementHasFocus());
+  Assert.equal(addressingElement, controller.window.WhichElementHasFocus());
 
   controller.keypress(null, key, { ctrlKey: ctrlTab, shiftKey: true });
-  assert_equals(identityElement, controller.window.WhichElementHasFocus());
+  Assert.equal(identityElement, controller.window.WhichElementHasFocus());
   controller.keypress(null, key, { ctrlKey: ctrlTab, shiftKey: true });
-  assert_equals(contentElement, controller.window.WhichElementHasFocus());
+  Assert.equal(contentElement, controller.window.WhichElementHasFocus());
   if (attachmentsExpanded) {
     controller.keypress(null, key, { ctrlKey: ctrlTab, shiftKey: true });
-    assert_equals(attachmentElement, controller.window.WhichElementHasFocus());
+    Assert.equal(attachmentElement, controller.window.WhichElementHasFocus());
   }
   controller.keypress(null, key, { ctrlKey: ctrlTab, shiftKey: true });
-  assert_equals(subjectElement, controller.window.WhichElementHasFocus());
+  Assert.equal(subjectElement, controller.window.WhichElementHasFocus());
   controller.keypress(null, key, { ctrlKey: ctrlTab, shiftKey: true });
   mc.sleep(0); // Focusing the addressing element happens in a timeout...
-  assert_equals(addressingElement, controller.window.WhichElementHasFocus());
+  Assert.equal(addressingElement, controller.window.WhichElementHasFocus());
 }
 
-function test_f6_no_attachment() {
+add_task(function test_f6_no_attachment() {
   let cwc = open_compose_new_mail();
   check_element_cycling(cwc, false, false);
   close_compose_window(cwc);
-}
+});
 
-function test_f6_attachment() {
+add_task(function test_f6_attachment() {
   let cwc = open_compose_new_mail();
   add_attachments(cwc, "http://www.mozilla.org/");
   check_element_cycling(cwc, true, false);
   close_compose_window(cwc);
-}
+});
 
-function test_ctrl_tab_no_attachment() {
+add_task(function test_ctrl_tab_no_attachment() {
   let cwc = open_compose_new_mail();
   check_element_cycling(cwc, false, true);
   close_compose_window(cwc);
-}
+});
 
-function test_ctrl_tab_attachment() {
+add_task(function test_ctrl_tab_attachment() {
   let cwc = open_compose_new_mail();
   add_attachments(cwc, "http://www.mozilla.org/");
   check_element_cycling(cwc, true, true);
   close_compose_window(cwc);
-}
+});
copy from mail/test/mozmill/composition/test-forward-headers.js
copy to mail/test/browser/composition/browser_forwardHeaders.js
--- a/mail/test/mozmill/composition/test-forward-headers.js
+++ b/mail/test/browser/composition/browser_forwardHeaders.js
@@ -12,18 +12,16 @@
 var {
   assert_previous_text,
   get_compose_body,
   open_compose_with_forward,
   open_compose_with_forward_as_attachments,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
   add_sets_to_folders,
-  assert_equals,
-  assert_true,
   be_in_folder,
   create_folder,
   create_thread,
   get_special_folder,
   mc,
   press_delete,
   select_click_row,
   select_shift_click_row,
@@ -41,32 +39,32 @@ var {
 } = ChromeUtils.import("resource://testing-common/mozmill/WindowHelpers.jsm");
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var cwc = null; // compose window controller
 var folder;
 var gDrafts;
 
-function setupModule(module) {
+add_task(function setupModule(module) {
   folder = create_folder("Test");
   let thread1 = create_thread(10);
   add_sets_to_folders([folder], [thread1]);
 
   gDrafts = get_special_folder(Ci.nsMsgFolderFlags.Drafts, true);
 
   // Don't create paragraphs in the test.
   // The test checks for the first DOM node and expects a text and not
   // a paragraph.
   Services.prefs.setBoolPref("mail.compose.default_to_paragraph", false);
-}
+});
 
-function teardownModule(module) {
+registerCleanupFunction(function teardownModule(module) {
   Services.prefs.clearUserPref("mail.compose.default_to_paragraph");
-}
+});
 
 function forward_selected_messages_and_go_to_drafts_folder(f) {
   const kText = "Hey check out this megalol link";
   // opening a new compose window
   cwc = f(mc);
   cwc.type(cwc.eid("content-frame"), kText);
 
   let mailBody = get_compose_body(cwc);
@@ -85,88 +83,88 @@ function forward_selected_messages_and_g
   wait_for_modal_dialog();
   // Actually quit the window.
   wait_for_window_close();
 
   // Visit the existing Drafts folder.
   be_in_folder(gDrafts);
 }
 
-function test_forward_inline() {
+add_task(function test_forward_inline() {
   be_in_folder(folder);
   // original message header
   let oMsgHdr = select_click_row(0);
 
   forward_selected_messages_and_go_to_drafts_folder(open_compose_with_forward);
 
   // forwarded message header
   let fMsgHdr = select_click_row(0);
 
-  assert_true(
+  Assert.ok(
     fMsgHdr.numReferences > 0,
     "No References Header in forwarded msg."
   );
-  assert_equals(
+  Assert.equal(
     fMsgHdr.getStringReference(0),
     oMsgHdr.messageId,
     "The forwarded message should have References: = Message-Id: of the original msg"
   );
 
   // test for x-forwarded-message id and exercise the js mime representation as
   // well
   to_mime_message(fMsgHdr, null, function(aMsgHdr, aMimeMsg) {
-    assert_equals(
+    Assert.equal(
       aMimeMsg.headers["x-forwarded-message-id"],
       "<" + oMsgHdr.messageId + ">"
     );
-    assert_equals(aMimeMsg.headers.references, "<" + oMsgHdr.messageId + ">");
+    Assert.equal(aMimeMsg.headers.references, "<" + oMsgHdr.messageId + ">");
   });
   press_delete(mc);
-}
+});
 
-function test_forward_as_attachments() {
+add_task(function test_forward_as_attachments() {
   be_in_folder(folder);
   // original message header
   let oMsgHdr0 = select_click_row(0);
   let oMsgHdr1 = select_click_row(1);
   select_shift_click_row(0);
 
   forward_selected_messages_and_go_to_drafts_folder(
     open_compose_with_forward_as_attachments
   );
 
   // forwarded message header
   let fMsgHdr = select_click_row(0);
 
-  assert_true(
+  Assert.ok(
     fMsgHdr.numReferences > 0,
     "No References Header in forwarded msg."
   );
-  assert_true(
+  Assert.ok(
     fMsgHdr.numReferences > 1,
     "Only one References Header in forwarded msg."
   );
-  assert_equals(
+  Assert.equal(
     fMsgHdr.getStringReference(1),
     oMsgHdr1.messageId,
     "The forwarded message should have References: = Message-Id: of the original msg#1"
   );
-  assert_equals(
+  Assert.equal(
     fMsgHdr.getStringReference(0),
     oMsgHdr0.messageId,
     "The forwarded message should have References: = Message-Id: of the original msg#0"
   );
 
   // test for x-forwarded-message id and exercise the js mime representation as
   // well
   to_mime_message(fMsgHdr, null, function(aMsgHdr, aMimeMsg) {
-    assert_equals(
+    Assert.equal(
       aMimeMsg.headers["x-forwarded-message-id"],
       "<" + oMsgHdr0.messageId + "> <" + oMsgHdr1.messageId + ">"
     );
-    assert_equals(
+    Assert.equal(
       aMimeMsg.headers.references,
       "<" + oMsgHdr0.messageId + "> <" + oMsgHdr1.messageId + ">"
     );
   });
 
   press_delete(mc);
-}
+});
copy from mail/test/mozmill/composition/test-forward-rfc822-attach.js
copy to mail/test/browser/composition/browser_forwardRFC822Attach.js
--- a/mail/test/mozmill/composition/test-forward-rfc822-attach.js
+++ b/mail/test/browser/composition/browser_forwardRFC822Attach.js
@@ -4,25 +4,24 @@
 
 /**
  * Tests that attached messages (message/rfc822) are correctly sent.
  * It's easiest to test the forward case.
  */
 
 "use strict";
 
-var os = ChromeUtils.import("chrome://mozmill/content/stdlib/os.jsm");
+var os = ChromeUtils.import("resource://testing-common/mozmill/os.jsm");
 
 var {
   close_compose_window,
   get_msg_source,
   open_compose_with_forward_as_attachments,
 } = ChromeUtils.import("resource://testing-common/mozmill/ComposeHelpers.jsm");
 var {
-  assert_true,
   be_in_folder,
   get_special_folder,