Backed out changeset 20e22a0b38f6 (bug 966424) for mochitest-bc failures.

This commit is contained in:
Ryan VanderMeulen 2014-03-12 15:23:21 -04:00
parent c0680383b8
commit 207bbe9c63
10 changed files with 264 additions and 318 deletions

View File

@ -75,14 +75,12 @@ function selectDiv() {
} }
function testTransformDimension() { function testTransformDimension() {
return Task.spawn(function*() { let deferred = promise.defer();
let tooltip = ruleView.previewTooltip; info("Testing css transform tooltip dimensions");
let panel = tooltip.panel;
info("Testing css transform tooltip dimensions"); let {valueSpan} = getRuleViewProperty("transform");
let {valueSpan} = getRuleViewProperty("transform"); showTooltipOn(ruleView.previewTooltip, valueSpan, () => {
let panel = ruleView.previewTooltip.panel;
yield assertTooltipShownOn(tooltip, valueSpan);
// Let's not test for a specific size, but instead let's make sure it's at // Let's not test for a specific size, but instead let's make sure it's at
// least as big as the preview canvas // least as big as the preview canvas
@ -94,23 +92,22 @@ function testTransformDimension() {
ok(panelRect.width >= w, "The panel is wide enough to show the canvas"); ok(panelRect.width >= w, "The panel is wide enough to show the canvas");
ok(panelRect.height >= h, "The panel is high enough to show the canvas"); ok(panelRect.height >= h, "The panel is high enough to show the canvas");
let onHidden = tooltip.once("hidden"); ruleView.previewTooltip.hide();
tooltip.hide(); deferred.resolve();
yield onHidden;
}); });
return deferred.promise;
} }
function testImageDimension() { function testImageDimension() {
return Task.spawn(function*() { let deferred = promise.defer();
info("Testing background-image tooltip dimensions"); info("Testing background-image tooltip dimensions");
let tooltip = ruleView.previewTooltip; let {valueSpan} = getRuleViewProperty("background");
let panel = tooltip.panel; let uriSpan = valueSpan.querySelector(".theme-link");
let {valueSpan} = getRuleViewProperty("background"); showTooltipOn(ruleView.previewTooltip, uriSpan, () => {
let uriSpan = valueSpan.querySelector(".theme-link"); let panel = ruleView.previewTooltip.panel;
yield assertTooltipShownOn(tooltip, uriSpan);
// Let's not test for a specific size, but instead let's make sure it's at // Let's not test for a specific size, but instead let's make sure it's at
// least as big as the image // least as big as the image
@ -122,24 +119,22 @@ function testImageDimension() {
ok(panelRect.height >= imageRect.height, ok(panelRect.height >= imageRect.height,
"The panel is high enough to show the image"); "The panel is high enough to show the image");
let onHidden = tooltip.once("hidden"); ruleView.previewTooltip.hide();
tooltip.hide(); deferred.resolve();
yield onHidden;
}); });
return deferred.promise;
} }
function testPickerDimension() { function testPickerDimension() {
return Task.spawn(function*() { let deferred = promise.defer();
info("Testing color-picker tooltip dimensions"); info("Testing color-picker tooltip dimensions");
let {valueSpan} = getRuleViewProperty("background"); let {valueSpan} = getRuleViewProperty("background");
let swatch = valueSpan.querySelector(".ruleview-colorswatch"); let swatch = valueSpan.querySelector(".ruleview-colorswatch");
let cPicker = ruleView.colorPicker; let cPicker = ruleView.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
cPicker.tooltip.once("shown", () => {
// The colorpicker spectrum's iframe has a fixed width height, so let's // The colorpicker spectrum's iframe has a fixed width height, so let's
// make sure the tooltip is at least as big as that // make sure the tooltip is at least as big as that
let w = cPicker.tooltip.panel.querySelector("iframe").width; let w = cPicker.tooltip.panel.querySelector("iframe").width;
@ -149,43 +144,21 @@ function testPickerDimension() {
ok(panelRect.width >= w, "The panel is wide enough to show the picker"); ok(panelRect.width >= w, "The panel is wide enough to show the picker");
ok(panelRect.height >= h, "The panel is high enough to show the picker"); ok(panelRect.height >= h, "The panel is high enough to show the picker");
let onHidden = cPicker.tooltip.once("hidden");
cPicker.hide(); cPicker.hide();
yield onHidden; deferred.resolve();
}); });
swatch.click();
return deferred.promise;
} }
/** function showTooltipOn(tooltip, element, cb) {
* @return a promise that resolves when the tooltip is shown // If there is indeed a show-on-hover on element, the xul panel will be shown
*/ tooltip.panel.addEventListener("popupshown", function shown() {
function assertTooltipShownOn(tooltip, element) { tooltip.panel.removeEventListener("popupshown", shown, true);
return Task.spawn(function*() { cb();
let isTarget = yield isHoverTooltipTarget(tooltip, element); }, true);
ok(isTarget, "The element is a tooltip target and content has been inserted"); tooltip._showOnHover(element);
info("Showing the tooltip now that content has been inserted by isValidHoverTarget");
let onShown = tooltip.once("shown");
tooltip.show();
yield onShown;
});
}
/**
* Given a tooltip object instance (see Tooltip.js), checks if it is set to
* toggle and hover and if so, checks if the given target is a valid hover target.
* This won't actually show the tooltip (the less we interact with XUL panels
* during test runs, the better).
* @return a promise that resolves when the answer is known. Also, this will
* delete to a function in the rule-view which will insert content into the
* tooltip
*/
function isHoverTooltipTarget(tooltip, target) {
if (!tooltip._basedNode || !tooltip.panel) {
return promise.reject(new Error("The tooltip passed isn't set to toggle on hover or is not a tooltip"));
}
// The tooltip delegates to a user defined cb that inserts content in the tooltip
// when calling isValidHoverTarget
return tooltip.isValidHoverTarget(target);
} }
function getRuleViewProperty(name) { function getRuleViewProperty(name) {

View File

@ -110,7 +110,7 @@ MarkupView.prototype = {
_initTooltips: function() { _initTooltips: function() {
this.tooltip = new Tooltip(this._inspector.panelDoc); this.tooltip = new Tooltip(this._inspector.panelDoc);
this.tooltip.startTogglingOnHover(this._elt, this.tooltip.startTogglingOnHover(this._elt,
this._isImagePreviewTarget.bind(this)); this._buildTooltipContent.bind(this));
}, },
_initHighlighter: function() { _initHighlighter: function() {
@ -232,15 +232,7 @@ MarkupView.prototype = {
updateChildren(documentElement); updateChildren(documentElement);
}, },
/** _buildTooltipContent: function(target) {
* Executed when the mouse hovers over a target in the markup-view and is used
* to decide whether this target should be used to display an image preview
* tooltip.
* Delegates the actual decision to the corresponding MarkupContainer instance
* if one is found.
* @return the promise returned by MarkupContainer._isImagePreviewTarget
*/
_isImagePreviewTarget: function(target) {
// From the target passed here, let's find the parent MarkupContainer // From the target passed here, let's find the parent MarkupContainer
// and ask it if the tooltip should be shown // and ask it if the tooltip should be shown
let parent = target, container; let parent = target, container;
@ -255,7 +247,7 @@ MarkupView.prototype = {
if (container) { if (container) {
// With the newly found container, delegate the tooltip content creation // With the newly found container, delegate the tooltip content creation
// and decision to show or not the tooltip // and decision to show or not the tooltip
return container._isImagePreviewTarget(target, this.tooltip); return container._buildTooltipContent(target, this.tooltip);
} }
}, },
@ -1273,13 +1265,6 @@ MarkupContainer.prototype = {
} }
}, },
/**
* If the node is an image or canvas (@see isPreviewable), then get the
* image data uri from the server so that it can then later be previewed in
* a tooltip if needed.
* Stores a promise in this.tooltipData.data that resolves when the data has
* been retrieved
*/
_prepareImagePreview: function() { _prepareImagePreview: function() {
if (this.isPreviewable()) { if (this.isPreviewable()) {
// Get the image data for later so that when the user actually hovers over // Get the image data for later so that when the user actually hovers over
@ -1306,27 +1291,6 @@ MarkupContainer.prototype = {
} }
}, },
/**
* Executed by MarkupView._isImagePreviewTarget which is itself called when the
* mouse hovers over a target in the markup-view.
* Checks if the target is indeed something we want to have an image tooltip
* preview over and, if so, inserts content into the tooltip.
* @return a promise that resolves when the content has been inserted or
* rejects if no preview is required. This promise is then used by Tooltip.js
* to decide if/when to show the tooltip
*/
_isImagePreviewTarget: function(target, tooltip) {
if (!this.tooltipData || this.tooltipData.target !== target) {
return promise.reject();
}
return this.tooltipData.data.then(({data, size}) => {
tooltip.setImageContent(data, size);
}, () => {
tooltip.setBrokenImageContent();
});
},
copyImageDataUri: function() { copyImageDataUri: function() {
// We need to send again a request to gettooltipData even if one was sent for // We need to send again a request to gettooltipData even if one was sent for
// the tooltip, because we want the full-size image // the tooltip, because we want the full-size image
@ -1337,6 +1301,17 @@ MarkupContainer.prototype = {
}); });
}, },
_buildTooltipContent: function(target, tooltip) {
if (this.tooltipData && target === this.tooltipData.target) {
this.tooltipData.data.then(({data, size}) => {
tooltip.setImageContent(data, size);
}, () => {
tooltip.setBrokenImageContent();
});
return true;
}
},
/** /**
* True if the current node has children. The MarkupView * True if the current node has children. The MarkupView
* will set this attribute for the MarkupContainer. * will set this attribute for the MarkupContainer.

View File

@ -88,7 +88,7 @@ function testImageTooltip(index) {
target = container.editor.getAttributeElement("src"); target = container.editor.getAttributeElement("src");
} }
assertTooltipShownOn(target).then(() => { assertTooltipShownOn(target, () => {
let images = markup.tooltip.panel.getElementsByTagName("image"); let images = markup.tooltip.panel.getElementsByTagName("image");
is(images.length, 1, is(images.length, 1,
"Tooltip for [" + TEST_NODES[index].selector + "] contains an image"); "Tooltip for [" + TEST_NODES[index].selector + "] contains an image");
@ -97,6 +97,7 @@ function testImageTooltip(index) {
is(label.textContent, TEST_NODES[index].size, is(label.textContent, TEST_NODES[index].size,
"Tooltip label for [" + TEST_NODES[index].selector + "] displays the right image size") "Tooltip label for [" + TEST_NODES[index].selector + "] displays the right image size")
markup.tooltip.hide();
testImageTooltip(index + 1); testImageTooltip(index + 1);
}); });
} }
@ -116,10 +117,22 @@ function compareImageData(img, imgData) {
} }
function assertTooltipShownOn(element, cb) { function assertTooltipShownOn(element, cb) {
return Task.spawn(function*() { // If there is indeed a show-on-hover on element, the xul panel will be shown
info("Is the element a valid hover target"); markup.tooltip.panel.addEventListener("popupshown", function shown() {
markup.tooltip.panel.removeEventListener("popupshown", shown, true);
let isValid = yield markup.tooltip.isValidHoverTarget(element); // Poll until the image gets loaded in the tooltip. This is required because
ok(isValid, "The element is a valid hover target for the image tooltip"); // markup containers only load images in their associated tooltips when
}); // the image data comes back from the server. However, this test is executed
// synchronously as soon as "inspector-updated" is fired, which is before
// the data for images is known.
let hasImage = () => markup.tooltip.panel.getElementsByTagName("image").length;
let poll = setInterval(() => {
if (hasImage()) {
clearInterval(poll);
cb();
}
}, 200);
}, true);
markup.tooltip._showOnHover(element);
} }

View File

@ -59,17 +59,16 @@ function test() {
}); });
} }
/** function showTooltipOn(aTooltip, aTarget) {
* @return a promise that resolves when the tooltip is shown let deferred = promise.defer();
*/
function showTooltipOn(tooltip, element) { aTooltip.panel.addEventListener("popupshown", function onEvent() {
return Task.spawn(function*() { aTooltip.panel.removeEventListener("popupshown", onEvent, true);
let isTarget = yield tooltip.isValidHoverTarget(element); deferred.resolve(aTooltip);
let onShown = tooltip.once("shown"); }, true);
tooltip.show();
yield onShown; aTooltip._showOnHover(aTarget);
return tooltip; return deferred.promise;
});
} }
aDebuggee.performRequests(); aDebuggee.performRequests();

