diff options
Diffstat (limited to 'comm/mail/test/browser/attachment/browser_attachmentSize.js')
-rw-r--r-- | comm/mail/test/browser/attachment/browser_attachmentSize.js | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/comm/mail/test/browser/attachment/browser_attachmentSize.js b/comm/mail/test/browser/attachment/browser_attachmentSize.js new file mode 100644 index 0000000000..f4980c46ad --- /dev/null +++ b/comm/mail/test/browser/attachment/browser_attachmentSize.js @@ -0,0 +1,421 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var folder; +var messenger; +var epsilon; + +var { + create_body_part, + create_deleted_attachment, + create_detached_attachment, +} = ChromeUtils.import( + "resource://testing-common/mozmill/AttachmentHelpers.jsm" +); +var { + add_message_to_folder, + be_in_folder, + create_folder, + create_message, + get_about_message, + mc, + msgGen, + select_click_row, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); + +var { SyntheticPartLeaf, SyntheticPartMultiMixed } = ChromeUtils.import( + "resource://testing-common/mailnews/MessageGenerator.jsm" +); + +var textAttachment = + "Can't make the frug contest, Helen; stomach's upset. I'll fix you, " + + "Ubik! Ubik drops you back in the thick of things fast. Taken as " + + "directed, Ubik speeds relief to head and stomach. Remember: Ubik is " + + "only seconds away. Avoid prolonged use."; + +var binaryAttachment = textAttachment; + +var imageAttachment = + "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwS" + + "FlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA" + + "A5SURBVCiRY/z//z8DKYCJJNXkaGBgYGD4D8NQ5zUgiTVAxeBqSLaBkVRPM0KtIhrQ3km0jwe" + + "SNQAAlmAY+71EgFoAAAAASUVORK5CYII="; +var imageSize = 188; + +var vcardAttachment = + "YmVnaW46dmNhcmQNCmZuOkppbSBCb2INCm46Qm9iO0ppbQ0KZW1haWw7aW50ZXJuZXQ6Zm9v" + + "QGJhci5jb20NCnZlcnNpb246Mi4xDQplbmQ6dmNhcmQNCg0K"; +var vcardSize = 90; + +var detachedName = "./attachment.txt"; +var missingName = "./nonexistent.txt"; +var deletedName = "deleted.txt"; + +// create some messages that have various types of attachments +var messages = [ + { + name: "text_attachment", + attachments: [{ body: textAttachment, filename: "ubik.txt", format: "" }], + attachmentSizes: [textAttachment.length], + attachmentTotalSize: { size: textAttachment.length, exact: true }, + }, + { + name: "binary_attachment", + attachments: [ + { + body: binaryAttachment, + contentType: "application/x-ubik", + filename: "ubik", + format: "", + }, + ], + attachmentSizes: [binaryAttachment.length], + attachmentTotalSize: { size: binaryAttachment.length, exact: true }, + }, + { + name: "image_attachment", + attachments: [ + { + body: imageAttachment, + contentType: "image/png", + filename: "lines.png", + encoding: "base64", + format: "", + }, + ], + attachmentSizes: [imageSize], + attachmentTotalSize: { size: imageSize, exact: true }, + }, + { + name: "detached_attachment", + bodyPart: null, + // Sizes filled in on message creation. + attachmentSizes: [null], + attachmentTotalSize: { size: 0, exact: true }, + }, + { + name: "detached_attachment_with_missing_file", + bodyPart: null, + attachmentSizes: [-1], + attachmentTotalSize: { size: 0, exact: false }, + }, + { + name: "deleted_attachment", + bodyPart: null, + attachmentSizes: [-1], + attachmentTotalSize: { size: 0, exact: true }, + }, + { + name: "multiple_attachments", + attachments: [ + { body: textAttachment, filename: "ubik.txt", format: "" }, + { + body: binaryAttachment, + contentType: "application/x-ubik", + filename: "ubik", + format: "", + }, + ], + attachmentSizes: [textAttachment.length, binaryAttachment.length], + attachmentTotalSize: { + size: textAttachment.length + binaryAttachment.length, + exact: true, + }, + }, + // vCards should be included in the attachment list. + { + name: "multiple_attachments_one_vcard", + attachments: [ + { body: textAttachment, filename: "ubik.txt", format: "" }, + { + body: vcardAttachment, + contentType: "text/vcard", + filename: "ubik.vcf", + encoding: "base64", + format: "", + }, + ], + attachmentSizes: [textAttachment.length, vcardSize], + attachmentTotalSize: { + size: textAttachment.length + vcardSize, + exact: true, + }, + }, + { + name: "multiple_attachments_one_detached", + bodyPart: null, + attachments: [{ body: textAttachment, filename: "ubik.txt", format: "" }], + attachmentSizes: [null, textAttachment.length], + attachmentTotalSize: { size: textAttachment.length, exact: true }, + }, + { + name: "multiple_attachments_one_detached_with_missing_file", + bodyPart: null, + attachments: [{ body: textAttachment, filename: "ubik.txt", format: "" }], + attachmentSizes: [-1, textAttachment.length], + attachmentTotalSize: { size: textAttachment.length, exact: false }, + }, + { + name: "multiple_attachments_one_deleted", + bodyPart: null, + attachments: [{ body: textAttachment, filename: "ubik.txt", format: "" }], + attachmentSizes: [-1, textAttachment.length], + attachmentTotalSize: { size: textAttachment.length, exact: true }, + }, + // this is an attached message that itself has an attachment + { + name: "attached_message_with_attachment", + bodyPart: null, + attachmentSizes: [-1, textAttachment.length], + attachmentTotalSize: { size: 0, exact: true }, + }, +]; + +add_setup(async function () { + messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger); + + /* Today's gory details (thanks to Jonathan Protzenko): libmime somehow + * counts the trailing newline for an attachment MIME part. Most of the time, + * assuming attachment has N bytes (no matter what's inside, newlines or + * not), libmime will return N + 1 bytes. On Linux and Mac, this always + * holds. However, on Windows, if the attachment is not encoded (that is, is + * inline text), libmime will return N + 2 bytes. + */ + epsilon = "@mozilla.org/windows-registry-key;1" in Cc ? 4 : 2; + + // set up our detached/deleted attachments + var detachedFile = new FileUtils.File( + getTestFilePath(`data/${detachedName}`) + ); + var detached = create_body_part("Here is a file", [ + create_detached_attachment(detachedFile, "text/plain"), + ]); + + var missingFile = new FileUtils.File(getTestFilePath(`data/${missingName}`)); + var missing = create_body_part( + "Here is a file (but you deleted the external file, you silly oaf!)", + [create_detached_attachment(missingFile, "text/plain")] + ); + + var deleted = create_body_part("Here is a file that you deleted", [ + create_deleted_attachment(deletedName, "text/plain"), + ]); + + var attachedMessage = msgGen.makeMessage({ + body: { body: textAttachment }, + attachments: [{ body: textAttachment, filename: "ubik.txt", format: "" }], + }); + + /* Much like the above comment, libmime counts bytes differently on Windows, + * where it counts newlines (\r\n) as 2 bytes. Mac and Linux treats them as + * 1 byte. + */ + var attachedMessageLength; + if (epsilon == 4) { + // Windows + attachedMessageLength = attachedMessage.toMessageString().length; + } else { + // Mac/Linux + attachedMessageLength = attachedMessage + .toMessageString() + .replace(/\r\n/g, "\n").length; + } + + folder = await create_folder("AttachmentSizeA"); + for (let i = 0; i < messages.length; i++) { + // First, add any missing info to the message object. + switch (messages[i].name) { + case "detached_attachment": + case "multiple_attachments_one_detached": + messages[i].bodyPart = detached; + messages[i].attachmentSizes[0] = detachedFile.fileSize; + messages[i].attachmentTotalSize.size += detachedFile.fileSize; + break; + case "detached_attachment_with_missing_file": + case "multiple_attachments_one_detached_with_missing_file": + messages[i].bodyPart = missing; + break; + case "deleted_attachment": + case "multiple_attachments_one_deleted": + messages[i].bodyPart = deleted; + break; + case "attached_message_with_attachment": + messages[i].bodyPart = new SyntheticPartMultiMixed([ + new SyntheticPartLeaf("I am text!", { contentType: "text/plain" }), + attachedMessage, + ]); + messages[i].attachmentSizes[0] = attachedMessageLength; + messages[i].attachmentTotalSize.size += attachedMessageLength; + break; + } + + await add_message_to_folder([folder], create_message(messages[i])); + } +}); + +/** + * Make sure that the attachment's size is what we expect + * + * @param index the attachment's index, starting at 0 + * @param expectedSize the expected size of the attachment, in bytes + */ +function check_attachment_size(index, expectedSize) { + let win = get_about_message(); + let list = win.document.getElementById("attachmentList"); + let node = list.querySelectorAll("richlistitem.attachmentItem")[index]; + + // First, let's check that the attachment size is correct + let size = node.attachment.size; + Assert.ok( + Math.abs(size - expectedSize) <= epsilon, + `Attachment "${node.attachment.name}" size should be within ${epsilon} ` + + `of ${expectedSize} (actual: ${size})` + ); + + // Next, make sure that the formatted size in the label is correct + Assert.equal( + node.getAttribute("size"), + messenger.formatFileSize(size), + `Attachment "${node.attachment.name}" displayed size should match` + ); +} + +/** + * Make sure that the attachment's size is not displayed + * + * @param index the attachment's index, starting at 0 + */ +function check_no_attachment_size(index) { + let win = get_about_message(); + let list = win.document.getElementById("attachmentList"); + let node = list.querySelectorAll("richlistitem.attachmentItem")[index]; + + Assert.equal( + node.attachment.size, + -1, + `Attachment "${node.attachment.name}" should have a size of -1` + ); + + // If there's no size, the size attribute is the zero-width space. + let nodeSize = node.getAttribute("size"); + Assert.equal( + nodeSize, + "", + `Attachment "${node.attachment.name}" size should not be displayed` + ); +} + +/** + * Make sure that the total size of all attachments is what we expect. + * + * @param count the expected number of attachments + * @param expectedSize the expected size in bytes of all the attachments + * @param exact true if the size of all attachments is known, false otherwise + */ +function check_total_attachment_size(count, expectedSize, exact) { + let win = get_about_message(); + let list = win.document.getElementById("attachmentList"); + let nodes = list.querySelectorAll("richlistitem.attachmentItem"); + let sizeNode = win.document.getElementById("attachmentSize"); + + Assert.equal( + nodes.length, + count, + "Should have the expected number of attachments" + ); + + let lastPartID; + let size = 0; + for (let i = 0; i < nodes.length; i++) { + let attachment = nodes[i].attachment; + if (!lastPartID || attachment.partID.indexOf(lastPartID) != 0) { + lastPartID = attachment.partID; + let currSize = attachment.size; + if (currSize > 0 && !isNaN(currSize)) { + size += Number(currSize); + } + } + } + + Assert.ok( + Math.abs(size - expectedSize) <= epsilon * count, + `Total attachments size should be within ${epsilon * count} ` + + `of ${expectedSize} (actual: ${size})` + ); + + // Next, make sure that the formatted size in the label is correct + let formattedSize = sizeNode.getAttribute("value"); + let expectedFormattedSize = messenger.formatFileSize(size); + let messengerBundle = mc.window.document.getElementById("bundle_messenger"); + + if (!exact) { + if (size == 0) { + expectedFormattedSize = messengerBundle.getString( + "attachmentSizeUnknown" + ); + } else { + expectedFormattedSize = messengerBundle.getFormattedString( + "attachmentSizeAtLeast", + [expectedFormattedSize] + ); + } + } + Assert.equal( + formattedSize, + expectedFormattedSize, + "Displayed attachments total size should match" + ); +} + +/** + * Make sure that the individual and total attachment sizes for this message + * are as expected + * + * @param index the index of the message to check in the thread pane + */ +async function help_test_attachment_size(index) { + await be_in_folder(folder); + select_click_row(index); + info(`Testing message ${index}: ${messages[index].name}`); + let expectedSizes = messages[index].attachmentSizes; + + let aboutMessage = get_about_message(); + aboutMessage.toggleAttachmentList(true); + + let attachmentList = aboutMessage.document.getElementById("attachmentList"); + await TestUtils.waitForCondition( + () => !attachmentList.collapsed, + "Attachment list is shown" + ); + + for (let i = 0; i < expectedSizes.length; i++) { + if (expectedSizes[i] == -1) { + check_no_attachment_size(i); + } else { + check_attachment_size(i, expectedSizes[i]); + } + } + + let totalSize = messages[index].attachmentTotalSize; + check_total_attachment_size( + expectedSizes.length, + totalSize.size, + totalSize.exact + ); +} + +add_task(async function test_attachment_sizes() { + for (let i = 0; i < messages.length; i++) { + await help_test_attachment_size(i); + } +}); + +registerCleanupFunction(() => { + // Remove created folders. + folder.deleteSelf(null); +}); |