diff options
Diffstat (limited to 'comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js')
-rw-r--r-- | comm/mail/base/test/unit/test_viewWrapper_virtualFolder.js | 552 |
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); +}); |