Source code

Revision control

Copy as Markdown

Other Tools

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Tooltip Tests"
<script type="application/javascript" src="popup_shared.js"></script>
<tooltip id="thetooltip">
<label id="label" class="tooltip-label" value="This is a tooltip"/>
</tooltip>
<box id="parent" tooltiptext="Box Tooltip" style="margin: 10px">
<button id="withtext" label="Tooltip Text" tooltiptext="Button Tooltip"
style="appearance: none; padding: 0;"/>
<button id="without" label="No Tooltip" style="appearance: none; padding: 0;"/>
<!-- remove the native theme and borders to avoid some platform
specific sizing differences -->
<button id="withtooltip" label="Tooltip Element" tooltip="thetooltip"
class="plain" style="appearance: none; padding: 0;"/>
</box>
<script class="testbody" type="application/javascript">
<![CDATA[
/* import-globals-from ../widgets/popup_shared.js */
var gOriginalWidth = -1;
var gOriginalHeight = -1;
var gButton = null;
const kTooltipOffsetVertical = 10;
function runTest()
{
startPopupTests(popupTests);
}
function checkCoords(event)
{
// all but one test open the tooltip at the button location offset by 6
// in each direction. Test 5 opens it at 4 in each direction.
var mod = (gTestIndex == 5) ? 4 : 6;
var rect = gButton.getBoundingClientRect();
is(event.clientX, Math.round(rect.left + mod),
"step " + (gTestIndex + 1) + " clientX");
is(event.clientY, Math.round(rect.top + mod),
"step " + (gTestIndex + 1) + " clientY");
ok(event.screenX > 0, "step " + (gTestIndex + 1) + " screenX");
ok(event.screenY > 0, "step " + (gTestIndex + 1) + " screenY");
}
var popupTests = [
{
testname: "hover tooltiptext attribute",
events: [ "popupshowing #tooltip", "popupshown #tooltip" ],
test() {
gButton = document.getElementById("withtext");
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
}
},
{
testname: "close tooltip",
events: [ "popuphiding #tooltip", "popuphidden #tooltip",
"DOMMenuInactive #tooltip" ],
test() {
disableNonTestMouse(true);
synthesizeMouse(document.documentElement, 2, 2, { type: "mousemove" });
disableNonTestMouse(false);
}
},
{
testname: "hover inherited tooltip",
events: [ "popupshowing #tooltip", "popupshown #tooltip" ],
test() {
gButton = document.getElementById("without");
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
}
},
{
testname: "hover tooltip attribute",
events: [ "popuphiding #tooltip", "popuphidden #tooltip",
"DOMMenuInactive #tooltip",
"popupshowing thetooltip", "popupshown thetooltip" ],
test() {
gButton = document.getElementById("withtooltip");
gExpectedTriggerNode = gButton;
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
},
result(testname) {
var tooltip = document.getElementById("thetooltip");
gExpectedTriggerNode = null;
is(tooltip.triggerNode, gButton, testname + " triggerNode");
var buttonrect = document.getElementById("withtooltip").getBoundingClientRect();
var rect = tooltip.getBoundingClientRect();
var popupstyle = window.getComputedStyle(document.getElementById("thetooltip"));
is(Math.round(rect.left),
Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 6),
testname + " left position of tooltip");
is(Math.round(rect.top),
Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6 + kTooltipOffsetVertical),
testname + " top position of tooltip");
var labelrect = document.getElementById("label").getBoundingClientRect();
ok(labelrect.right < rect.right, testname + " tooltip width");
ok(labelrect.bottom < rect.bottom, testname + " tooltip height");
gOriginalWidth = rect.right - rect.left;
gOriginalHeight = rect.bottom - rect.top;
}
},
{
testname: "click to close tooltip",
events: [ "popuphiding thetooltip", "popuphidden thetooltip",
"command withtooltip", "DOMMenuInactive thetooltip" ],
test() {
gButton = document.getElementById("withtooltip");
synthesizeMouse(gButton, 2, 2, { });
},
result(testname) {
var tooltip = document.getElementById("thetooltip");
is(tooltip.triggerNode, null, testname + " triggerNode");
}
},
{
testname: "hover tooltip after size increased",
events: [ "popupshowing thetooltip", "popupshown thetooltip" ],
test() {
var label = document.getElementById("label");
label.removeAttribute("value");
label.textContent = "This is a longer tooltip than before\nIt has multiple lines\nIt is testing tooltip sizing\n";
gButton = document.getElementById("withtooltip");
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
disableNonTestMouse(false);
},
result(testname) {
var buttonrect = document.getElementById("withtooltip").getBoundingClientRect();
var rect = document.getElementById("thetooltip").getBoundingClientRect();
var popupstyle = window.getComputedStyle(document.getElementById("thetooltip"));
is(Math.round(rect.left),
Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 4),
testname + " left position of tooltip");
is(Math.round(rect.top),
Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 4 + kTooltipOffsetVertical),
testname + " top position of tooltip");
var labelrect = document.getElementById("label").getBoundingClientRect();
ok(labelrect.right < rect.right, testname + " tooltip width");
ok(labelrect.bottom < rect.bottom, testname + " tooltip height");
// make sure that the tooltip is larger than it was before by just
// checking against the original height plus an arbitrary 15 pixels
ok(gOriginalWidth + 15 < rect.right - rect.left, testname + " tooltip is wider");
ok(gOriginalHeight + 15 < rect.bottom - rect.top, testname + " tooltip is taller");
}
},
{
testname: "close tooltip with hidePopup",
events: [ "popuphiding thetooltip", "popuphidden thetooltip",
"DOMMenuInactive thetooltip" ],
test() {
document.getElementById("thetooltip").hidePopup();
},
},
{
testname: "hover tooltip after size decreased",
events: [ "popupshowing thetooltip", "popupshown thetooltip" ],
autohide: "thetooltip",
test() {
var label = document.getElementById("label");
label.value = "This is a tooltip";
label.textContent = "";
gButton = document.getElementById("withtooltip");
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
},
result(testname) {
var buttonrect = document.getElementById("withtooltip").getBoundingClientRect();
var rect = document.getElementById("thetooltip").getBoundingClientRect();
var popupstyle = window.getComputedStyle(document.getElementById("thetooltip"));
is(Math.round(rect.left),
Math.round(buttonrect.left + parseFloat(popupstyle.marginLeft) + 6),
testname + " left position of tooltip");
is(Math.round(rect.top),
Math.round(buttonrect.top + parseFloat(popupstyle.marginTop) + 6 + kTooltipOffsetVertical),
testname + " top position of tooltip");
var labelrect = document.getElementById("label").getBoundingClientRect();
ok(labelrect.right < rect.right, testname + " tooltip width");
ok(labelrect.bottom < rect.bottom, testname + " tooltip height");
is(gOriginalWidth, rect.right - rect.left, testname + " tooltip is original width");
is(gOriginalHeight, rect.bottom - rect.top, testname + " tooltip is original height");
}
},
{
testname: "hover tooltip at bottom edge of screen",
events: [ "popupshowing thetooltip", "popupshown thetooltip" ],
autohide: "thetooltip",
condition() {
// Only checking OSX here because on other platforms popups and tooltips behave the same way
// when there's not enough space to show them below (by flipping vertically)
// However, on OSX most popups are not flipped but tooltips are.
return navigator.platform.indexOf("Mac") > -1;
},
test() {
var buttonRect = document.getElementById("withtext").getBoundingClientRect();
var windowY = screen.height -
(window.mozInnerScreenY - window.screenY ) - buttonRect.bottom;
moveWindowTo(window.screenX, windowY, function() {
gButton = document.getElementById("withtooltip");
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
disableNonTestMouse(false);
});
},
result(testname) {
var buttonrect = document.getElementById("withtooltip").getBoundingClientRect();
var rect = document.getElementById("thetooltip").getBoundingClientRect();
var popupstyle = window.getComputedStyle(document.getElementById("thetooltip"));
is(Math.round(rect.y + rect.height),
Math.round(buttonrect.top + 4 - parseFloat(popupstyle.marginTop)),
testname + " position of tooltip above button");
}
},
{
testname: "open tooltip for keyclose",
events: [ "popupshowing thetooltip", "popupshown thetooltip" ],
test() {
gButton = document.getElementById("withtooltip");
gExpectedTriggerNode = gButton;
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
},
},
{
testname: "close tooltip with modifiers",
test() {
// Press all of the modifiers; the tooltip should remain open on all platforms.
synthesizeKey("KEY_Shift");
synthesizeKey("KEY_Control");
synthesizeKey("KEY_Alt");
synthesizeKey("KEY_Alt");
},
result() {
is(document.getElementById("thetooltip").state, "open", "tooltip still open after modifiers pressed")
}
},
{
testname: "close tooltip with key",
events() {
if (navigator.platform.indexOf("Win") > -1) {
return [];
}
return [ "popuphiding thetooltip", "popuphidden thetooltip",
"DOMMenuInactive thetooltip" ];
},
test() {
sendString("a");
},
result() {
let expectedState = (navigator.platform.indexOf("Win") > -1) ? "open" : "closed";
is(document.getElementById("thetooltip").state, expectedState, "tooltip closed after key pressed")
}
},
{
testname: "close tooltip with hidePopup again",
condition() { return navigator.platform.indexOf("Win") > -1; },
events: [ "popuphiding thetooltip", "popuphidden thetooltip",
"DOMMenuInactive thetooltip" ],
test() {
document.getElementById("thetooltip").hidePopup();
},
},
{
testname: "hover tooltip with long unbreakable text",
events: [ "popupshowing thetooltip", "popupshown thetooltip" ],
autohide: "thetooltip",
test() {
var label = document.getElementById("label");
label.removeAttribute("value");
label.textContent = "This_tooltip_contains_no_whitespace_and_is_longer_than_the_maximum_tooltip_width_It_should_wrap_onto_a_second_line_instead_of_being_truncated";
gButton = document.getElementById("withtooltip");
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
},
result(testname) {
var rect = document.getElementById("thetooltip").getBoundingClientRect();
var labelrect = document.getElementById("label").getBoundingClientRect();
ok(labelrect.right < rect.right, testname + " tooltip width");
ok(labelrect.bottom < rect.bottom, testname + " tooltip height");
// make sure that the tooltip contains more than one line of text, by checking
// that the original height has increased by at least 10 pixels
ok(gOriginalHeight + 10 < rect.bottom - rect.top, testname + " tooltip is wrapped");
}
},
{
testname: "anchored tooltip with no offset",
events: ["popupshowing thetooltip", "popupshown thetooltip"],
autohide: "thetooltip",
test() {
gButton = document.getElementById("withtooltip");
document
.getElementById("thetooltip")
.setAttribute(
"onpopupshowing",
"this.moveToAnchor(this.triggerNode, 'after_start');"
);
disableNonTestMouse(true);
synthesizeMouse(gButton, 2, 2, { type: "mouseover" });
synthesizeMouse(gButton, 4, 4, { type: "mousemove" });
synthesizeMouse(gButton, 6, 6, { type: "mousemove" });
disableNonTestMouse(false);
},
result(testname) {
var buttonrect = document
.getElementById("withtooltip")
.getBoundingClientRect();
var tooltip = document.getElementById("thetooltip");
var rect = tooltip.getBoundingClientRect();
var popupstyle = window.getComputedStyle(tooltip);
// Offset does not apply to anchored tooltips
is(
Math.round(rect.top),
Math.round(buttonrect.bottom + parseFloat(popupstyle.marginTop)),
testname + " top position of tooltip"
);
tooltip.removeAttribute("onpopupshowing");
},
},
];
var waitSteps = 0;
var oldx, oldy;
function moveWindowTo(x, y, callback, arg)
{
if (!waitSteps) {
oldx = window.screenX;
oldy = window.screenY;
window.moveTo(x, y);
waitSteps++;
setTimeout(moveWindowTo, 100, x, y, callback, arg);
return;
}
if (window.screenX == oldx && window.screenY == oldy) {
if (waitSteps++ > 10) {
ok(false, "Window never moved properly to " + x + "," + y);
window.arguments[0].SimpleTest.finish();
window.close();
}
setTimeout(moveWindowTo, 100, x, y, callback, arg);
}
else {
waitSteps = 0;
callback(arg);
}
}
(async function() {
let parent = window.arguments[0];
await Promise.all([
parent.SimpleTest.promiseFocus(window),
parent.SpecialPowers.pushPrefEnv({set: [["ui.tooltipOffsetVertical", kTooltipOffsetVertical]]}),
]);
runTest();
})();
]]>
</script>
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</window>