From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- comm/mail/base/test/unit/test_viewWrapper_logic.js | 359 +++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 comm/mail/base/test/unit/test_viewWrapper_logic.js (limited to 'comm/mail/base/test/unit/test_viewWrapper_logic.js') diff --git a/comm/mail/base/test/unit/test_viewWrapper_logic.js b/comm/mail/base/test/unit/test_viewWrapper_logic.js new file mode 100644 index 0000000000..ef56cb3997 --- /dev/null +++ b/comm/mail/base/test/unit/test_viewWrapper_logic.js @@ -0,0 +1,359 @@ +/* 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/. */ + +load("../../../../mailnews/resources/abSetup.js"); + +/* import-globals-from resources/viewWrapperTestUtils.js */ +load("resources/viewWrapperTestUtils.js"); +initViewWrapperTestUtils({ mode: "local" }); + +/** + * Verify that flipping between threading and grouped by sort settings properly + * clears the other flag. (Because they're mutually exclusive, you see.) + */ +add_task(async function test_threading_grouping_mutual_exclusion() { + let viewWrapper = make_view_wrapper(); + let folder = await messageInjection.makeEmptyFolder(); + + await view_open(viewWrapper, folder); + // enter an update that will never conclude. this is fine. + viewWrapper.beginViewUpdate(); + viewWrapper.showThreaded = true; + assert_true(viewWrapper.showThreaded, "view should be threaded"); + assert_false( + viewWrapper.showGroupedBySort, + "view should not be grouped by sort" + ); + + viewWrapper.showGroupedBySort = true; + assert_false(viewWrapper.showThreaded, "view should not be threaded"); + assert_true(viewWrapper.showGroupedBySort, "view should be grouped by sort"); +}); + +/** + * Verify that flipping between the "View... Threads..." menu cases supported by + * |showUnreadOnly| / |specialViewThreadsWithUnread| / + * |specialViewThreadsWithUnread| has them all be properly mutually exclusive. + */ +add_task(async function test_threads_special_views_mutual_exclusion() { + let viewWrapper = make_view_wrapper(); + let folder = await messageInjection.makeEmptyFolder(); + + await view_open(viewWrapper, folder); + // enter an update that will never conclude. this is fine. + viewWrapper.beginViewUpdate(); + + // turn on the special view, make sure we think it took + viewWrapper.specialViewThreadsWithUnread = true; + Assert.ok(viewWrapper.specialViewThreadsWithUnread); + Assert.ok(!viewWrapper.specialViewWatchedThreadsWithUnread); + + // hit showUnreadOnly which should already be false, so this makes sure that + // just writing to it forces the special view off. + viewWrapper.showUnreadOnly = false; + Assert.ok(!viewWrapper.showUnreadOnly); + Assert.ok(!viewWrapper.specialViewThreadsWithUnread); + Assert.ok(!viewWrapper.specialViewWatchedThreadsWithUnread); + + // turn on the other special view + viewWrapper.specialViewWatchedThreadsWithUnread = true; + Assert.ok(!viewWrapper.specialViewThreadsWithUnread); + Assert.ok(viewWrapper.specialViewWatchedThreadsWithUnread); + + // turn on show unread only mode, make sure special view is cleared + viewWrapper.showUnreadOnly = true; + Assert.ok(viewWrapper.showUnreadOnly); + Assert.ok(!viewWrapper.specialViewThreadsWithUnread); + Assert.ok(!viewWrapper.specialViewWatchedThreadsWithUnread); + + // turn off show unread only mode just to make sure the transition happens + viewWrapper.showUnreadOnly = false; + Assert.ok(!viewWrapper.showUnreadOnly); + Assert.ok(!viewWrapper.specialViewThreadsWithUnread); + Assert.ok(!viewWrapper.specialViewWatchedThreadsWithUnread); +}); + +/** + * Do a quick test of primary sorting to make sure we're actually changing the + * sort order. (However, we are not responsible for verifying correctness of + * the sort.) + */ +add_task(async function test_sort_primary() { + let viewWrapper = make_view_wrapper(); + // we need to put messages in the folder or the sort logic doesn't actually + // save the sort state. (this is the C++ view's fault.) + let [[folder]] = await messageInjection.makeFoldersWithSets(1, [{}]); + + await view_open(viewWrapper, folder); + viewWrapper.sort( + Ci.nsMsgViewSortType.byDate, + Ci.nsMsgViewSortOrder.ascending + ); + assert_equals( + viewWrapper.dbView.sortType, + Ci.nsMsgViewSortType.byDate, + "sort should be by date", + true + ); + assert_equals( + viewWrapper.dbView.sortOrder, + Ci.nsMsgViewSortOrder.ascending, + "sort order should be ascending", + true + ); + + viewWrapper.sort( + Ci.nsMsgViewSortType.byAuthor, + Ci.nsMsgViewSortOrder.descending + ); + assert_equals( + viewWrapper.dbView.sortType, + Ci.nsMsgViewSortType.byAuthor, + "sort should be by author", + true + ); + assert_equals( + viewWrapper.dbView.sortOrder, + Ci.nsMsgViewSortOrder.descending, + "sort order should be descending", + true + ); +}); + +/** + * Verify that we handle explicit secondary sorts correctly. + */ +add_task(async function test_sort_secondary_explicit() { + let viewWrapper = make_view_wrapper(); + // we need to put messages in the folder or the sort logic doesn't actually + // save the sort state. (this is the C++ view's fault.) + let [[folder]] = await messageInjection.makeFoldersWithSets(1, [{}]); + + await view_open(viewWrapper, folder); + viewWrapper.sort( + Ci.nsMsgViewSortType.byAuthor, + Ci.nsMsgViewSortOrder.ascending, + Ci.nsMsgViewSortType.bySubject, + Ci.nsMsgViewSortOrder.descending + ); + // check once for what we just did, then again after refreshing to make + // sure the sort order 'stuck' + for (let i = 0; i < 2; i++) { + assert_equals( + viewWrapper.dbView.sortType, + Ci.nsMsgViewSortType.byAuthor, + "sort should be by author" + ); + assert_equals( + viewWrapper.dbView.sortOrder, + Ci.nsMsgViewSortOrder.ascending, + "sort order should be ascending" + ); + assert_equals( + viewWrapper.dbView.secondarySortType, + Ci.nsMsgViewSortType.bySubject, + "secondary sort should be by subject" + ); + assert_equals( + viewWrapper.dbView.secondarySortOrder, + Ci.nsMsgViewSortOrder.descending, + "secondary sort order should be descending" + ); + await view_refresh(viewWrapper); + } +}); + +/** + * Verify that we handle implicit secondary sorts correctly. + * An implicit secondary sort is when we sort by Y, then we sort by X, and it's + * okay to have the effective sort of [X, Y]. The UI has/wants this, so, uh, + * let's make sure we obey its assumptions unless we have gone and made the UI + * be explicit about these things. We can't simply depend on the view to do + * this for us. Why? Because we re-create the view all the bloody time. + */ +add_task(async function test_sort_secondary_implicit() { + let viewWrapper = make_view_wrapper(); + // we need to put messages in the folder or the sort logic doesn't actually + // save the sort state. (this is the C++ view's fault.) + let [[folder]] = await messageInjection.makeFoldersWithSets(1, [{}]); + + await view_open(viewWrapper, folder); + viewWrapper.magicSort( + Ci.nsMsgViewSortType.bySubject, + Ci.nsMsgViewSortOrder.descending + ); + viewWrapper.magicSort( + Ci.nsMsgViewSortType.byAuthor, + Ci.nsMsgViewSortOrder.ascending + ); + // check once for what we just did, then again after refreshing to make + // sure the sort order 'stuck' + for (let i = 0; i < 2; i++) { + assert_equals( + viewWrapper.dbView.sortType, + Ci.nsMsgViewSortType.byAuthor, + "sort should be by author" + ); + assert_equals( + viewWrapper.dbView.sortOrder, + Ci.nsMsgViewSortOrder.ascending, + "sort order should be ascending" + ); + assert_equals( + viewWrapper.dbView.secondarySortType, + Ci.nsMsgViewSortType.bySubject, + "secondary sort should be by subject" + ); + assert_equals( + viewWrapper.dbView.secondarySortOrder, + Ci.nsMsgViewSortOrder.descending, + "secondary sort order should be descending" + ); + await view_refresh(viewWrapper); + } +}); + +/** + * Test that group-by-sort does not explode even if we try and get it to use + * sorts that are illegal for group-by-sort mode. It is important that we + * test both illegal primary sorts (fixed a while back) plus illegal + * secondary sorts (fixing now). + * + * Note: Sorting changes are synchronous, but toggling grouped by sort requires + * a view rebuild. + */ +add_task(async function test_sort_group_by_sort() { + let viewWrapper = make_view_wrapper(); + // we need to put messages in the folder or the sort logic doesn't actually + // save the sort state. (this is the C++ view's fault.) + let [[folder]] = await messageInjection.makeFoldersWithSets(1, [{}]); + await view_open(viewWrapper, folder); + + // - start out by being in an illegal (for group-by-sort) sort mode and + // switch to group-by-sort. + // (sorting changes are synchronous) + viewWrapper.sort(Ci.nsMsgViewSortType.byId, Ci.nsMsgViewSortOrder.descending); + await view_group_by_sort(viewWrapper, true); + + // there should have been no explosion, and we should have changed to date + assert_equals( + viewWrapper.primarySortType, + Ci.nsMsgViewSortType.byDate, + "sort should have reset to date" + ); + + // - return to unthreaded, have an illegal secondary sort, go group-by-sort + await view_group_by_sort(viewWrapper, false); + + viewWrapper.sort( + Ci.nsMsgViewSortType.byDate, + Ci.nsMsgViewSortOrder.descending, + Ci.nsMsgViewSortType.byId, + Ci.nsMsgViewSortOrder.descending + ); + + await view_group_by_sort(viewWrapper, true); + // we should now only have a single sort type and it should be date + assert_equals( + viewWrapper._sort.length, + 1, + "we should only have one sort type active" + ); + assert_equals( + viewWrapper.primarySortType, + Ci.nsMsgViewSortType.byDate, + "remaining (primary) sort type should be date" + ); + + // - try and make group-by-sort sort by something illegal + // (we're still in group-by-sort mode) + viewWrapper.magicSort( + Ci.nsMsgViewSortType.byId, + Ci.nsMsgViewSortOrder.descending + ); + assert_equals( + viewWrapper.primarySortType, + Ci.nsMsgViewSortType.byDate, + "remaining (primary) sort type should be date" + ); +}); + +/** + * Verify that mailview changes are properly persisted but that we only use them + * when the listener indicates we should use them (because the widget is + * presumably visible). + */ +add_task(async function test_mailviews_persistence() { + let viewWrapper = make_view_wrapper(); + let folder = await messageInjection.makeEmptyFolder(); + + // open the folder, ensure it is using the default mail view + await view_open(viewWrapper, folder); + Assert.equal(viewWrapper.mailViewIndex, MailViewConstants.kViewItemAll); + + // set the view so as to be persisted + viewWrapper.setMailView(MailViewConstants.kViewItemUnread); + // ...but first make sure it took at all + Assert.equal(viewWrapper.mailViewIndex, MailViewConstants.kViewItemUnread); + + // close, re-open and verify it took + viewWrapper.close(); + await view_open(viewWrapper, folder); + Assert.equal(viewWrapper.mailViewIndex, MailViewConstants.kViewItemUnread); + + // close, turn off the mailview usage indication by the listener... + viewWrapper.close(); + gMockViewWrapperListener.shouldUseMailViews = false; + // ...open and verify that it did not take! + await view_open(viewWrapper, folder); + Assert.equal(viewWrapper.mailViewIndex, MailViewConstants.kViewItemAll); + + // put the mailview setting back so other tests work + gMockViewWrapperListener.shouldUseMailViews = true; +}); + +/** + * Make sure: + * - View update depth increments / decrements as expected, and triggers a + * view rebuild when expected. + * - View update depth can't go below zero resulting in odd happenings. + * - That the view update depth is zeroed by a close so that we don't + * get into awkward states. + * + * @bug 498145 + */ +add_task(function test_view_update_depth_logic() { + let viewWrapper = make_view_wrapper(); + + // create an instance-specific dummy method that counts calls t + // _applyViewChanges + let applyViewCount = 0; + viewWrapper._applyViewChanges = function () { + applyViewCount++; + }; + + // - view update depth basics + Assert.equal(viewWrapper._viewUpdateDepth, 0); + viewWrapper.beginViewUpdate(); + Assert.equal(viewWrapper._viewUpdateDepth, 1); + viewWrapper.beginViewUpdate(); + Assert.equal(viewWrapper._viewUpdateDepth, 2); + viewWrapper.endViewUpdate(); + Assert.equal(applyViewCount, 0); + Assert.equal(viewWrapper._viewUpdateDepth, 1); + viewWrapper.endViewUpdate(); + Assert.equal(applyViewCount, 1); + Assert.equal(viewWrapper._viewUpdateDepth, 0); + + // - don't go below zero! (and don't trigger.) + applyViewCount = 0; + viewWrapper.endViewUpdate(); + Assert.equal(applyViewCount, 0); + Assert.equal(viewWrapper._viewUpdateDepth, 0); + + // - depth zeroed on clear + viewWrapper.beginViewUpdate(); + viewWrapper.close(); // this does little else because there is nothing open + Assert.equal(viewWrapper._viewUpdateDepth, 0); +}); -- cgit v1.2.3