Bug 1252296 - Convert test_contextmenu_input.html to browser_contextmenu_input.html to run in e10s. r?gijs draft
authorJared Wein <jwein@mozilla.com>
Wed, 02 Mar 2016 14:19:59 -0500
changeset 336154 7ed56637fb8b8ab304e8ceb149938ed958afdab8
parent 334408 e86f91dd77be96bc473c02acf581a4a19d3073ef
child 515331 7f77eed43ec38d5cb1a2ad6294d88bb814c3c39d
push id11999
push userjwein@mozilla.com
push dateWed, 02 Mar 2016 19:20:08 +0000
reviewersgijs
bugs1252296
milestone47.0a1
Bug 1252296 - Convert test_contextmenu_input.html to browser_contextmenu_input.html to run in e10s. r?gijs MozReview-Commit-ID: FwiwY1WO42o
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_contextmenu.js
browser/base/content/test/general/browser_contextmenu_input.js
browser/base/content/test/general/contextmenu_common.js
browser/base/content/test/general/mochitest.ini
browser/base/content/test/general/subtst_contextmenu_input.html
browser/base/content/test/general/test_contextmenu_input.html
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -84,16 +84,17 @@ support-files =
   ssl_error_reports.sjs
   popup_blocker.html
   print_postdata.sjs
   redirect_bug623155.sjs
   searchSuggestionEngine.sjs
   searchSuggestionEngine.xml
   searchSuggestionEngine2.xml
   subtst_contextmenu.html
+  subtst_contextmenu_input.html
   test-mixedcontent-securityerrors.html
   test_bug435035.html
   test_bug462673.html
   test_bug628179.html
   test_bug839103.html
   test_bug959531.html
   test_process_flags_chrome.html
   test_wyciwyg_copying.html
@@ -290,16 +291,18 @@ skip-if = os == 'win' || e10s # Bug 1159
 [browser_bug1070778.js]
 [browser_accesskeys.js]
 [browser_canonizeURL.js]
 skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
 [browser_clipboard.js]
 [browser_contentAreaClick.js]
 [browser_contextmenu.js]
 skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
+[browser_contextmenu_input.js]
+skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
 [browser_ctrlTab.js]
 [browser_datachoices_notification.js]
 skip-if = !datareporting
 [browser_devedition.js]
 [browser_devices_get_user_media.js]
 skip-if = buildapp == 'mulet' || (os == "linux" && debug) # linux: bug 976544
 [browser_devices_get_user_media_about_urls.js]
 skip-if = e10s # Bug 1071623
--- a/browser/base/content/test/general/browser_contextmenu.js
+++ b/browser/base/content/test/general/browser_contextmenu.js
@@ -781,115 +781,16 @@ add_task(function* test_input_spell_fals
     ]
   );
 });
 
 add_task(function* test_cleanup() {
   gBrowser.removeCurrentTab();
 });
 