View File

@ -392,34 +392,19 @@ Tooltip.prototype = {
this.hide(); this.hide();
this._lastHovered = event.target; this._lastHovered = event.target;
setNamedTimeout(this.uid, this._showDelay, () => { setNamedTimeout(this.uid, this._showDelay, () => {
this.isValidHoverTarget(event.target).then(target => { this._showOnHover(event.target);
this.show(target);
});
}); });
} }
}, },
/** _showOnHover: function(target) {
* Is the given target DOMNode a valid node for toggling the tooltip on hover.
* This delegates to the user-defined _targetNodeCb callback.
* @return a promise that resolves or rejects depending if the tooltip should
* be shown or not. If it resolves, it does to the actual anchor to be used
*/
isValidHoverTarget: function(target) {
// Execute the user-defined callback which should return either true/false
// or a promise that resolves or rejects
let res = this._targetNodeCb(target, this); let res = this._targetNodeCb(target, this);
let show = arg => this.show(arg instanceof Ci.nsIDOMNode ? arg : target);
// The callback can additionally return a DOMNode to replace the anchor of
// the tooltip when shown
if (res && res.then) { if (res && res.then) {
return res.then(arg => { res.then(show);
return arg instanceof Ci.nsIDOMNode ? arg : target; } else if (res) {
}, () => { show(res);
return false;
});
} else {
return res ? promise.resolve(res) : promise.reject(false);
} }
}, },
@ -635,44 +620,42 @@ Tooltip.prototype = {
* a number here * a number here
*/ */
setImageContent: function(imageUrl, options={}) { setImageContent: function(imageUrl, options={}) {
if (!imageUrl) { if (imageUrl) {
return; // Main container
} let vbox = this.doc.createElement("vbox");
vbox.setAttribute("align", "center");
// Main container // Display the image
let vbox = this.doc.createElement("vbox"); let image = this.doc.createElement("image");
vbox.setAttribute("align", "center"); image.setAttribute("src", imageUrl);
if (options.maxDim) {
// Display the image image.style.maxWidth = options.maxDim + "px";
let image = this.doc.createElement("image"); image.style.maxHeight = options.maxDim + "px";
image.setAttribute("src", imageUrl);
if (options.maxDim) {
image.style.maxWidth = options.maxDim + "px";
image.style.maxHeight = options.maxDim + "px";
}
vbox.appendChild(image);
// Dimension label
let label = this.doc.createElement("label");
label.classList.add("devtools-tooltip-caption");
label.classList.add("theme-comment");
if (options.naturalWidth && options.naturalHeight) {
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
options.naturalHeight);
} else {
// If no dimensions were provided, load the image to get them
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
let imgObj = new this.doc.defaultView.Image();
imgObj.src = imageUrl;
imgObj.onload = () => {
imgObj.onload = null;
label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
imgObj.naturalHeight);
} }
} vbox.appendChild(image);
vbox.appendChild(label);
this.content = vbox; // Dimension label
let label = this.doc.createElement("label");
label.classList.add("devtools-tooltip-caption");
label.classList.add("theme-comment");
if (options.naturalWidth && options.naturalHeight) {
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
options.naturalHeight);
} else {
// If no dimensions were provided, load the image to get them
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
let imgObj = new this.doc.defaultView.Image();
imgObj.src = imageUrl;
imgObj.onload = () => {
imgObj.onload = null;
label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
imgObj.naturalHeight);
}
}
vbox.appendChild(label);
this.content = vbox;
}
}, },
_getImageDimensionLabel: (w, h) => w + " x " + h, _getImageDimensionLabel: (w, h) => w + " x " + h,

