summaryrefslogtreecommitdiffstats
path: root/comm/mail/base/test/unit/test_viewWrapper_logic.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/base/test/unit/test_viewWrapper_logic.js')
-rw-r--r--comm/mail/base/test/unit/test_viewWrapper_logic.js359
1 files changed, 359 insertions, 0 deletions
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);
+});