-let lastElementSelector = null;
-
-/**
- * Right-clicks on the element that matches `selector` and checks the
- * context menu that appears against the `menuItems` array.
- *
- * @param {String} selector
- *        A selector passed to querySelector to find
- *        the element that will be referenced.
- * @param {Array} menuItems
- *        An array of menuitem ids and their associated enabled state. A state
- *        of null means that it will be ignored. Ids of '---' are used for
- *        menuseparators.
- * @param {Object} options, optional
- *        skipFocusChange: don't move focus to the element before test, useful
- *                         if you want to delay spell-check initialization
- *        offsetX: horizontal mouse offset from the top-left corner of
- *                 the element, optional
- *        offsetY: vertical mouse offset from the top-left corner of the
- *                 element, optional
- *        centered: if true, mouse position is centered in element, defaults
- *                  to true if offsetX and offsetY are not provided
- *        waitForSpellCheck: wait until spellcheck is initialized before
- *                           starting test
- *        preCheckContextMenuFn: callback to run before opening menu
- *        postCheckContextMenuFn: callback to run after opening menu
- * @return {Promise} resolved after the test finishes
- */
-function* test_contextmenu(selector, menuItems, options={}) {
-  contextMenu = document.getElementById("contentAreaContextMenu");
-  is(contextMenu.state, "closed", "checking if popup is closed");
-
-  // Default to centered if no positioning is defined.
-  if (!options.offsetX && !options.offsetY) {
-    options.centered = true;
-  }
-
-  if (!options.skipFocusChange) {
-    yield ContentTask.spawn(gBrowser.selectedBrowser,
-                            {lastElementSelector, selector},
-                            function*({lastElementSelector, selector}) {
-      if (lastElementSelector) {
-        let lastElement = content.document.querySelector(lastElementSelector);
-        lastElement.blur();
-      }
-      let element = content.document.querySelector(selector);
-      element.focus();
-    });
-    lastElementSelector = selector;
-    info(`Moved focus to ${selector}`);
-  }
-
-  if (options.waitForSpellCheck) {
-    info("Waiting for spell check");
-    yield ContentTask.spawn(gBrowser.selectedBrowser, selector, function*(selector) {
-      let {onSpellCheck} = Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", {});
-      let element = content.document.querySelector(selector);
-      yield new Promise(resolve => onSpellCheck(element, resolve));
-      info("Spell check running");
-    });
-  }
-
-  if (options.preCheckContextMenuFn) {
-    yield options.preCheckContextMenuFn();
-    info("Completed preCheckContextMenuFn");
-  }
-
-  let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
-  yield BrowserTestUtils.synthesizeMouse(selector, options.offsetX || 0, options.offsetY || 0, {
-      type: "contextmenu",
-      button: 2,
-      shiftkey: options.shiftkey,
-      centered: options.centered
-    },
-    gBrowser.selectedBrowser);
-  yield awaitPopupShown;
-  info("Popup Shown");
-
-  if (menuItems) {
-    if (Services.prefs.getBoolPref("devtools.inspector.enabled")) {
-      let inspectItems = ["---", null,
-                          "context-inspect", true];
-      menuItems = menuItems.concat(inspectItems);
-    }
-
-    checkContextMenu(menuItems);
-  }
-
-  let awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
-
-  if (options.postCheckContextMenuFn) {
-    yield options.postCheckContextMenuFn();
-    info("Completed postCheckContextMenuFn");
-  }
-
-  contextMenu.hidePopup();
-  yield awaitPopupHidden;
-}
-
 /**
  * Selects the text of the element that matches the provided `selector`
  *
  * @param {String} selector
  *        A selector passed to querySelector to find
  *        the element that will be referenced.
  */
 function* selectText(selector) {
rename from browser/base/content/test/general/test_contextmenu_input.html
rename to browser/base/content/test/general/browser_contextmenu_input.js
--- a/browser/base/content/test/general/test_contextmenu_input.html
+++ b/browser/base/content/test/general/browser_contextmenu_input.js
@@ -1,364 +1,303 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Tests for browser context menu</title>
-  <script type="text/javascript" src="/MochiKit/packed.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-Browser context menu tests for input.
-<p id="display"></p>
+"use strict";
 
-<div id="content">
-</div>
+let contextMenu;
+add_task(function* test_setup() {
+  const example_base = "http://example.com/browser/browser/base/content/test/general/";
+  const url = example_base + "subtst_contextmenu_input.html";
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+
+  const chrome_base = "chrome://mochitests/content/browser/browser/base/content/test/general/";
+  const contextmenu_common = chrome_base + "contextmenu_common.js";
+  Services.scriptloader.loadSubScript(contextmenu_common, this);
+});
 
-<pre id="test">
-<script type="text/javascript" src="contextmenu_common.js"></script>
-<script class="testbody" type="text/javascript">
-
-const Ci = SpecialPowers.Ci;
-
-/*
- * runTest
- *
- * Called by a popupshowing event handler. Each test checks for expected menu
- * contents, closes the popup, and finally triggers the popup on a new element
- * (thus kicking off another cycle).
- *
- */
-function runTest(testNum) {
-  ok(true, "Starting test #" + testNum);
-
-  switch (testNum) {
-    case 1:
-        openContextMenuFor(input); // Invoke context menu for next test.
-        break;
+add_task(function* test_text_input() {
+  yield test_contextmenu("#input1",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   false,
+     "---",                 null,
+     "spell-check-enabled", true]);
+});
 
-    case 2:
-        // Context menu for text input field.
-        checkContextMenu(["context-undo",        false,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      false,
-                          "---",                 null,
-                          "context-selectall",   false,
-                          "---",                 null,
-                          "spell-check-enabled", true,
-                          "---",                 null,
-                          "context-inspect",     true]);
-        closeContextMenu();
-        input.setAttribute('spellcheck', 'true');
-        // Invoke context menu for next test and wait for spell check to finish
-        openContextMenuFor(input, false, true);
-        break;
-
-    case 3:
-        var value = false;
-        // Context menu for spell-check input.
-        checkContextMenu(["context-undo",        value,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      value,
-                          "---",                 null,
-                          "context-selectall",   value,
-                          "---",                 null,
-                          "spell-check-enabled", true,
-                          "spell-dictionaries",  true,
-                              ["spell-check-dictionary-en-US", true,
-                               "---",                          null,
-                               "spell-add-dictionaries",       true], null,
-                          "---",                 null,
-                          "context-inspect",     true]);
-
-        closeContextMenu();
-        input.removeAttribute('spellcheck');
-        // Invoke context menu for next test and wait for spell check to finish
-        openContextMenuFor(inputspellwrong, false, true);
-        break;
+add_task(function* test_text_input_spellcheck() {
+  yield test_contextmenu("#input1",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   false,
+     "---",                 null,
+     "spell-check-enabled", true,
+     "spell-dictionaries",  true,
+         ["spell-check-dictionary-en-US", true,
+          "---",                          null,
+          "spell-add-dictionaries",       true], null],
+    {
+      *preCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.setAttribute("spellcheck", "true");
+        });
+      },
+      waitForSpellCheck: true,
+      *postCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.removeAttribute("spellcheck");
+        });
+      }
+    }
+  );
+});
 