View File

@ -1122,7 +1122,7 @@ CssRuleView.prototype = {
// Test for css transform // Test for css transform
if (property && property.name === "transform") { if (property && property.name === "transform") {
this.previewTooltip.setCssTransformContent(property.value, this.pageStyle, this.previewTooltip.setCssTransformContent(property.value, this.pageStyle,
this._viewedElement).then(def.resolve, def.reject); this._viewedElement).then(def.resolve);
hasTooltip = true; hasTooltip = true;
} }
@ -1164,10 +1164,8 @@ CssRuleView.prototype = {
} }
if (hasTooltip) { if (hasTooltip) {
if (this.colorPicker.tooltip.isShown()) { this.colorPicker.revert();
this.colorPicker.revert(); this.colorPicker.hide();
this.colorPicker.hide();
}
} else { } else {
def.reject(); def.reject();
} }

View File

@ -64,82 +64,106 @@ function endTests() {
} }
function testTransformTooltipOnIDSelector() { function testTransformTooltipOnIDSelector() {
Task.spawn(function*() { info("Testing that a transform tooltip appears on the #ID rule");
info("Testing that a transform tooltip appears on the #ID rule");
let panel = ruleView.previewTooltip.panel; let panel = ruleView.previewTooltip.panel;
ok(panel, "The XUL panel exists for the rule-view preview tooltips"); ok(panel, "The XUL panel exists for the rule-view preview tooltips");
let {valueSpan} = getRuleViewProperty("#testElement", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let {valueSpan} = getRuleViewProperty("#testElement", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for // The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown! // now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the #ID rule"); ok(true, "Tooltip shown on the transform property of the #ID rule");
}).then(testTransformTooltipOnClassSelector); ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipOnClassSelector);
});
} }
function testTransformTooltipOnClassSelector() { function testTransformTooltipOnClassSelector() {
Task.spawn(function*() { info("Testing that a transform tooltip appears on the .class rule");
info("Testing that a transform tooltip appears on the .class rule");
let {valueSpan} = getRuleViewProperty(".test-element", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let {valueSpan} = getRuleViewProperty(".test-element", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for // The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown! // now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the .class rule"); ok(true, "Tooltip shown on the transform property of the .class rule");
}).then(testTransformTooltipOnTagSelector); ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipOnTagSelector);
});
} }
function testTransformTooltipOnTagSelector() { function testTransformTooltipOnTagSelector() {
Task.spawn(function*() { info("Testing that a transform tooltip appears on the tag rule");
info("Testing that a transform tooltip appears on the tag rule");
let {valueSpan} = getRuleViewProperty("div", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let {valueSpan} = getRuleViewProperty("div", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for // The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown! // now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the tag rule"); ok(true, "Tooltip shown on the transform property of the tag rule");
}).then(testTransformTooltipNotShownOnInvalidTransform); ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipNotShownOnInvalidTransform);
});
} }
function testTransformTooltipNotShownOnInvalidTransform() { function testTransformTooltipNotShownOnInvalidTransform() {
Task.spawn(function*() { info("Testing that a transform tooltip does not appear for invalid values");
info("Testing that a transform tooltip does not appear for invalid values");
let ruleEditor; let ruleEditor;
for (let rule of ruleView._elementStyle.rules) { for (let rule of ruleView._elementStyle.rules) {
if (rule.matchedSelectors[0] === "[attr]") { if (rule.matchedSelectors[0] === "[attr]") {
ruleEditor = rule.editor; ruleEditor = rule.editor;
}
} }
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", ""); }
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
let {valueSpan} = getRuleViewProperty("[attr]", "transform"); let {valueSpan} = getRuleViewProperty("[attr]", "transform");
let isValid = yield isHoverTooltipTarget(ruleView.previewTooltip, valueSpan); assertTooltipNotShownOn(ruleView.previewTooltip, valueSpan, () => {
ok(!isValid, "The tooltip did not appear on hover of an invalid transform value"); executeSoon(testTransformTooltipOnComputedView);
}).then(testTransformTooltipOnComputedView); });
} }
function testTransformTooltipOnComputedView() { function testTransformTooltipOnComputedView() {
Task.spawn(function*() { info("Testing that a transform tooltip appears in the computed view too");
info("Testing that a transform tooltip appears in the computed view too");
inspector.sidebar.select("computedview"); inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view; computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument; let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel; let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("transform"); let {valueSpan} = getComputedViewProperty("transform");
yield assertTooltipShownOn(computedView.tooltip, valueSpan);
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for // The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown! // now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the computed transform property"); ok(true, "Tooltip shown on the computed transform property");
}).then(endTests); computedView.tooltip.hide();
executeSoon(endTests);
});
}
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
// Run _showOnHover at stable state after the next refresh driver tick.
// This way nothing during reflow or painting should be able to
// cancel showing the popup.
element.ownerDocument.defaultView.requestAnimationFrame(() => {
executeSoon(() => { tooltip._showOnHover(element); });
});
}
function assertTooltipNotShownOn(tooltip, element, cb) {
// The only way to make sure the tooltip is not shown is try and show it, wait
// for a given amount of time, and then check if it's shown or not
tooltip._showOnHover(element);
setTimeout(() => {
ok(!tooltip.isShown(), "The tooltip did not appear on hover of the element");
cb();
}, tooltip.defaultShowDelay + 100);
} }
function getRule(selectorText) { function getRule(selectorText) {

View File

@ -59,92 +59,100 @@ function endTests() {
finish(); finish();
} }
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
tooltip._showOnHover(element);
}
function testBodyRuleView() { function testBodyRuleView() {
Task.spawn(function*() { info("Testing tooltips in the rule view");
info("Testing tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created let panel = ruleView.previewTooltip.panel;
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the background-image property inside the rule view // Check that the rule view has a tooltip and that a XUL panel has been created
let {valueSpan} = getRuleViewProperty("background-image"); ok(ruleView.previewTooltip, "Tooltip instance exists");
let uriSpan = valueSpan.querySelector(".theme-link"); ok(panel, "XUL panel exists");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
// Get the background-image property inside the rule view
let {valueSpan} = getRuleViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image"); let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image"); is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1, ok(images[0].src.indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1, "The image URL seems fine");
"The image URL seems fine");
ruleView.previewTooltip.hide();
let onUpdated = inspector.once("inspector-updated");
inspector.selection.setNode(contentDoc.querySelector(".test-element")); inspector.selection.setNode(contentDoc.querySelector(".test-element"));
yield onUpdated; inspector.once("inspector-updated", testDivRuleView);
}).then(testDivRuleView); });
} }
function testDivRuleView() { function testDivRuleView() {
Task.spawn(function*() { let panel = ruleView.previewTooltip.panel;
let panel = ruleView.previewTooltip.panel;
// Get the background property inside the rule view // Get the background property inside the rule view
let {valueSpan} = getRuleViewProperty("background"); let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link"); let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image"); let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image"); is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected"); ok(images[0].src.startsWith("data:"), "Tooltip contains a data-uri image as expected");
}).then(testTooltipAppearsEvenInEditMode);
ruleView.previewTooltip.hide();
testTooltipAppearsEvenInEditMode();
});
} }
function testTooltipAppearsEvenInEditMode() { function testTooltipAppearsEvenInEditMode() {
Task.spawn(function*() { let panel = ruleView.previewTooltip.panel;
let panel = ruleView.previewTooltip.panel;
info("Switching to edit mode in the rule view"); // Switch one field to edit mode
let editor = yield turnToEditMode(ruleView); let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
waitForEditorFocus(brace.parentNode, editor => {
info("Now trying to show the preview tooltip"); // Now try to show the tooltip
let {valueSpan} = getRuleViewProperty("background"); let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link"); let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan); assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
is(ruleView.doc.activeElement, editor.input,
"Tooltip was shown in edit mode, and inplace-editor still focused");
is(ruleView.doc.activeElement, editor.input, ruleView.previewTooltip.hide();
"Tooltip was shown in edit mode, and inplace-editor still focused");
}).then(testComputedView);
}
function turnToEditMode(ruleView) { testComputedView();
let def = promise.defer(); });
let brace = ruleView.doc.querySelector(".ruleview-ruleclose"); });
waitForEditorFocus(brace.parentNode, def.resolve);
brace.click(); brace.click();
return def.promise;
} }
function testComputedView() { function testComputedView() {
Task.spawn(function*() { info("Testing tooltips in the computed view");
info("Testing tooltips in the computed view");
inspector.sidebar.select("computedview"); inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view; computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument; let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel; let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("background-image"); let {valueSpan} = getComputedViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link"); let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(computedView.tooltip, uriSpan);
assertTooltipShownOn(computedView.tooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image"); let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image"); is(images.length, 1, "Tooltip contains an image");
ok(images[0].src.startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too"); computedView.tooltip.hide();
}).then(endTests);
endTests();
});
} }
function getRuleViewProperty(name) { function getRuleViewProperty(name) {

View File

@ -105,24 +105,24 @@ function testColorPickerAppearsOnColorSwatchClick() {
} }
function testColorPickerHidesWhenImageTooltipAppears() { function testColorPickerHidesWhenImageTooltipAppears() {
Task.spawn(function*() { let swatch = swatches[0];
let swatch = swatches[0]; let bgImageSpan = getRuleViewProperty("background-image").valueSpan;
let bgImageSpan = getRuleViewProperty("background-image").valueSpan; let uriSpan = bgImageSpan.querySelector(".theme-link");
let uriSpan = bgImageSpan.querySelector(".theme-link");
let tooltip = ruleView.colorPicker.tooltip;
info("Showing the color picker tooltip by clicking on the color swatch");
let onShown = tooltip.once("shown");
swatch.click();
yield onShown;
info("Now showing the image preview tooltip to hide the color picker");
let onHidden = tooltip.once("hidden");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
yield onHidden;
ruleView.colorPicker.tooltip.once("shown", () => {
info("The color picker is shown, now display an image tooltip to hide it");
ruleView.previewTooltip._showOnHover(uriSpan);
});
ruleView.colorPicker.tooltip.once("hidden", () => {
ok(true, "The color picker closed when the image preview tooltip appeared"); ok(true, "The color picker closed when the image preview tooltip appeared");
}).then(testPressingEscapeRevertsChanges);
executeSoon(() => {
ruleView.previewTooltip.hide();
testPressingEscapeRevertsChanges();
});
});
swatch.click();
} }
function testPressingEscapeRevertsChanges() { function testPressingEscapeRevertsChanges() {

View File

@ -280,30 +280,3 @@ registerCleanupFunction(tearDown);
waitForExplicitFinish(); waitForExplicitFinish();
/**
* @return a promise that resolves when the tooltip is shown
*/
function assertTooltipShownOn(tooltip, element) {
return Task.spawn(function*() {
let isTarget = yield isHoverTooltipTarget(tooltip, element);
ok(isTarget, "The element is a tooltip target");
});
}
/**
* Given a tooltip object instance (see Tooltip.js), checks if it is set to
* toggle and hover and if so, checks if the given target is a valid hover target.
* This won't actually show the tooltip (the less we interact with XUL panels
* during test runs, the better).
* @return a promise that resolves when the answer is known. Also, this will
* delete to a function in the rule-view which will insert content into the
* tooltip
*/
function isHoverTooltipTarget(tooltip, target) {
if (!tooltip._basedNode || !tooltip.panel) {
return promise.reject(new Error("The tooltip passed isn't set to toggle on hover or is not a tooltip"));
}
// The tooltip delegates to a user defined cb that inserts content in the tooltip
// when calling isValidHoverTarget
return tooltip.isValidHoverTarget(target);
}