Bug 782810 - add text, link, and input context menu tests. r=mbrubeck

This commit is contained in:
Jim Mathies 2013-02-19 19:51:02 -06:00
parent 98dcbfb847
commit 195c3f380f
5 changed files with 301 additions and 7 deletions

View File

@ -25,6 +25,7 @@ BROWSER_TESTS = \
browser_plugin_input_keyboard.js \
browser_context_menu_tests.js \
browser_context_menu_tests_01.html \
browser_context_menu_tests_02.html \
$(NULL)
BROWSER_TEST_RESOURCES = \

View File

@ -20,6 +20,226 @@ function debugClipFlavors(aClip)
}
}
// XXX won't work with out of process content
function emptyClipboard() {
Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard)
.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
}
// Image context menu tests
gTests.push({
desc: "text context menu",
run: function test() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
info(chromeRoot + "browser_context_menu_tests_02.html");
yield addTab(chromeRoot + "browser_context_menu_tests_02.html");
purgeEventQueue();
let win = Browser.selectedTab.browser.contentWindow;
yield hideContextUI();
////////////////////////////////////////////////////////////
// Context menu in content on selected text
// select some text
let span = win.document.getElementById("text1");
win.getSelection().selectAllChildren(span);
// invoke selection context menu
let promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, span, 85, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
// selected text context:
checkContextUIMenuItemVisibility(["context-copy",
"context-search"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
win.getSelection().removeAllRanges();
////////////////////////////////////////////////////////////
// Context menu in content on selected text that includes a link
// invoke selection with link context menu
let link = win.document.getElementById("text2-link");
win.getSelection().selectAllChildren(link);
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, link, 40, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
// selected text context:
checkContextUIMenuItemVisibility(["context-copy",
"context-search",
"context-open-in-new-tab",
"context-copy-link"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
win.getSelection().removeAllRanges();
////////////////////////////////////////////////////////////
// Context menu in content on a link
link = win.document.getElementById("text2-link");
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, link, 40, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
// selected text context:
checkContextUIMenuItemVisibility(["context-open-in-new-tab",
"context-copy-link",
"context-bookmark-link"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in input with no selection, no data on clipboard
emptyClipboard();
let input = win.document.getElementById("text3-input");
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
checkContextUIMenuItemVisibility(["context-copy",
"context-select",
"context-select-all"]);
// copy menu item should copy all text
let menuItem = document.getElementById("context-copy");
ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win);
yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error");
let string = SpecialPowers.getClipboardData("text/unicode");
ok(string, "hello, I'm sorry but I must be going.", "copy all");
emptyClipboard();
////////////////////////////////////////////////////////////
// context in input with text selection, no data on clipboard
input = win.document.getElementById("text3-input");
input.select();
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
// selected text context:
checkContextUIMenuItemVisibility(["context-copy",
"context-search"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in input with no selection, data on clipboard
SpecialPowers.clipboardCopyString("foo");
input = win.document.getElementById("text3-input");
input.select();
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
// selected text context:
checkContextUIMenuItemVisibility(["context-copy",
"context-search",
"context-paste"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in empty input, data on clipboard (paste operation)
SpecialPowers.clipboardCopyString("foo");
input = win.document.getElementById("text3-input");
input.value = "";
promise = waitForEvent(document, "popupshown");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should be visible
ok(ContextMenuUI._menuPopup._visible, "is visible");
// selected text context:
checkContextUIMenuItemVisibility(["context-paste"]);
promise = waitForEvent(document, "popuphidden");
ContextMenuUI.hide();
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
////////////////////////////////////////////////////////////
// context in empty input, no data on clipboard (??)
emptyClipboard();
input = win.document.getElementById("text3-input");
input.value = "";
promise = waitForEvent(Elements.tray, "transitionend");
sendContextMenuClickToElement(win, input, 20, 10);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
// should *not* be visible
ok(!ContextMenuUI._menuPopup._visible, "is visible");
// the test above will invoke the app bar
yield hideContextUI();
Browser.closeTab(Browser.selectedTab);
purgeEventQueue();
}
});
// Image context menu tests
gTests.push({
desc: "image context menu",
@ -31,8 +251,14 @@ gTests.push({
let win = Browser.selectedTab.browser.contentWindow;
purgeEventQueue();
yield hideContextUI();
// If we don't do this, sometimes the first sendContextMenuClick
// will trigger the app bar.
yield waitForImageLoad(win, "image01");
////////////////////////////////////////////////////////////
// Context menu options
@ -46,7 +272,10 @@ gTests.push({
ok(ContextMenuUI._menuPopup._visible, "is visible");
checkContextUIMenuItemCount(4);
checkContextUIMenuItemVisibility(["context-save-image-lib",
"context-copy-image",
"context-copy-image-loc",
"context-open-image-tab"]);
////////////////////////////////////////////////////////////
// Save to image library
@ -85,7 +314,7 @@ gTests.push({
// Copy image
let promise = waitForEvent(document, "popupshown");
sendContextMenuClick(win, 30, 30);
sendContextMenuClick(win, 20, 20);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -102,13 +331,13 @@ gTests.push({
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
let flavors = ["image/png"];
ok(clip.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard), "clip has my flavor");
ok(clip.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard), "clip has my png flavor");
////////////////////////////////////////////////////////////
// Copy image location
promise = waitForEvent(document, "popupshown");
sendContextMenuClick(win, 60, 60);
sendContextMenuClick(win, 30, 30);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
ok(ContextMenuUI._menuPopup._visible, "is visible");
@ -125,7 +354,7 @@ gTests.push({
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
let flavors = ["text/unicode"];
ok(clip.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard), "clip has my flavor");
ok(clip.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard), "clip has my text flavor");
let xfer = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
@ -142,7 +371,7 @@ gTests.push({
// Open image in new tab
promise = waitForEvent(document, "popupshown");
sendContextMenuClick(win, 60, 60);
sendContextMenuClick(win, 40, 40);
yield promise;
ok(promise && !(promise instanceof Error), "promise error");
ok(ContextMenuUI._menuPopup._visible, "is visible");

View File

@ -7,7 +7,7 @@
<body style="padding: 1px; margin: 1px;">
<div style="margin: 0; padding: 0;">
<span>
<img width="100" height="100" src="./res/image01.png" />
<img id="image01" width="100" height="100" src="./res/image01.png" />
</span>
</div>
</body>

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body style="padding: 10px; margin: 10px;">
<div style="margin: 0; padding: 5px;">
<span id="text1">hello, I'm sorry but I must be going.</span>
</div>
<div style="margin: 0; padding: 5px;">
<span id="text2"><a id="text2-link" href="#test">hello, I'm sorry but</a> I must be going.</span>
</div>
<div style="margin: 0; padding: 5px;">
<span id="text3"><input id="text3-input" value="hello, I'm sorry but I must be going." style="width:200px;"/></span>
</div>
</body>
</html>

View File

@ -32,13 +32,33 @@ function checkContextUIMenuItemCount(aCount)
is(visibleCount, aCount, "command list count");
}
function checkContextUIMenuItemVisibility(aVisibleList)
{
let errors = 0;
for (let idx = 0; idx < ContextMenuUI._commands.childNodes.length; idx++) {
let item = ContextMenuUI._commands.childNodes[idx];
if (aVisibleList.indexOf(item.id) != -1 && item.hidden) {
// item should be visible
errors++;
info("should be visible:" + item.id);
} else if (aVisibleList.indexOf(item.id) == -1 && !item.hidden) {
// item should be hidden
errors++;
info("should be hidden:" + item.id);
}
}
is(errors, 0, "context menu item list visibility");
}
/*=============================================================================
Asynchronous Metro ui helpers
=============================================================================*/
function hideContextUI()
{
purgeEventQueue();
if (ContextUI.isVisible) {
info("is visible, waiting...");
let promise = waitForEvent(Elements.tray, "transitionend");
ContextUI.dismiss();
return promise;
@ -93,6 +113,7 @@ function addTab(aUrl) {
* @returns a Promise that resolves to the received event, or to an Error
*/
function waitForEvent(aSubject, aEventName, aTimeoutMs) {
info("waitForEvent: on " + aSubject + " event: " + aEventName);
let eventDeferred = Promise.defer();
let timeoutMs = aTimeoutMs || kDefaultWait;
let timerID = setTimeout(function wfe_canceller() {
@ -189,6 +210,23 @@ function waitForCondition(aCondition, aTimeoutMs, aIntervalMs) {
return deferred.promise;
}
/*
* Waits for an image in a page to load. Wrapper around waitForCondition.
*
* @param aWindow the tab or window that contains the image.
* @param aImageId the id of the image in the page.
* @returns a Promise that resolves to true, or to an Error
*/
function waitForImageLoad(aWindow, aImageId) {
let elem = aWindow.document.getElementById(aImageId);
return waitForCondition(function () {
let request = elem.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE))
return true;
return false;
}, 5000, 100);
}
/**
* Waits a specified number of miliseconds for an observer event.
*
@ -339,6 +377,14 @@ function sendContextMenuClick(aWindow, aX, aY) {
1, Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH);
}
function sendContextMenuClickToElement(aWindow, aElement, aX, aY) {
let utils = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
let rect = aElement.getBoundingClientRect();
utils.sendMouseEventToWindow("contextmenu", rect.left + aX, rect.top + aY, 2, 1, 0, true,
1, Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH);
}
/*=============================================================================
System utilities
=============================================================================*/