-    case 4:
-        var value = false;
-        // Context menu for spell-check input with a unknwon word.
-        checkContextMenu(["*prodigality",        true, // spelling suggestion
-                          "spell-add-to-dictionary", true,
-                          "---",                 null,
-                          "context-undo",        value,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      value,
-                          "---",                 null,
-                          "context-selectall",   true,
-                          "---",                 null,
-                          "spell-check-enabled", true,
-                          "spell-dictionaries",  true,
-                              ["spell-check-dictionary-en-US", true,
-                               "---",                          null,
-                               "spell-add-dictionaries",       true], null,
-                          "---",                 null,
-                          "context-inspect",     true]);
-
-        closeContextMenu();
-        // Invoke context menu for next test and wait for spell check to finish
-        openContextMenuFor(inputspellcorrect, false, true);
-        break;
-
-    case 5:
-        var value = false;
-        // Context menu for spell-check input with a known word.
-        checkContextMenu(["context-undo",        value,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      value,
-                          "---",                 null,
-                          "context-selectall",   true,
-                          "---",                 null,
-                          "spell-check-enabled", true,
-                          "spell-dictionaries",  true,
-                              ["spell-check-dictionary-en-US", true,
-                               "---",                          null,
-                               "spell-add-dictionaries",       true], null,
-                          "---",                 null,
-                          "context-inspect",     true]);
+add_task(function* test_text_input_spellcheckwrong() {
+  yield test_contextmenu("#input2",
+    ["*prodigality",        true, // spelling suggestion
+     "spell-add-to-dictionary", true,
+     "---",                 null,
+     "context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   true,
+     "---",                 null,
+     "spell-check-enabled", true,
+     "spell-dictionaries",  true,
+         ["spell-check-dictionary-en-US", true,
+          "---",                          null,
+          "spell-add-dictionaries",       true], null],
+     {waitForSpellCheck: true}
+   );
+});
 
