зеркало из https://github.com/mozilla/gecko-dev.git
Bug 966424 - Intermittent browser_bug765105_background_image_tooltip.js; r=jwalker
This commit is contained in:
Родитель
06e078cf79
Коммит
07a92094c4
|
@ -75,12 +75,14 @@ function selectDiv() {
|
|||
}
|
||||
|
||||
function testTransformDimension() {
|
||||
let deferred = promise.defer();
|
||||
info("Testing css transform tooltip dimensions");
|
||||
return Task.spawn(function*() {
|
||||
let tooltip = ruleView.previewTooltip;
|
||||
let panel = tooltip.panel;
|
||||
|
||||
let {valueSpan} = getRuleViewProperty("transform");
|
||||
showTooltipOn(ruleView.previewTooltip, valueSpan, () => {
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
info("Testing css transform tooltip dimensions");
|
||||
let {valueSpan} = getRuleViewProperty("transform");
|
||||
|
||||
yield assertTooltipShownOn(tooltip, valueSpan);
|
||||
|
||||
// Let's not test for a specific size, but instead let's make sure it's at
|
||||
// least as big as the preview canvas
|
||||
|
@ -92,22 +94,23 @@ function testTransformDimension() {
|
|||
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");
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
deferred.resolve();
|
||||
let onHidden = tooltip.once("hidden");
|
||||
tooltip.hide();
|
||||
yield onHidden;
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testImageDimension() {
|
||||
let deferred = promise.defer();
|
||||
info("Testing background-image tooltip dimensions");
|
||||
return Task.spawn(function*() {
|
||||
info("Testing background-image tooltip dimensions");
|
||||
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
let tooltip = ruleView.previewTooltip;
|
||||
let panel = tooltip.panel;
|
||||
|
||||
showTooltipOn(ruleView.previewTooltip, uriSpan, () => {
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
|
||||
yield assertTooltipShownOn(tooltip, uriSpan);
|
||||
|
||||
// Let's not test for a specific size, but instead let's make sure it's at
|
||||
// least as big as the image
|
||||
|
@ -119,22 +122,24 @@ function testImageDimension() {
|
|||
ok(panelRect.height >= imageRect.height,
|
||||
"The panel is high enough to show the image");
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
deferred.resolve();
|
||||
let onHidden = tooltip.once("hidden");
|
||||
tooltip.hide();
|
||||
yield onHidden;
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testPickerDimension() {
|
||||
let deferred = promise.defer();
|
||||
info("Testing color-picker tooltip dimensions");
|
||||
return Task.spawn(function*() {
|
||||
info("Testing color-picker tooltip dimensions");
|
||||
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
let swatch = valueSpan.querySelector(".ruleview-colorswatch");
|
||||
let cPicker = ruleView.colorPicker;
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
let swatch = valueSpan.querySelector(".ruleview-colorswatch");
|
||||
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
|
||||
// make sure the tooltip is at least as big as that
|
||||
let w = cPicker.tooltip.panel.querySelector("iframe").width;
|
||||
|
@ -144,21 +149,43 @@ function testPickerDimension() {
|
|||
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");
|
||||
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
cPicker.hide();
|
||||
deferred.resolve();
|
||||
yield onHidden;
|
||||
});
|
||||
swatch.click();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function showTooltipOn(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);
|
||||
/**
|
||||
* @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 and content has been inserted");
|
||||
|
||||
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) {
|
||||
|
|
|
@ -110,7 +110,7 @@ MarkupView.prototype = {
|
|||
_initTooltips: function() {
|
||||
this.tooltip = new Tooltip(this._inspector.panelDoc);
|
||||
this.tooltip.startTogglingOnHover(this._elt,
|
||||
this._buildTooltipContent.bind(this));
|
||||
this._isImagePreviewTarget.bind(this));
|
||||
},
|
||||
|
||||
_initHighlighter: function() {
|
||||
|
@ -232,7 +232,15 @@ MarkupView.prototype = {
|
|||
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
|
||||
// and ask it if the tooltip should be shown
|
||||
let parent = target, container;
|
||||
|
@ -247,7 +255,7 @@ MarkupView.prototype = {
|
|||
if (container) {
|
||||
// With the newly found container, delegate the tooltip content creation
|
||||
// and decision to show or not the tooltip
|
||||
return container._buildTooltipContent(target, this.tooltip);
|
||||
return container._isImagePreviewTarget(target, this.tooltip);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1271,6 +1279,13 @@ 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() {
|
||||
if (this.isPreviewable()) {
|
||||
// Get the image data for later so that when the user actually hovers over
|
||||
|
@ -1297,6 +1312,27 @@ 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() {
|
||||
// We need to send again a request to gettooltipData even if one was sent for
|
||||
// the tooltip, because we want the full-size image
|
||||
|
@ -1307,17 +1343,6 @@ 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
|
||||
* will set this attribute for the MarkupContainer.
|
||||
|
|
|
@ -88,7 +88,7 @@ function testImageTooltip(index) {
|
|||
target = container.editor.getAttributeElement("src");
|
||||
}
|
||||
|
||||
assertTooltipShownOn(target, () => {
|
||||
assertTooltipShownOn(target).then(() => {
|
||||
let images = markup.tooltip.panel.getElementsByTagName("image");
|
||||
is(images.length, 1,
|
||||
"Tooltip for [" + TEST_NODES[index].selector + "] contains an image");
|
||||
|
@ -97,7 +97,6 @@ function testImageTooltip(index) {
|
|||
is(label.textContent, TEST_NODES[index].size,
|
||||
"Tooltip label for [" + TEST_NODES[index].selector + "] displays the right image size")
|
||||
|
||||
markup.tooltip.hide();
|
||||
testImageTooltip(index + 1);
|
||||
});
|
||||
}
|
||||
|
@ -117,22 +116,10 @@ function compareImageData(img, imgData) {
|
|||
}
|
||||
|
||||
function assertTooltipShownOn(element, cb) {
|
||||
// If there is indeed a show-on-hover on element, the xul panel will be shown
|
||||
markup.tooltip.panel.addEventListener("popupshown", function shown() {
|
||||
markup.tooltip.panel.removeEventListener("popupshown", shown, true);
|
||||
return Task.spawn(function*() {
|
||||
info("Is the element a valid hover target");
|
||||
|
||||
// Poll until the image gets loaded in the tooltip. This is required because
|
||||
// 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);
|
||||
let isValid = yield markup.tooltip.isValidHoverTarget(element);
|
||||
ok(isValid, "The element is a valid hover target for the image tooltip");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -59,16 +59,17 @@ function test() {
|
|||
});
|
||||
}
|
||||
|
||||
function showTooltipOn(aTooltip, aTarget) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
aTooltip.panel.addEventListener("popupshown", function onEvent() {
|
||||
aTooltip.panel.removeEventListener("popupshown", onEvent, true);
|
||||
deferred.resolve(aTooltip);
|
||||
}, true);
|
||||
|
||||
aTooltip._showOnHover(aTarget);
|
||||
return deferred.promise;
|
||||
/**
|
||||
* @return a promise that resolves when the tooltip is shown
|
||||
*/
|
||||
function showTooltipOn(tooltip, element) {
|
||||
return Task.spawn(function*() {
|
||||
let isTarget = yield tooltip.isValidHoverTarget(element);
|
||||
let onShown = tooltip.once("shown");
|
||||
tooltip.show();
|
||||
yield onShown;
|
||||
return tooltip;
|
||||
});
|
||||
}
|
||||
|
||||
aDebuggee.performRequests();
|
||||
|
|
|
@ -392,19 +392,34 @@ Tooltip.prototype = {
|
|||
this.hide();
|
||||
this._lastHovered = event.target;
|
||||
setNamedTimeout(this.uid, this._showDelay, () => {
|
||||
this._showOnHover(event.target);
|
||||
this.isValidHoverTarget(event.target).then(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 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) {
|
||||
res.then(show);
|
||||
} else if (res) {
|
||||
show(res);
|
||||
return res.then(arg => {
|
||||
return arg instanceof Ci.nsIDOMNode ? arg : target;
|
||||
}, () => {
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
return res ? promise.resolve(res) : promise.reject(false);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -620,42 +635,44 @@ Tooltip.prototype = {
|
|||
* a number here
|
||||
*/
|
||||
setImageContent: function(imageUrl, options={}) {
|
||||
if (imageUrl) {
|
||||
// Main container
|
||||
let vbox = this.doc.createElement("vbox");
|
||||
vbox.setAttribute("align", "center");
|
||||
|
||||
// Display the image
|
||||
let image = this.doc.createElement("image");
|
||||
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(label);
|
||||
|
||||
this.content = vbox;
|
||||
if (!imageUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Main container
|
||||
let vbox = this.doc.createElement("vbox");
|
||||
vbox.setAttribute("align", "center");
|
||||
|
||||
// Display the image
|
||||
let image = this.doc.createElement("image");
|
||||
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(label);
|
||||
|
||||
this.content = vbox;
|
||||
},
|
||||
|
||||
_getImageDimensionLabel: (w, h) => w + " x " + h,
|
||||
|
|
|
@ -1122,7 +1122,7 @@ CssRuleView.prototype = {
|
|||
// Test for css transform
|
||||
if (property && property.name === "transform") {
|
||||
this.previewTooltip.setCssTransformContent(property.value, this.pageStyle,
|
||||
this._viewedElement).then(def.resolve);
|
||||
this._viewedElement).then(def.resolve, def.reject);
|
||||
hasTooltip = true;
|
||||
}
|
||||
|
||||
|
@ -1163,11 +1163,11 @@ CssRuleView.prototype = {
|
|||
hasTooltip = true;
|
||||
}
|
||||
|
||||
if (hasTooltip) {
|
||||
if (!hasTooltip) {
|
||||
def.reject();
|
||||
} else if (this.colorPicker.tooltip.isShown()) {
|
||||
this.colorPicker.revert();
|
||||
this.colorPicker.hide();
|
||||
} else {
|
||||
def.reject();
|
||||
}
|
||||
|
||||
return def.promise;
|
||||
|
|
|
@ -52,56 +52,43 @@ function endTests() {
|
|||
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 testRuleView() {
|
||||
info("Testing font-family tooltips in the rule view");
|
||||
Task.spawn(function*() {
|
||||
info("Testing font-family tooltips in the rule view");
|
||||
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.previewTooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.previewTooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
|
||||
// Get the font family property inside the rule view
|
||||
let {valueSpan} = getRuleViewProperty("font-family");
|
||||
// Get the font family property inside the rule view
|
||||
let {valueSpan} = getRuleViewProperty("font-family");
|
||||
|
||||
// And verify that the tooltip gets shown on this property
|
||||
assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
|
||||
|
||||
// And verify that the tooltip gets shown on this property
|
||||
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
|
||||
testComputedView();
|
||||
});
|
||||
}).then(testComputedView);
|
||||
}
|
||||
|
||||
function testComputedView() {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
Task.spawn(function*() {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("font-family");
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("font-family");
|
||||
|
||||
assertTooltipShownOn(computedView.tooltip, valueSpan);
|
||||
|
||||
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
|
||||
|
||||
computedView.tooltip.hide();
|
||||
|
||||
endTests();
|
||||
});
|
||||
}).then(endTests);
|
||||
}
|
||||
|
||||
function getRuleViewProperty(name) {
|
||||
|
|
|
@ -50,60 +50,48 @@ function endTests() {
|
|||
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 testRuleView() {
|
||||
info("Testing font-family tooltips in the rule view");
|
||||
Task.spawn(function*() {
|
||||
info("Testing font-family tooltips in the rule view");
|
||||
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.previewTooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.previewTooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
|
||||
// Get the computed font family property inside the font rule view
|
||||
let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
|
||||
let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
|
||||
fontExpander.click();
|
||||
// Get the computed font family property inside the font rule view
|
||||
let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
|
||||
let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
|
||||
fontExpander.click();
|
||||
|
||||
let {valueSpan} = getRuleViewProperty("font-family");
|
||||
let {valueSpan} = getRuleViewProperty("font-family");
|
||||
|
||||
// And verify that the tooltip gets shown on this property
|
||||
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
|
||||
// And verify that the tooltip gets shown on this property
|
||||
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
|
||||
|
||||
// And that it has the right content
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
|
||||
testComputedView();
|
||||
});
|
||||
}).then(testComputedView);
|
||||
}
|
||||
|
||||
function testComputedView() {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
Task.spawn(function*() {
|
||||
info("Testing font-family tooltips in the computed view");
|
||||
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("font-family");
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("font-family");
|
||||
|
||||
yield assertTooltipShownOn(computedView.tooltip, valueSpan);
|
||||
|
||||
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
|
||||
let description = panel.getElementsByTagName("description")[0];
|
||||
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
|
||||
|
||||
computedView.tooltip.hide();
|
||||
|
||||
endTests();
|
||||
});
|
||||
}).then(endTests);
|
||||
}
|
||||
|
||||
function getRuleViewProperty(name) {
|
||||
|
|
|
@ -64,106 +64,82 @@ function endTests() {
|
|||
}
|
||||
|
||||
function testTransformTooltipOnIDSelector() {
|
||||
info("Testing that a transform tooltip appears on the #ID rule");
|
||||
Task.spawn(function*() {
|
||||
info("Testing that a transform tooltip appears on the #ID rule");
|
||||
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
ok(panel, "The XUL panel exists for the rule-view preview tooltips");
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
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
|
||||
// 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");
|
||||
ruleView.previewTooltip.hide();
|
||||
executeSoon(testTransformTooltipOnClassSelector);
|
||||
});
|
||||
}).then(testTransformTooltipOnClassSelector);
|
||||
}
|
||||
|
||||
function testTransformTooltipOnClassSelector() {
|
||||
info("Testing that a transform tooltip appears on the .class rule");
|
||||
Task.spawn(function*() {
|
||||
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
|
||||
// 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");
|
||||
ruleView.previewTooltip.hide();
|
||||
executeSoon(testTransformTooltipOnTagSelector);
|
||||
});
|
||||
}).then(testTransformTooltipOnTagSelector);
|
||||
}
|
||||
|
||||
function testTransformTooltipOnTagSelector() {
|
||||
info("Testing that a transform tooltip appears on the tag rule");
|
||||
Task.spawn(function*() {
|
||||
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
|
||||
// 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");
|
||||
ruleView.previewTooltip.hide();
|
||||
executeSoon(testTransformTooltipNotShownOnInvalidTransform);
|
||||
});
|
||||
}).then(testTransformTooltipNotShownOnInvalidTransform);
|
||||
}
|
||||
|
||||
function testTransformTooltipNotShownOnInvalidTransform() {
|
||||
info("Testing that a transform tooltip does not appear for invalid values");
|
||||
Task.spawn(function*() {
|
||||
info("Testing that a transform tooltip does not appear for invalid values");
|
||||
|
||||
let ruleEditor;
|
||||
for (let rule of ruleView._elementStyle.rules) {
|
||||
if (rule.matchedSelectors[0] === "[attr]") {
|
||||
ruleEditor = rule.editor;
|
||||
let ruleEditor;
|
||||
for (let rule of ruleView._elementStyle.rules) {
|
||||
if (rule.matchedSelectors[0] === "[attr]") {
|
||||
ruleEditor = rule.editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
|
||||
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
|
||||
|
||||
let {valueSpan} = getRuleViewProperty("[attr]", "transform");
|
||||
assertTooltipNotShownOn(ruleView.previewTooltip, valueSpan, () => {
|
||||
executeSoon(testTransformTooltipOnComputedView);
|
||||
});
|
||||
let {valueSpan} = getRuleViewProperty("[attr]", "transform");
|
||||
let isValid = yield isHoverTooltipTarget(ruleView.previewTooltip, valueSpan);
|
||||
ok(!isValid, "The tooltip did not appear on hover of an invalid transform value");
|
||||
}).then(testTransformTooltipOnComputedView);
|
||||
}
|
||||
|
||||
function testTransformTooltipOnComputedView() {
|
||||
info("Testing that a transform tooltip appears in the computed view too");
|
||||
Task.spawn(function*() {
|
||||
info("Testing that a transform tooltip appears in the computed view too");
|
||||
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("transform");
|
||||
let panel = computedView.tooltip.panel;
|
||||
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
|
||||
// now, let's just be happy with the fact that the tooltips is shown!
|
||||
ok(true, "Tooltip shown on the computed transform property");
|
||||
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);
|
||||
}).then(endTests);
|
||||
}
|
||||
|
||||
function getRule(selectorText) {
|
||||
|
|
|
@ -59,100 +59,92 @@ function endTests() {
|
|||
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() {
|
||||
info("Testing tooltips in the rule view");
|
||||
Task.spawn(function*() {
|
||||
info("Testing tooltips in the rule view");
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.previewTooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
|
||||
// Check that the rule view has a tooltip and that a XUL panel has been created
|
||||
ok(ruleView.previewTooltip, "Tooltip instance exists");
|
||||
ok(panel, "XUL panel exists");
|
||||
// Get the background-image property inside the rule view
|
||||
let {valueSpan} = getRuleViewProperty("background-image");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
|
||||
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");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].src.indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1, "The image URL seems fine");
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
|
||||
"The image URL seems fine");
|
||||
|
||||
let onUpdated = inspector.once("inspector-updated");
|
||||
inspector.selection.setNode(contentDoc.querySelector(".test-element"));
|
||||
inspector.once("inspector-updated", testDivRuleView);
|
||||
});
|
||||
yield onUpdated;
|
||||
}).then(testDivRuleView);
|
||||
}
|
||||
|
||||
function testDivRuleView() {
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
Task.spawn(function*() {
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
|
||||
// Get the background property inside the rule view
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
// Get the background property inside the rule view
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
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");
|
||||
is(images.length, 1, "Tooltip contains an image");
|
||||
ok(images[0].src.startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
|
||||
testTooltipAppearsEvenInEditMode();
|
||||
});
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
|
||||
}).then(testTooltipAppearsEvenInEditMode);
|
||||
}
|
||||
|
||||
function testTooltipAppearsEvenInEditMode() {
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
Task.spawn(function*() {
|
||||
let panel = ruleView.previewTooltip.panel;
|
||||
|
||||
// Switch one field to edit mode
|
||||
let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
|
||||
waitForEditorFocus(brace.parentNode, editor => {
|
||||
// Now try to show the tooltip
|
||||
info("Switching to edit mode in the rule view");
|
||||
let editor = yield turnToEditMode(ruleView);
|
||||
|
||||
info("Now trying to show the preview tooltip");
|
||||
let {valueSpan} = getRuleViewProperty("background");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
|
||||
is(ruleView.doc.activeElement, editor.input,
|
||||
"Tooltip was shown in edit mode, and inplace-editor still focused");
|
||||
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
|
||||
|
||||
ruleView.previewTooltip.hide();
|
||||
is(ruleView.doc.activeElement, editor.input,
|
||||
"Tooltip was shown in edit mode, and inplace-editor still focused");
|
||||
}).then(testComputedView);
|
||||
}
|
||||
|
||||
testComputedView();
|
||||
});
|
||||
});
|
||||
function turnToEditMode(ruleView) {
|
||||
let def = promise.defer();
|
||||
let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
|
||||
waitForEditorFocus(brace.parentNode, def.resolve);
|
||||
brace.click();
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
function testComputedView() {
|
||||
info("Testing tooltips in the computed view");
|
||||
Task.spawn(function*() {
|
||||
info("Testing tooltips in the computed view");
|
||||
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
inspector.sidebar.select("computedview");
|
||||
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
|
||||
let doc = computedView.styleDocument;
|
||||
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("background-image");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
let panel = computedView.tooltip.panel;
|
||||
let {valueSpan} = getComputedViewProperty("background-image");
|
||||
let uriSpan = valueSpan.querySelector(".theme-link");
|
||||
|
||||
yield assertTooltipShownOn(computedView.tooltip, uriSpan);
|
||||
|
||||
assertTooltipShownOn(computedView.tooltip, uriSpan, () => {
|
||||
let images = panel.getElementsByTagName("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");
|
||||
|
||||
computedView.tooltip.hide();
|
||||
|
||||
endTests();
|
||||
});
|
||||
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
|
||||
}).then(endTests);
|
||||
}
|
||||
|
||||
function getRuleViewProperty(name) {
|
||||
|
|
|
@ -105,24 +105,24 @@ function testColorPickerAppearsOnColorSwatchClick() {
|
|||
}
|
||||
|
||||
function testColorPickerHidesWhenImageTooltipAppears() {
|
||||
let swatch = swatches[0];
|
||||
let bgImageSpan = getRuleViewProperty("background-image").valueSpan;
|
||||
let uriSpan = bgImageSpan.querySelector(".theme-link");
|
||||
Task.spawn(function*() {
|
||||
let swatch = swatches[0];
|
||||
let bgImageSpan = getRuleViewProperty("background-image").valueSpan;
|
||||
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");
|
||||
|
||||
executeSoon(() => {
|
||||
ruleView.previewTooltip.hide();
|
||||
testPressingEscapeRevertsChanges();
|
||||
});
|
||||
});
|
||||
|
||||
swatch.click();
|
||||
}).then(testPressingEscapeRevertsChanges);
|
||||
}
|
||||
|
||||
function testPressingEscapeRevertsChanges() {
|
||||
|
|
|
@ -290,3 +290,30 @@ registerCleanupFunction(tearDown);
|
|||
|
||||
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
|
||||
* delegate 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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче