summaryrefslogtreecommitdiffstats
path: root/comm/mail/test/browser/attachment/browser_attachmentSize.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/test/browser/attachment/browser_attachmentSize.js')
-rw-r--r--comm/mail/test/browser/attachment/browser_attachmentSize.js421
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);
+});