-        closeContextMenu();
-        input.disabled = true;
-        openContextMenuFor(input); // Invoke context menu for next test.
-        break;
-
-    case 6:
-        // Context menu for disabled input.
-        checkContextMenu(["context-undo",        false,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      false,
-                          "---",                 null,
-                          "context-selectall",   true,
-                          "---",                 null,
-                          "spell-check-enabled", true,
-                          "---",                 null,
-                          "context-inspect",     true]);
+add_task(function* test_text_input_spellcheckcorrect() {
+  yield test_contextmenu("#input3",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   true,
+     "---",                 null,
+     "spell-check-enabled", true,
+     "spell-dictionaries",  true,
+         ["spell-check-dictionary-en-US", true,
+          "---",                          null,
+          "spell-add-dictionaries",       true], null],
+     {waitForSpellCheck: true}
+  );
+});
 
-        closeContextMenu();
-        input.disabled = false;
-        input.type = 'password';
-        openContextMenuFor(input); // Invoke context menu for next test.
-        break;
-
-    case 7: // password
-        // Context menu for password input fields.
-        checkContextMenu(["context-undo",        false,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      false,
-                          "---",                 null,
-                          "context-selectall",   false,
-                          "---",                 null,
-                          "fill-login",          null,
-                            ["fill-login-no-logins",       false,
-                             "---",                        null,
-                             "fill-login-saved-passwords", true], null,
-                          "---",                 null,
-                          "context-inspect",     true]);
-
-        closeContextMenu();
-
-        input.type = 'email';
+add_task(function* test_text_input_disabled() {
+  yield test_contextmenu("#input1",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   true,
+     "---",                 null,
+     "spell-check-enabled", true],
+    {
+      skipFocusChange: true,
+      *preCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.disabled = true;
+          input.clientTop; // force layout flush
+        });
+      },
+      *postCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.disabled = false;
+        });
+      }
+    }
+  );
+});
 
-        openContextMenuFor(input); // Invoke context menu for next test.
-        break;
-
-    case 8: // email
-    case 9: // url
-    case 10: // tel
-    case 11: // type='number'
-        // Context menu for tel, email, url and number input fields.
-        checkContextMenu(["context-undo",        false,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      false,
-                          "---",                 null,
-                          "context-selectall",   false,
-                          "---",                 null,
-                          "context-inspect",     true]);
-
-        closeContextMenu();
-
-        if (testNum == 8) {
-          input.type = 'url';
-        } else if (testNum == 9) {
-          input.type = 'tel';
-        } else if (testNum == 10) {
-          input.type = 'number';
-        } else if (testNum == 11) {
-          input.type = 'date';
-        }
-
-        openContextMenuFor(input); // Invoke context menu for next test.
-        break;
+add_task(function* test_password_input() {
+  todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
+              " it should be disabled");
+  yield test_contextmenu("#input1",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   null,
+     "---",                 null,
+     "fill-login",          null,
+       ["fill-login-no-logins",       false,
+        "---",                        null,
+        "fill-login-saved-passwords", true], null],
+    {
+      skipFocusChange: true,
+      *preCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.type = "password";
+          input.clientTop; // force layout flush
+        });
+      }
+    }
+  );
+});
 
