Bug 1252296 - Convert test_contextmenu_input.html to browser_contextmenu_input.html to run in e10s. r=gijs

MozReview-Commit-ID: gyAnGiiDOT

--HG--
rename : browser/base/content/test/general/test_contextmenu_input.html => browser/base/content/test/general/browser_contextmenu_input.js
This commit is contained in:
Jared Wein 2016-03-03 14:23:46 -05:00
Родитель ed8fb019e9
Коммит 5504d170f6
7 изменённых файлов: 379 добавлений и 465 удалений

Просмотреть файл

@ -89,6 +89,7 @@ support-files =
searchSuggestionEngine.xml
searchSuggestionEngine2.xml
subtst_contextmenu.html
subtst_contextmenu_input.html
test-mixedcontent-securityerrors.html
test_bug435035.html
test_bug462673.html
@ -294,6 +295,8 @@ skip-if = os == 'win'
[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

Просмотреть файл

@ -786,105 +786,6 @@ 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`
*

Просмотреть файл

@ -0,0 +1,249 @@
"use strict";
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);
});
add_task(function* test_text_input() {
yield test_contextmenu("#input_text",
["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]);
});
add_task(function* test_text_input_spellcheck() {
yield test_contextmenu("#input_spellcheck_no_value",
["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],
{
waitForSpellCheck: true,
// Need to dynamically add/remove the "password" type or LoginManager
// will think that the form inputs on the page are part of a login
// and will add fill-login context menu items.
*preCheckContextMenuFn() {
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
let doc = content.document;
let input = doc.getElementById("input_spellcheck_no_value");
input.setAttribute("spellcheck", "true");
input.clientTop; // force layout flush
});
},
}
);
});
add_task(function* test_text_input_spellcheckwrong() {
yield test_contextmenu("#input_spellcheck_incorrect",
["*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}
);
});
add_task(function* test_text_input_spellcheckcorrect() {
yield test_contextmenu("#input_spellcheck_correct",
["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}
);
});
add_task(function* test_text_input_disabled() {
yield test_contextmenu("#input_disabled",
["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}
);
});
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("#input_password",
["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,
// Need to dynamically add/remove the "password" type or LoginManager
// will think that the form inputs on the page are part of a login
// and will add fill-login context menu items.
*preCheckContextMenuFn() {
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
let doc = content.document;
let input = doc.getElementById("input_password");
input.type = "password";
input.clientTop; // force layout flush
});
},
*postCheckContextMenuFn() {
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
let doc = content.document;
let input = doc.getElementById("input_password");
input.type = "text";
input.clientTop; // force layout flush
});
},
}
);
});
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 selector of ["#input_email", "#input_url", "#input_tel", "#input_number"]) {
yield test_contextmenu(selector,
["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}
);
}
});
add_task(function* test_date_time_color_range_input() {
for (let selector of ["#input_date", "#input_time", "#input_color", "#input_range"]) {
yield test_contextmenu(selector,
["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}
);
}
});
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("#input_search",
["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}
);
});
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("input_" + type);
return input.type;
});
todo_is(returnedType, type, `TODO: add test for ${type} input fields`);
}
});
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("#input_readonly",
["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}
);
});
add_task(function* test_cleanup() {
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

Просмотреть файл

@ -216,3 +216,101 @@ function checkMenu(menu, expectedItems, data) {
// 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;
}

Просмотреть файл

@ -28,8 +28,6 @@ support-files =
[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]

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Subtest for browser context menu</title>
</head>
<body>
Browser context menu subtest.
<input id="input_text">
<input id="input_spellcheck_no_value">
<input id="input_spellcheck_incorrect" spellcheck="true" value="prodkjfgigrty">
<input id="input_spellcheck_correct" spellcheck="true" value="foo">
<input id="input_disabled" disabled="true">
<input id="input_password">
<input id="input_email" type="email">
<input id="input_tel" type="tel">
<input id="input_url" type="url">
<input id="input_number" type="number">
<input id="input_date" type="date">
<input id="input_time" type="time">
<input id="input_color" type="color">
<input id="input_range" type="range">
<input id="input_search" type="search">
<input id="input_datetime" type="datetime">
<input id="input_month" type="month">
<input id="input_week" type="week">
<input id="input_datetime-local" type="datetime-local">
<input id="input_readonly" readonly="true">
</body>
</html>

Просмотреть файл

@ -1,364 +0,0 @@
<!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>
<div id="content">
</div>
<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;
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;
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]);
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]);
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';
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;
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';
}
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;
}
}
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;
}
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;
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);
}
}
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>