summaryrefslogtreecommitdiffstats
path: root/comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js')
-rw-r--r--comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js552
1 files changed, 552 insertions, 0 deletions
diff --git a/comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js b/comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js
new file mode 100644
index 0000000000..f33124b9d4
--- /dev/null
+++ b/comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js
@@ -0,0 +1,552 @@
+/* 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/. */
+
+/**
+ * Test DBViewWrapper against virtual folders.
+ *
+ * Things we do not test and our rationalizations:
+ * - threading stuff. This is not the view wrapper's problem. That is the db
+ * view's problem! (We test it in the real folder to make sure we are telling
+ * it to do things correctly.)
+ * - view flags. Again, it's a db view issue once we're sure we set the bits.
+ * - special view with threads. same deal.
+ *
+ * We could test all these things, but my patch is way behind schedule...
+ */
+
+/* import-globals-from resources/viewWrapperTestUtils.js */
+load("resources/viewWrapperTestUtils.js");
+initViewWrapperTestUtils({ mode: "local" });
+
+// -- single-folder backed virtual folder
+
+/**
+ * Make sure we open a virtual folder backed by a single underlying folder
+ * correctly; no constraints.
+ */
+add_task(async function test_virtual_folder_single_load_no_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne], setOne] = await messageInjection.makeFoldersWithSets(1, [
+ {},
+ ]);
+
+ let virtFolder = messageInjection.makeVirtualFolder([folderOne], {});
+ await view_open(viewWrapper, virtFolder);
+
+ Assert.ok(viewWrapper.isVirtual);
+
+ assert_equals(
+ gMockViewWrapperListener.allMessagesLoadedEventCount,
+ 1,
+ "Should only have received a single all messages loaded notification!"
+ );
+
+ verify_messages_in_view(setOne, viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/**
+ * Make sure we open a virtual folder backed by a single underlying folder
+ * correctly; one constraint.
+ */
+add_task(async function test_virtual_folder_single_load_simple_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne], oneSubjFoo] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, {}]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder([folderOne], {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view(oneSubjFoo, viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/**
+ * Make sure we open a virtual folder backed by a single underlying folder
+ * correctly; two constraints ANDed together.
+ */
+add_task(async function test_virtual_folder_single_load_complex_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ let whoBar = make_person_with_word_in_name("bar");
+
+ let [[folderOne], , , oneBoth] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, { from: whoBar }, { subject: "foo", from: whoBar }, {}]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder(
+ [folderOne],
+ { subject: "foo", from: "bar" },
+ /* and? */ true
+ );
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view(oneBoth, viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/**
+ * Open a single-backed virtual folder, verify, open another single-backed
+ * virtual folder, verify. We are testing our ability to change folders
+ * without exploding.
+ */
+add_task(async function test_virtual_folder_single_load_after_load() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne], oneSubjFoo] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, {}]
+ );
+ let virtOne = messageInjection.makeVirtualFolder([folderOne], {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtOne);
+ verify_messages_in_view([oneSubjFoo], viewWrapper);
+
+ // use "bar" instead of "foo" to make sure constraints are properly changing
+ let [[folderTwo], twoSubjBar] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "bar" }, {}]
+ );
+ let virtTwo = messageInjection.makeVirtualFolder([folderTwo], {
+ subject: "bar",
+ });
+ await view_open(viewWrapper, virtTwo);
+ verify_messages_in_view([twoSubjBar], viewWrapper);
+ virtOne.parent.propagateDelete(virtOne, true);
+ virtTwo.parent.propagateDelete(virtTwo, true);
+});
+
+// -- multi-folder backed virtual folder
+
+/**
+ * Make sure we open a virtual folder backed by multiple underlying folders
+ * correctly; no constraints.
+ */
+add_task(async function test_virtual_folder_multi_load_no_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne], setOne] = await messageInjection.makeFoldersWithSets(1, [
+ {},
+ ]);
+ let [[folderTwo], setTwo] = await messageInjection.makeFoldersWithSets(1, [
+ {},
+ ]);
+
+ let virtFolder = messageInjection.makeVirtualFolder(
+ [folderOne, folderTwo],
+ {}
+ );
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view([setOne, setTwo], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/**
+ * Make sure the sort order of a virtual folder backed by multiple underlying
+ * folders is persistent.
+ */
+add_task(async function test_virtual_folder_multi_sortorder_persistence() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne], setOne] = await messageInjection.makeFoldersWithSets(1, [
+ {},
+ ]);
+ let [[folderTwo], setTwo] = await messageInjection.makeFoldersWithSets(1, [
+ {},
+ ]);
+
+ let virtFolder = messageInjection.makeVirtualFolder(
+ [folderOne, folderTwo],
+ {}
+ );
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view([setOne, setTwo], viewWrapper);
+ viewWrapper.showThreaded = true;
+ viewWrapper.sort(
+ Ci.nsMsgViewSortType.bySubject,
+ Ci.nsMsgViewSortOrder.ascending
+ );
+
+ viewWrapper.close();
+ await view_open(viewWrapper, virtFolder);
+ assert_equals(
+ viewWrapper.primarySortType,
+ Ci.nsMsgViewSortType.bySubject,
+ "should have remembered sort type."
+ );
+ assert_equals(
+ viewWrapper.primarySortOrder,
+ Ci.nsMsgViewSortOrder.ascending,
+ "should have remembered sort order."
+ );
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/**
+ * Make sure we open a virtual folder backed by multiple underlying folders
+ * correctly; one constraint.
+ */
+add_task(async function test_virtual_folder_multi_load_simple_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne], oneSubjFoo] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, {}]
+ );
+ let [[folderTwo], twoSubjFoo] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, {}]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder([folderOne, folderTwo], {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view([oneSubjFoo, twoSubjFoo], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/**
+ * Make sure we open a virtual folder backed by multiple underlying folders
+ * correctly; two constraints ANDed together.
+ */
+add_task(async function test_virtual_folder_multi_load_complex_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ let whoBar = make_person_with_word_in_name("bar");
+
+ let [[folderOne], , , oneBoth] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, { from: whoBar }, { subject: "foo", from: whoBar }, {}]
+ );
+ let [[folderTwo], , , twoBoth] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, { from: whoBar }, { subject: "foo", from: whoBar }, {}]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder(
+ [folderOne, folderTwo],
+ { subject: "foo", from: "bar" },
+ /* and? */ true
+ );
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view([oneBoth, twoBoth], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+add_task(
+ async function test_virtual_folder_multi_load_alotta_folders_no_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ const folderCount = 4;
+ const messageCount = 64;
+
+ let [folders, setOne] = await messageInjection.makeFoldersWithSets(
+ folderCount,
+ [{ count: messageCount }]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder(folders, {});
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view([setOne], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+ }
+);
+
+add_task(
+ async function test_virtual_folder_multi_load_alotta_folders_simple_pred() {
+ let viewWrapper = make_view_wrapper();
+
+ const folderCount = 16;
+ const messageCount = 256;
+
+ let [folders, setOne] = await messageInjection.makeFoldersWithSets(
+ folderCount,
+ [{ subject: "foo", count: messageCount }]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder(folders, {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtFolder);
+
+ verify_messages_in_view([setOne], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+ }
+);
+
+/**
+ * Make sure that opening a virtual folder backed by multiple real folders, then
+ * opening another virtual folder of the same variety works without explosions.
+ */
+add_task(async function test_virtual_folder_multi_load_after_load() {
+ let viewWrapper = make_view_wrapper();
+
+ let [foldersOne, oneSubjFoo] = await messageInjection.makeFoldersWithSets(2, [
+ { subject: "foo" },
+ {},
+ ]);
+ let virtOne = messageInjection.makeVirtualFolder(foldersOne, {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtOne);
+ verify_messages_in_view([oneSubjFoo], viewWrapper);
+
+ // use "bar" instead of "foo" to make sure constraints are properly changing
+ let [foldersTwo, twoSubjBar] = await messageInjection.makeFoldersWithSets(3, [
+ { subject: "bar" },
+ {},
+ ]);
+ let virtTwo = messageInjection.makeVirtualFolder(foldersTwo, {
+ subject: "bar",
+ });
+ await view_open(viewWrapper, virtTwo);
+ verify_messages_in_view([twoSubjBar], viewWrapper);
+
+ await view_open(viewWrapper, virtOne);
+ verify_messages_in_view([oneSubjFoo], viewWrapper);
+ virtOne.parent.propagateDelete(virtOne, true);
+ virtTwo.parent.propagateDelete(virtTwo, true);
+});
+
+// -- mixture of single-backed and multi-backed
+
+/**
+ * Make sure that opening a virtual folder backed by a single real folder, then
+ * a multi-backed one, then the single-backed one again doesn't explode.
+ *
+ * This is just test_virtual_folder_multi_load_after_load with foldersOne told
+ * to create just a single folder.
+ */
+add_task(async function test_virtual_folder_combo_load_after_load() {
+ let viewWrapper = make_view_wrapper();
+
+ let [foldersOne, oneSubjFoo] = await messageInjection.makeFoldersWithSets(1, [
+ { subject: "foo" },
+ {},
+ ]);
+ let virtOne = messageInjection.makeVirtualFolder(foldersOne, {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtOne);
+ verify_messages_in_view([oneSubjFoo], viewWrapper);
+
+ // use "bar" instead of "foo" to make sure constraints are properly changing
+ let [foldersTwo, twoSubjBar] = await messageInjection.makeFoldersWithSets(3, [
+ { subject: "bar" },
+ {},
+ ]);
+ let virtTwo = messageInjection.makeVirtualFolder(foldersTwo, {
+ subject: "bar",
+ });
+ await view_open(viewWrapper, virtTwo);
+ verify_messages_in_view([twoSubjBar], viewWrapper);
+
+ await view_open(viewWrapper, virtOne);
+ verify_messages_in_view([oneSubjFoo], viewWrapper);
+ virtOne.parent.propagateDelete(virtOne, true);
+ virtTwo.parent.propagateDelete(virtTwo, true);
+});
+
+// -- ignore things we should ignore
+
+/**
+ * Make sure that if a server is listed in a virtual folder's search Uris that
+ * it does not get into our list of _underlyingFolders.
+ */
+add_task(async function test_virtual_folder_filters_out_servers() {
+ let viewWrapper = make_view_wrapper();
+
+ let [folders] = await messageInjection.makeFoldersWithSets(2, []);
+ folders.push(folders[0].rootFolder);
+ let virtFolder = messageInjection.makeVirtualFolder(folders, {});
+ await view_open(viewWrapper, virtFolder);
+
+ assert_equals(
+ viewWrapper._underlyingFolders.length,
+ 2,
+ "Server folder should have been filtered out."
+ );
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+// -- rare/edge cases!
+
+/**
+ * Verify that if one of the folders backing our virtual folder is deleted that
+ * we do not explode. Then verify that if we remove the rest of them that the
+ * view wrapper closes itself.
+ */
+add_task(async function test_virtual_folder_underlying_folder_deleted() {
+ let viewWrapper = make_view_wrapper();
+
+ let [[folderOne]] = await messageInjection.makeFoldersWithSets(1, [
+ { subject: "foo" },
+ {},
+ ]);
+ let [[folderTwo], twoSubjFoo] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo" }, {}]
+ );
+
+ let virtFolder = messageInjection.makeVirtualFolder([folderOne, folderTwo], {
+ subject: "foo",
+ });
+ await view_open(viewWrapper, virtFolder);
+
+ // this triggers the search (under the view's hood), so it's async
+ await delete_folder(folderOne, viewWrapper);
+
+ // only messages from the surviving folder should be present
+ verify_messages_in_view([twoSubjFoo], viewWrapper);
+
+ // this one is not async though, because we are expecting to close the wrapper
+ // and ignore the view entirely, no resolving action.
+ delete_folder(folderTwo);
+
+ // now the view wrapper should have closed itself.
+ Assert.equal(null, viewWrapper.displayedFolder);
+ // This fails because virtFolder.parent is null, not sure why
+ // virtFolder.parent.propagateDelete(virtFolder, true);
+});
+
+/* ===== Virtual Folder, Mail Views ===== */
+
+/*
+ * We do not need to test all of the mail view permutations, realFolder
+ * already did that. We just need to make sure it works at all.
+ */
+
+add_task(
+ async function test_virtual_folder_mail_views_unread_with_one_folder() {
+ let viewWrapper = make_view_wrapper();
+
+ let [folders, fooOne, fooTwo] = await messageInjection.makeFoldersWithSets(
+ 1,
+ [{ subject: "foo 1" }, { subject: "foo 2" }, {}, {}]
+ );
+ let virtFolder = messageInjection.makeVirtualFolder(folders, {
+ subject: "foo",
+ });
+
+ // everything is unread to start with!
+ await view_open(viewWrapper, virtFolder);
+ await view_set_mail_view(viewWrapper, MailViewConstants.kViewItemUnread);
+ verify_messages_in_view([fooOne, fooTwo], viewWrapper);
+
+ // add some more things (unread!), make sure they appear.
+ let [fooThree] = await messageInjection.makeNewSetsInFolders(folders, [
+ { subject: "foo 3" },
+ {},
+ ]);
+ verify_messages_in_view([fooOne, fooTwo, fooThree], viewWrapper);
+
+ // make some things read, make sure they disappear. (after a refresh)
+ fooTwo.setRead(true);
+ await view_refresh(viewWrapper);
+ verify_messages_in_view([fooOne, fooThree], viewWrapper);
+
+ // make those things un-read again.
+ fooTwo.setRead(false);
+ // I thought this was a quick search limitation, but XFVF needs it to, at
+ // least for the unread case.
+ await view_refresh(viewWrapper);
+ verify_messages_in_view([fooOne, fooTwo, fooThree], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+ }
+);
+
+// -- mail views
+
+add_task(
+ async function test_virtual_folder_mail_views_unread_with_four_folders() {
+ let viewWrapper = make_view_wrapper();
+
+ let [folders, fooOne, fooTwo] = await messageInjection.makeFoldersWithSets(
+ 4,
+ [{ subject: "foo 1" }, { subject: "foo 2" }, {}, {}]
+ );
+ let virtFolder = messageInjection.makeVirtualFolder(folders, {
+ subject: "foo",
+ });
+
+ // everything is unread to start with!
+ await view_open(viewWrapper, virtFolder);
+ await view_set_mail_view(viewWrapper, MailViewConstants.kViewItemUnread);
+ verify_messages_in_view([fooOne, fooTwo], viewWrapper);
+
+ // add some more things (unread!), make sure they appear.
+ let [fooThree] = await messageInjection.makeNewSetsInFolders(folders, [
+ { subject: "foo 3" },
+ {},
+ ]);
+ verify_messages_in_view([fooOne, fooTwo, fooThree], viewWrapper);
+
+ // make some things read, make sure they disappear. (after a refresh)
+ fooTwo.setRead(true);
+ await view_refresh(viewWrapper);
+ verify_messages_in_view([fooOne, fooThree], viewWrapper);
+
+ // make those things un-read again.
+ fooTwo.setRead(false);
+ // I thought this was a quick search limitation, but XFVF needs it to, at
+ // least for the unread case.
+ await view_refresh(viewWrapper);
+ verify_messages_in_view([fooOne, fooTwo, fooThree], viewWrapper);
+ virtFolder.parent.propagateDelete(virtFolder, true);
+ }
+);
+
+// This tests that clearing the new messages in a folder also clears the
+// new flag on saved search folders based on the real folder. This could be a
+// core view test, or a mozmill test, but I think the view wrapper stuff
+// is involved in some of the issues here, so this is a compromise.
+add_task(async function test_virtual_folder_mail_new_handling() {
+ let viewWrapper = make_view_wrapper();
+
+ let [folders] = await messageInjection.makeFoldersWithSets(1, [
+ { subject: "foo 1" },
+ { subject: "foo 2" },
+ ]);
+ let folder = folders[0];
+ let virtFolder = messageInjection.makeVirtualFolder(folders, {
+ subject: "foo",
+ });
+
+ await view_open(viewWrapper, folder);
+
+ await messageInjection.makeNewSetsInFolders(folders, [
+ { subject: "foo 3" },
+ {},
+ ]);
+
+ if (!virtFolder.hasNewMessages) {
+ do_throw("saved search should have new messages!");
+ }
+
+ if (!folder.hasNewMessages) {
+ do_throw("folder should have new messages!");
+ }
+
+ viewWrapper.close();
+ folder.msgDatabase = null;
+ folder.clearNewMessages();
+ if (virtFolder.hasNewMessages) {
+ do_throw("saved search should not have new messages!");
+ }
+ virtFolder.parent.propagateDelete(virtFolder, true);
+});