-    case 12: // type='date'
-    case 13: // type='time'
-    case 14: // type='color'
-    case 15: // type='range'
-        checkContextMenu(["context-navigation", null,
-                              ["context-back",         false,
-                               "context-forward",      false,
-                               "context-reload",       true,
-                               "context-bookmarkpage", true], null,
-                          "---",                  null,
-                          "context-savepage",     true,
-                          "---",                  null,
-                          "context-viewbgimage",  false,
-                          "context-selectall",    null,
-                          "---",                  null,
-                          "context-viewsource",   true,
-                          "context-viewinfo",     true,
-                          "---",                 null,
-                          "context-inspect",     true]);
-        closeContextMenu();
-
-        if (testNum == 12) {
-          input.type = 'time';
-        } else if (testNum == 13) {
-          input.type = 'color';
-        } else if (testNum == 14) {
-          input.type = 'range';
-        } else {
-          input.type = 'search';
+add_task(function* test_tel_email_url_number_input() {
+  todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
+              " it should be disabled");
+  for (let type of ["email", "url", "tel", "number"]) {
+    yield test_contextmenu("#input1",
+      ["context-undo",        false,
+       "---",                 null,
+       "context-cut",         true,
+       "context-copy",        true,
+       "context-paste",       null, // ignore clipboard state
+       "context-delete",      false,
+       "---",                 null,
+       "context-selectall",   null],
+      {
+        skipFocusChange: true,
+        *preCheckContextMenuFn() {
+          yield ContentTask.spawn(gBrowser.selectedBrowser, type, function*(type) {
+            let doc = content.document;
+            let input = doc.getElementById("input1");
+            input.type = type;
+            input.clientTop; // force layout flush
+          });
         }
-
-        openContextMenuFor(input);
-        break;
-
-    case 16: // type='search'
-        // Context menu for search input fields.
-        checkContextMenu(["context-undo",        false,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      false,
-                          "---",                 null,
-                          "context-selectall",   false,
-                          "---",                 null,
-                          "spell-check-enabled", true,
-                          "---",                 null,
-                          "context-inspect",     true]);
-
-        closeContextMenu();
-
-        // Add some todos to make sure all input fields got a test.
-        var todos = [ "datetime", "month", "week", "datetime-local" ];
-        todos.forEach(function(type) {
-          input.type = type;
-          todo_is(input.type, type, "TODO: add test for " + type + " input fields");
-        });
+      }
+    );
+  }
+});
 
-        input.type = 'text';
-        input.readOnly = true;
-        openContextMenuFor(input);
-        break;
-
-    case 17:
-        // Context menu for a read-only input.
-        checkContextMenu(["context-undo",        false,
-                          "---",                 null,
-                          "context-cut",         true,
-                          "context-copy",        true,
-                          "context-paste",       null, // ignore clipboard state
-                          "context-delete",      false,
-                          "---",                 null,
-                          "context-selectall",   false,
-                          "---",                 null,
-                          "context-inspect",     true]);
-        closeContextMenu();
-
-        // Clean-up.
-        subwindow.close();
-        SimpleTest.finish();
-        return;
-
-    default:
-        ok(false, "Unexpected invocation of test #" + testNum);
-        subwindow.close();
-        SimpleTest.finish();
-        return;
+add_task(function* test_date_time_color_range_input() {
+  for (let type of ["date", "time", "color", "range"]) {
+    yield test_contextmenu("#input1",
+      ["context-navigation", null,
+           ["context-back",         false,
+            "context-forward",      false,
+            "context-reload",       true,
+            "context-bookmarkpage", true], null,
+       "---",                  null,
+       "context-savepage",     true,
+       "---",                  null,
+       "context-viewbgimage",  false,
+       "context-selectall",    null,
+       "---",                  null,
+       "context-viewsource",   true,
+       "context-viewinfo",     true],
+      {
+        skipFocusChange: true,
+        *preCheckContextMenuFn() {
+          yield ContentTask.spawn(gBrowser.selectedBrowser, type, function*(type) {
+            let doc = content.document;
+            let input = doc.getElementById("input1");
+            input.type = type;
+            input.clientTop; // force layout flush
+          });
+        }
+      }
+    );
   }
-
-}
-
-
-var gTestNum = 1;
-var subwindow, chromeWin, contextMenu;
-var input, inputspellwrong, inputspellcorrect;
+});
 
-function startTest() {
-    chromeWin = SpecialPowers.wrap(subwindow)
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow)
-                    .QueryInterface(Ci.nsIDOMChromeWindow);
-    contextMenu = chromeWin.document.getElementById("contentAreaContextMenu");
-    ok(contextMenu, "Got context menu XUL");
-
-    if (chromeWin.document.getElementById("Browser:Stop").getAttribute("disabled") != "true") {
-      SimpleTest.executeSoon(startTest);
-      return;
+add_task(function* test_search_input() {
+  todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
+              " it should be disabled");
+  yield test_contextmenu("#input1",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   null,
+     "---",                 null,
+     "spell-check-enabled", true],
+    {
+      skipFocusChange: true,
+      *preCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.type = "search";
+          input.clientTop; // force layout flush
+        });
+      }
     }
