Bug 1912579 - Fix intermittent comm/mail/test/browser/message-reader/browser_imageOverflow.js | The message display needs to be less than 400px wide - 832 < 400. r=tobyp
There were a bunch of issues with this test. Simplified the real code to make it more understandable (and using boolean attributes). Differential Revision: https://phabricator.services.mozilla.com/D228603 --HG-- rename : mail/test/browser/message-reader/data/Image sizing test.eml => mail/test/browser/message-reader/data/image_sizing_test.eml extra : moz-landing-system : lando
This commit is contained in:
Родитель
0208da7cda
Коммит
f2ed6688f0
|
@ -50,7 +50,10 @@ function getMessagePaneBrowser() {
|
|||
return document.getElementById("messagepane");
|
||||
}
|
||||
|
||||
function messagePaneOnResize() {
|
||||
/**
|
||||
* Handle "resize" events on the messagepane.
|
||||
*/
|
||||
async function messagePaneOnResize() {
|
||||
const doc = getMessagePaneBrowser().contentDocument;
|
||||
// Bail out if it's http content or we don't have images.
|
||||
if (doc?.URL.startsWith("http") || !doc?.images) {
|
||||
|
@ -62,22 +65,29 @@ function messagePaneOnResize() {
|
|||
window.visualViewport.width
|
||||
);
|
||||
|
||||
const adjustImg = img => {
|
||||
if (img.hasAttribute("shrinktofit")) {
|
||||
// overflowing: Whether the image is overflowing visible area.
|
||||
img.toggleAttribute("overflowing", img.naturalWidth > img.clientWidth);
|
||||
} else if (img.hasAttribute("overflowing")) {
|
||||
const isOverflowing = img.clientWidth >= availableWidth;
|
||||
img.toggleAttribute("overflowing", isOverflowing);
|
||||
img.toggleAttribute("shrinktofit", !isOverflowing);
|
||||
}
|
||||
};
|
||||
|
||||
for (const img of doc.querySelectorAll(
|
||||
"img:is([shrinktofit],[overflowing])"
|
||||
)) {
|
||||
if (!img.complete || img.closest("[href]")) {
|
||||
if (img.closest("[href]")) {
|
||||
continue;
|
||||
}
|
||||
if (img.hasAttribute("shrinktofit")) {
|
||||
// Determine if the image could be enlarged.
|
||||
img.toggleAttribute("overflowing", img.naturalWidth > img.clientWidth);
|
||||
} else if (
|
||||
img.hasAttribute("overflowing") &&
|
||||
img.clientWidth < availableWidth
|
||||
) {
|
||||
// Handle zoomed images that are no longer overflowing after a resize.
|
||||
img.removeAttribute("overflowing");
|
||||
img.setAttribute("shrinktofit", "true");
|
||||
if (!img.complete) {
|
||||
img.addEventListener("load", event => adjustImg(event.target), {
|
||||
once: true,
|
||||
});
|
||||
} else {
|
||||
adjustImg(img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,14 +145,7 @@ function contentAreaClick(aEvent) {
|
|||
|
||||
// Is it an image?
|
||||
if (target.localName == "img" && target.hasAttribute("overflowing")) {
|
||||
if (target.hasAttribute("shrinktofit")) {
|
||||
// Currently shrunk to fit, so unshrink it.
|
||||
target.removeAttribute("shrinktofit");
|
||||
} else {
|
||||
// User wants to shrink now.
|
||||
target.setAttribute("shrinktofit", true);
|
||||
}
|
||||
|
||||
target.toggleAttribute("shrinktofit");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -895,8 +895,10 @@ var messageProgressListener = {
|
|||
* OnStateChange event for STATE_STOP. This is the same event that
|
||||
* generates the "msgLoaded" property flag change event. This best
|
||||
* corresponds to the end of the streaming process.
|
||||
*
|
||||
* @param {nsIMsgMailNewsUrl} url
|
||||
*/
|
||||
onEndMsgDownload(url) {
|
||||
async onEndMsgDownload(url) {
|
||||
const browser = getMessagePaneBrowser();
|
||||
|
||||
// If we have no attachments, we hide the attachment icon in the message
|
||||
|
@ -929,9 +931,7 @@ var messageProgressListener = {
|
|||
currentAttachments.length &&
|
||||
Services.prefs.getBoolPref("mail.inline_attachments") &&
|
||||
FeedUtils.isFeedMessage(gMessage) &&
|
||||
browser &&
|
||||
browser.contentDocument &&
|
||||
browser.contentDocument.body
|
||||
browser.contentDocument?.body
|
||||
) {
|
||||
for (const img of browser.contentDocument.body.getElementsByClassName(
|
||||
"moz-attached-image"
|
||||
|
@ -944,23 +944,108 @@ var messageProgressListener = {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
img.addEventListener(
|
||||
"load",
|
||||
function () {
|
||||
if (this.clientWidth > this.parentNode.clientWidth) {
|
||||
img.setAttribute("overflowing", "true");
|
||||
img.setAttribute("shrinktofit", "true");
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
OnMsgParsed(url);
|
||||
// browser doesn't do this, but I thought it could be a useful thing to test out...
|
||||
// If the find bar is visible and we just loaded a new message, re-run
|
||||
// the find command. This means the new message will get highlighted and
|
||||
// we'll scroll to the first word in the message that matches the find text.
|
||||
const findBar = document.getElementById("FindToolbar");
|
||||
if (!findBar.hidden) {
|
||||
findBar.onFindAgainCommand(false);
|
||||
}
|
||||
// Run the phishing detector on the message if it hasn't been marked as not
|
||||
// a scam already.
|
||||
if (
|
||||
gMessage &&
|
||||
!gMessage.getUint32Property("notAPhishMessage") &&
|
||||
PhishingDetector.analyzeMsgForPhishingURLs(url, browser)
|
||||
) {
|
||||
gMessageNotificationBar.setPhishingMsg();
|
||||
}
|
||||
|
||||
// Notify anyone (e.g., extensions) who's interested in when a message is loaded.
|
||||
Services.obs.notifyObservers(null, "MsgMsgDisplayed", gMessageURI);
|
||||
|
||||
// Rewrite any anchor elements' href attribute to reflect that the loaded
|
||||
// document is a mailnews url. This will cause docShell to scroll to the
|
||||
// element in the document rather than opening the link externally.
|
||||
for (const linkNode of browser.contentDocument.links) {
|
||||
if (!linkNode.hash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have a ref fragment which may reference a node in this document.
|
||||
// Ensure html in mail anchors work as expected.
|
||||
const anchorId = linkNode.hash.replace("#", "");
|
||||
// Continue if an id (html5) or name attribute value for the ref is not
|
||||
// found in this document.
|
||||
try {
|
||||
if (
|
||||
!linkNode.ownerDocument.querySelector(
|
||||
`#${anchorId},[name='${anchorId}']`
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
} catch (ex) {
|
||||
// invalid selector
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then check if the href url matches the document baseURL.
|
||||
if (
|
||||
makeURI(linkNode.href).specIgnoringRef !=
|
||||
makeURI(linkNode.baseURI).specIgnoringRef
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Finally, if the document url is a message url, and the anchor href is
|
||||
// http, it needs to be adjusted so docShell finds the node.
|
||||
const messageURI = makeURI(linkNode.ownerDocument.URL);
|
||||
if (
|
||||
messageURI instanceof Ci.nsIMsgMailNewsUrl &&
|
||||
linkNode.href.startsWith("http")
|
||||
) {
|
||||
linkNode.href = messageURI.specIgnoringRef + linkNode.hash;
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.contentDocument.readyState != "complete") {
|
||||
await new Promise(resolve => {
|
||||
browser.contentWindow.addEventListener("load", resolve, {
|
||||
once: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Scale any overflowing images, exclude http content.
|
||||
if (!browser.contentDocument.URL.startsWith("http")) {
|
||||
const adjustImg = img => {
|
||||
img.toggleAttribute("overflowing", img.naturalWidth > img.clientWidth);
|
||||
};
|
||||
for (const img of browser.contentDocument.images) {
|
||||
// No zooming for children of clickable links.
|
||||
if (img.closest("[href]")) {
|
||||
continue;
|
||||
}
|
||||
img.toggleAttribute("shrinktofit", true);
|
||||
if (!img.complete) {
|
||||
img.addEventListener("load", event => adjustImg(event.target), {
|
||||
once: true,
|
||||
});
|
||||
} else {
|
||||
adjustImg(img);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {nsIMsgMailNewsUrl} url
|
||||
*/
|
||||
onEndMsgHeaders(url) {
|
||||
if (!url.errorCode) {
|
||||
// Should not mark a message as read if failed to load.
|
||||
|
@ -4148,110 +4233,6 @@ function ClearPendingReadTimer() {
|
|||
}
|
||||
}
|
||||
|
||||
// this is called when layout is actually finished rendering a
|
||||
// mail message. OnMsgLoaded is called when libmime is done parsing the message
|
||||
function OnMsgParsed(aUrl) {
|
||||
// browser doesn't do this, but I thought it could be a useful thing to test out...
|
||||
// If the find bar is visible and we just loaded a new message, re-run
|
||||
// the find command. This means the new message will get highlighted and
|
||||
// we'll scroll to the first word in the message that matches the find text.
|
||||
const findBar = document.getElementById("FindToolbar");
|
||||
if (!findBar.hidden) {
|
||||
findBar.onFindAgainCommand(false);
|
||||
}
|
||||
const browser = getMessagePaneBrowser();
|
||||
// Run the phishing detector on the message if it hasn't been marked as not
|
||||
// a scam already.
|
||||
if (
|
||||
gMessage &&
|
||||
!gMessage.getUint32Property("notAPhishMessage") &&
|
||||
PhishingDetector.analyzeMsgForPhishingURLs(aUrl, browser)
|
||||
) {
|
||||
gMessageNotificationBar.setPhishingMsg();
|
||||
}
|
||||
|
||||
// Notify anyone (e.g., extensions) who's interested in when a message is loaded.
|
||||
Services.obs.notifyObservers(null, "MsgMsgDisplayed", gMessageURI);
|
||||
|
||||
const doc =
|
||||
browser && browser.contentDocument ? browser.contentDocument : null;
|
||||
|
||||
// Rewrite any anchor elements' href attribute to reflect that the loaded
|
||||
// document is a mailnews url. This will cause docShell to scroll to the
|
||||
// element in the document rather than opening the link externally.
|
||||
const links = doc && doc.links ? doc.links : [];
|
||||
for (const linkNode of links) {
|
||||
if (!linkNode.hash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have a ref fragment which may reference a node in this document.
|
||||
// Ensure html in mail anchors work as expected.
|
||||
const anchorId = linkNode.hash.replace("#", "");
|
||||
// Continue if an id (html5) or name attribute value for the ref is not
|
||||
// found in this document.
|
||||
const selector = "#" + anchorId + ", [name='" + anchorId + "']";
|
||||
try {
|
||||
if (!linkNode.ownerDocument.querySelector(selector)) {
|
||||
continue;
|
||||
}
|
||||
} catch (ex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then check if the href url matches the document baseURL.
|
||||
if (
|
||||
makeURI(linkNode.href).specIgnoringRef !=
|
||||
makeURI(linkNode.baseURI).specIgnoringRef
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Finally, if the document url is a message url, and the anchor href is
|
||||
// http, it needs to be adjusted so docShell finds the node.
|
||||
const messageURI = makeURI(linkNode.ownerDocument.URL);
|
||||
if (
|
||||
messageURI instanceof Ci.nsIMsgMailNewsUrl &&
|
||||
linkNode.href.startsWith("http")
|
||||
) {
|
||||
linkNode.href = messageURI.specIgnoringRef + linkNode.hash;
|
||||
}
|
||||
}
|
||||
|
||||
const stylesReadyPromise = new Promise(resolve => {
|
||||
if (doc.readyState === "complete") {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
browser.contentWindow.addEventListener("load", resolve, {
|
||||
once: true,
|
||||
});
|
||||
});
|
||||
|
||||
const applyOverflowingToImg = async img => {
|
||||
img.setAttribute("shrinktofit", "true");
|
||||
if (!img.complete) {
|
||||
await new Promise(resolve => {
|
||||
img.addEventListener("load", resolve, { once: true });
|
||||
});
|
||||
}
|
||||
await stylesReadyPromise;
|
||||
if (img.naturalWidth > img.clientWidth) {
|
||||
img.setAttribute("overflowing", "true");
|
||||
}
|
||||
};
|
||||
|
||||
// Scale any overflowing images, exclude http content.
|
||||
const imgs = doc && !doc.URL.startsWith("http") ? doc.images : [];
|
||||
for (const img of imgs) {
|
||||
// No zooming for children of clickable links.
|
||||
if (img.closest("[href]")) {
|
||||
continue;
|
||||
}
|
||||
applyOverflowingToImg(img);
|
||||
}
|
||||
}
|
||||
|
||||
function OnMsgLoaded(aUrl) {
|
||||
window.msgLoaded = true;
|
||||
window.dispatchEvent(
|
||||
|
|
|
@ -15,14 +15,18 @@ let msgc;
|
|||
add_setup(async () => {
|
||||
Services.prefs.setBoolPref("mail.inline_attachments", true);
|
||||
const file = new FileUtils.File(
|
||||
getTestFilePath("data/Image sizing test.eml")
|
||||
getTestFilePath("data/image_sizing_test.eml")
|
||||
);
|
||||
msgc = await open_message_from_file(file);
|
||||
|
||||
if (window.screen.availWidth > msgc.outerWidth && msgc.outerWidth < 500) {
|
||||
const resizePromise = BrowserTestUtils.waitForEvent(msgc, "resize");
|
||||
msgc.resizeTo(Math.min(window.screen.availWidth, 550), msgc.outerHeight);
|
||||
const w = Math.min(window.screen.availWidth, 550);
|
||||
const h = msgc.outerHeight;
|
||||
info(`Resizing window... to ${w}x${h}...`);
|
||||
msgc.resizeTo(w, h);
|
||||
await resizePromise;
|
||||
info("... resized!");
|
||||
await TestUtils.waitForTick();
|
||||
}
|
||||
|
||||
|
@ -38,18 +42,21 @@ add_task(async function test_imageOverflow() {
|
|||
const msgDoc =
|
||||
aboutMessage.document.getElementById("messagepane").contentDocument;
|
||||
|
||||
const messageDisplayWidth = msgDoc.body.clientWidth;
|
||||
Assert.less(
|
||||
messageDisplayWidth,
|
||||
5000,
|
||||
"The message display needs to be less than 5000px wide"
|
||||
await TestUtils.waitForCondition(
|
||||
() => msgDoc.body.clientWidth < 5000,
|
||||
`The message display needs to be less than 5000px wide: ${msgDoc.body.clientWidth}`
|
||||
);
|
||||
|
||||
await TestUtils.waitForCondition(() =>
|
||||
Array.from(msgDoc.querySelectorAll("img")).every(img => img.complete)
|
||||
);
|
||||
|
||||
Assert.equal(msgDoc.body.scrollWidth, messageDisplayWidth, "No scrollbars");
|
||||
const messageDisplayWidth = msgDoc.body.clientWidth;
|
||||
Assert.equal(
|
||||
msgDoc.body.scrollWidth,
|
||||
messageDisplayWidth,
|
||||
"msg doc should not have scrollbars"
|
||||
);
|
||||
|
||||
const imageIds = [];
|
||||
|
||||
|
@ -102,7 +109,6 @@ add_task(async function test_imageOverflow() {
|
|||
},
|
||||
() => !image.hasAttribute("shrinktofit")
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
image.hasAttribute("overflowing"),
|
||||
"Click should keep overflowing attribute"
|
||||
|
@ -131,7 +137,6 @@ add_task(async function test_imageOverflow() {
|
|||
},
|
||||
() => image.hasAttribute("shrinktofit")
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
image.hasAttribute("overflowing"),
|
||||
"Click should keep overflowing attribute"
|
||||
|
@ -167,23 +172,35 @@ add_task(async function test_imageUnderflow() {
|
|||
|
||||
if (initialWidth > 350) {
|
||||
const resizePromise = BrowserTestUtils.waitForEvent(msgc, "resize");
|
||||
info(`Initial width too large; resizing to 350x${msgc.outerHeight}...`);
|
||||
msgc.resizeTo(350, msgc.outerHeight);
|
||||
await resizePromise;
|
||||
info("... resized!");
|
||||
//Assert.equal(msgc.outerWidth, 350, "resizeTo should have worked");
|
||||
await TestUtils.waitForTick();
|
||||
}
|
||||
|
||||
const messageDisplayWidth = msgDoc.body.clientWidth;
|
||||
await TestUtils.waitForCondition(
|
||||
() => msgDoc.body.clientWidth < 400,
|
||||
`The message display needs to be less than 400px wide: ${msgDoc.body.clientWidth}`
|
||||
);
|
||||
Assert.less(
|
||||
messageDisplayWidth,
|
||||
msgDoc.body.clientWidth,
|
||||
400,
|
||||
"The message display needs to be less than 400px wide"
|
||||
"message display width should be less than 400"
|
||||
);
|
||||
|
||||
await TestUtils.waitForCondition(() =>
|
||||
Array.from(msgDoc.querySelectorAll("img")).every(img => img.complete)
|
||||
await TestUtils.waitForCondition(
|
||||
() => Array.from(msgDoc.querySelectorAll("img")).every(img => img.complete),
|
||||
"Every image should complete loading"
|
||||
);
|
||||
|
||||
Assert.equal(msgDoc.body.scrollWidth, messageDisplayWidth, "No scrollbars");
|
||||
const messageDisplayWidth = msgDoc.body.clientWidth;
|
||||
Assert.equal(
|
||||
msgDoc.body.scrollWidth,
|
||||
messageDisplayWidth,
|
||||
"msg doc should not have scrollbars"
|
||||
);
|
||||
|
||||
msgDoc.defaultView.scrollBy({
|
||||
top: 5000,
|
||||
|
@ -191,8 +208,12 @@ add_task(async function test_imageUnderflow() {
|
|||
});
|
||||
|
||||
const image = msgDoc.getElementById("stretched");
|
||||
|
||||
EventUtils.synthesizeMouse(image, 1, 1, {}, msgDoc.defaultView);
|
||||
Assert.ok(
|
||||
image.hasAttribute("shrinktofit"),
|
||||
"img#stretched should have attr shrinktofit"
|
||||
);
|
||||
info("Zooming image #stretched");
|
||||
EventUtils.synthesizeMouse(image, 1, 1, {}, image.ownerGlobal);
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
image,
|
||||
{
|
||||
|
@ -200,11 +221,12 @@ add_task(async function test_imageUnderflow() {
|
|||
},
|
||||
() => !image.hasAttribute("shrinktofit")
|
||||
);
|
||||
info("Zoomed on the image");
|
||||
info("... zoomed on the image #stretched");
|
||||
|
||||
info(`Resizing window to 450x${msgc.outerHeight}...`);
|
||||
const resizePromise2 = BrowserTestUtils.waitForEvent(msgc, "resize");
|
||||
msgc.resizeTo(450, msgc.outerHeight);
|
||||
info("Resizing window...");
|
||||
|
||||
await resizePromise2;
|
||||
await BrowserTestUtils.waitForMutationCondition(
|
||||
image,
|
||||
{
|
||||
|
@ -218,7 +240,10 @@ add_task(async function test_imageUnderflow() {
|
|||
"Image should no longer be overflowing"
|
||||
);
|
||||
|
||||
const resizePromise3 = BrowserTestUtils.waitForEvent(msgc, "resize");
|
||||
info(`Resizing window to ${initialWidth}x${msgc.outerHeight}...`);
|
||||
msgc.resizeTo(initialWidth, msgc.outerHeight);
|
||||
await resizePromise3;
|
||||
msgDoc.defaultView.scrollTo({
|
||||
top: 0,
|
||||
behavior: "instant",
|
||||
|
|
|
@ -1009,7 +1009,7 @@ static char* mime_image_make_image_html(MimeClosure image_closure) {
|
|||
/* Wouldn't it be nice if attributes were case-sensitive? */
|
||||
const char* scaledPrefix =
|
||||
"<DIV CLASS=\"moz-attached-image-container\"><IMG "
|
||||
"CLASS=\"moz-attached-image\" shrinktofit=\"yes\" SRC=\"";
|
||||
"CLASS=\"moz-attached-image\" SRC=\"";
|
||||
const char* suffix = "\"></DIV>";
|
||||
// Thunderbird doesn't have this pref.
|
||||
#ifdef MOZ_SUITE
|
||||
|
|
Загрузка…
Ссылка в новой задаче