-
-    var inputs = subwindow.document.getElementsByTagName('input');
-    input = inputs[0];
-    inputspellwrong = inputs[1];
-    inputspellcorrect = inputs[2];
-
-    contextMenu.addEventListener("popupshown", function() { runTest(++gTestNum); }, false);
-    runTest(1);
-}
+  );
+});
 
-// We open this in a separate window, because the Mochitests run inside a frame.
-// The frame causes an extra menu item, and prevents running the test
-// standalone (ie, clicking the test name in the Mochitest window) to see
-// success/failure messages.
-var painted = false, loaded = false;
+add_task(function* test_datetime_month_week_datetimelocal_input_todos() {
+  for (let type of ["datetime", "month", "week", "datetime-local"]) {
+    let returnedType = yield ContentTask.spawn(gBrowser.selectedBrowser, type, function*(type) {
+      let doc = content.document;
+      let input = doc.getElementById("input1");
+      input.type = type;
+      input.clientTop; // force layout flush
+      return input.type;
+    });
+    todo_is(returnedType, type, `TODO: add test for ${type} input fields`);
+  }
+});
 
-function waitForEvents(event)
-{
-  if (event.type == "MozAfterPaint")
-    painted = true;
-  else if (event.type == "load")
-    loaded = true;
-  if (painted && loaded) {
-    subwindow.removeEventListener("MozAfterPaint", waitForEvents, false);
-    subwindow.onload = null;
-    SimpleTest.waitForFocus(startTest, subwindow);
-  }
-}
+add_task(function* test_text_input_readonly() {
+  todo(false, "context-selectall is enabled on osx-e10s, and windows when" +
+              " it should be disabled");
+  todo(false, "spell-check should not be enabled for input[readonly]. see bug 1246296");
+  yield test_contextmenu("#input1",
+    ["context-undo",        false,
+     "---",                 null,
+     "context-cut",         true,
+     "context-copy",        true,
+     "context-paste",       null, // ignore clipboard state
+     "context-delete",      false,
+     "---",                 null,
+     "context-selectall",   null,
+     "---",                 null,
+     "spell-check-enabled", true],
+    {
+      skipFocusChange: true,
+      *preCheckContextMenuFn() {
+        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+          let doc = content.document;
+          let input = doc.getElementById("input1");
+          input.type = "text";
+          input.readonly = true;
+          input.clientTop; // force layout flush
+        });
+      }
+    }
+  );
+});
 
-var subwindow = window.open("data:text/html,<!DOCTYPE html><input><input spellcheck='true' value='prodkjfgigrty'><input spellcheck='true' value='foo'><input readonly spellcheck='false'>", "contextmenu-subtext", "width=600,height=700");
-subwindow.addEventListener("MozAfterPaint", waitForEvents, false);
-subwindow.onload = waitForEvents;
-
-SimpleTest.waitForExplicitFinish();
-</script>
-</pre>
-</body>
-</html>
+add_task(function* test_cleanup() {
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
--- a/browser/base/content/test/general/contextmenu_common.js
+++ b/browser/base/content/test/general/contextmenu_common.js
@@ -211,8 +211,106 @@ function checkMenu(menu, expectedItems, 
             }
         } else {
             checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, i);
         }
     }
     // Could find unexpected extra items at the end...
     is(actualItems.length, expectedItems.length, "checking expected number of menu entries");
 }
+
+let lastElementSelector = null;
+/**
+ * Right-clicks on the element that matches `selector` and checks the
+ * context menu that appears against the `menuItems` array.
+ *
+ * @param {String} selector
+ *        A selector passed to querySelector to find
+ *        the element that will be referenced.
+ * @param {Array} menuItems
+ *        An array of menuitem ids and their associated enabled state. A state
+ *        of null means that it will be ignored. Ids of '---' are used for
+ *        menuseparators.
+ * @param {Object} options, optional
+ *        skipFocusChange: don't move focus to the element before test, useful
+ *                         if you want to delay spell-check initialization
+ *        offsetX: horizontal mouse offset from the top-left corner of
+ *                 the element, optional
+ *        offsetY: vertical mouse offset from the top-left corner of the
+ *                 element, optional
+ *        centered: if true, mouse position is centered in element, defaults
+ *                  to true if offsetX and offsetY are not provided
+ *        waitForSpellCheck: wait until spellcheck is initialized before
+ *                           starting test
+ *        preCheckContextMenuFn: callback to run before opening menu
+ *        postCheckContextMenuFn: callback to run after opening menu
+ * @return {Promise} resolved after the test finishes
+ */
+function* test_contextmenu(selector, menuItems, options={}) {
+  contextMenu = document.getElementById("contentAreaContextMenu");
+  is(contextMenu.state, "closed", "checking if popup is closed");
+
+  // Default to centered if no positioning is defined.
+  if (!options.offsetX && !options.offsetY) {
+    options.centered = true;
+  }
+
+  if (!options.skipFocusChange) {
+    yield ContentTask.spawn(gBrowser.selectedBrowser,
+                            {lastElementSelector, selector},
+                            function*({lastElementSelector, selector}) {
+      if (lastElementSelector) {
+        let lastElement = content.document.querySelector(lastElementSelector);
+        lastElement.blur();
+      }
+      let element = content.document.querySelector(selector);
+      element.focus();
+    });
+    lastElementSelector = selector;
+    info(`Moved focus to ${selector}`);
+  }
+
+  if (options.preCheckContextMenuFn) {
+    yield options.preCheckContextMenuFn();
+    info("Completed preCheckContextMenuFn");
+  }
+
+  if (options.waitForSpellCheck) {
+    info("Waiting for spell check");
+    yield ContentTask.spawn(gBrowser.selectedBrowser, selector, function*(selector) {
+      let {onSpellCheck} = Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", {});
+      let element = content.document.querySelector(selector);
+      yield new Promise(resolve => onSpellCheck(element, resolve));
+      info("Spell check running");
+    });
+  }
+
+  let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
+  yield BrowserTestUtils.synthesizeMouse(selector, options.offsetX || 0, options.offsetY || 0, {
+      type: "contextmenu",
+      button: 2,
+      shiftkey: options.shiftkey,
+      centered: options.centered
+    },
+    gBrowser.selectedBrowser);
+  yield awaitPopupShown;
+  info("Popup Shown");
+
+  if (menuItems) {
+    if (Services.prefs.getBoolPref("devtools.inspector.enabled")) {
+      let inspectItems = ["---", null,
+                          "context-inspect", true];
+      menuItems = menuItems.concat(inspectItems);
+    }
+
+    checkContextMenu(menuItems);
+  }
+
+  let awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden");
+
+  if (options.postCheckContextMenuFn) {
+    yield options.postCheckContextMenuFn();
+    info("Completed postCheckContextMenuFn");
+  }
+
+  contextMenu.hidePopup();
+  yield awaitPopupHidden;
+}
--- a/browser/base/content/test/general/mochitest.ini
+++ b/browser/base/content/test/general/mochitest.ini
@@ -23,16 +23,14 @@ support-files =
   offlineEvent.cacheManifest
   offlineEvent.cacheManifest^headers^
   offlineEvent.html
   subtst_contextmenu.html
   video.ogg
 
 [test_bug364677.html]
 [test_bug395533.html]
-[test_contextmenu_input.html]
-skip-if = toolkit == "gtk2" || toolkit == "gtk3" || e10s # disabled on Linux due to bug 513558
 [test_feed_discovery.html]
 skip-if = e10s
 [test_offlineNotification.html]
 skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
 [test_offline_gzip.html]
 skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/subtst_contextmenu_input.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Subtest for browser context menu</title>
+</head>
+<body>
+  Browser context menu subtest.
+  <input id='input1'>
+  <input id='input2' spellcheck='true' value='prodkjfgigrty'>
+  <input id='input3' spellcheck='true' value='foo'>
+  <input id='input4' readonly spellcheck='false'>
+</body>
+</html>