Revision control

Copy as Markdown

Other Tools

/* 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/. */
/**
* Tests the live view adapter for displaying messages in threads.
*/
const { LiveViewThreadedDataAdapter } = ChromeUtils.importESModule(
);
const LiveView = Components.Constructor(
"@mozilla.org/mailnews/live-view;1",
"nsILiveView"
);
add_setup(async function () {
await installDBFromFile("db/conversations.sql");
});
/**
* Tests the threaded view, with all of the messages available for all threads.
*/
add_task(async function testThreadedView() {
const liveView = new LiveView();
const adapter = new LiveViewThreadedDataAdapter(liveView);
adapter.sortBy("date", "descending");
adapter.setTree(tree);
try {
Assert.equal(adapter.rowCount, 6);
Assert.equal(adapter.rowAt(0).rowCount, 0);
Assert.equal(adapter.getCellText(0, "messageId"), "message10@invalid");
Assert.equal(adapter.getCellText(0, "threadId"), "10");
Assert.equal(adapter.rowAt(1).rowCount, 0);
Assert.equal(adapter.getCellText(1, "messageId"), "message9@invalid");
Assert.equal(adapter.getCellText(1, "threadId"), "9");
Assert.equal(adapter.rowAt(2).rowCount, 0);
Assert.equal(adapter.getCellText(2, "messageId"), "message8@invalid");
Assert.equal(adapter.getCellText(2, "threadId"), "8");
Assert.equal(adapter.rowAt(3).rowCount, 2);
Assert.equal(adapter.getCellText(3, "messageId"), "message6@invalid");
Assert.equal(adapter.getCellText(3, "threadId"), "3");
Assert.equal(adapter.rowAt(4).rowCount, 2);
Assert.equal(adapter.getCellText(4, "messageId"), "message4@invalid");
Assert.equal(adapter.getCellText(4, "threadId"), "7");
Assert.equal(adapter.rowAt(5).rowCount, 0);
Assert.equal(adapter.getCellText(5, "messageId"), "message1@invalid");
Assert.equal(adapter.getCellText(5, "threadId"), "1");
// Open thread with ID 3, which is at row 3.
adapter.toggleOpenState(3);
await tree.promiseRowCountChanged(4, 2);
await tree.promiseInvalidated(3, 5);
Assert.equal(adapter.rowCount, 8);
// Row 3 is no longer the newest message in thread 3, it's the oldest.
Assert.equal(adapter.getCellText(3, "messageId"), "message3@invalid");
Assert.equal(adapter.getCellText(3, "threadId"), "3");
// And the following rows are the rest of the thread, in ascending order.
Assert.equal(adapter.getCellText(4, "messageId"), "message5@invalid");
Assert.equal(adapter.getCellText(4, "threadId"), "3");
Assert.equal(adapter.getCellText(5, "messageId"), "message6@invalid");
Assert.equal(adapter.getCellText(5, "threadId"), "3");
Assert.equal(adapter.getCellText(6, "messageId"), "message4@invalid");
Assert.equal(adapter.getCellText(6, "threadId"), "7");
Assert.equal(adapter.getCellText(7, "messageId"), "message1@invalid");
Assert.equal(adapter.getCellText(7, "threadId"), "1");
// Open thread with ID 7, which is at row 6.
adapter.toggleOpenState(6);
await tree.promiseRowCountChanged(7, 2);
await tree.promiseInvalidated(6, 8);
Assert.equal(adapter.rowCount, 10);
// Row 6 is no longer the newest message in thread 7, it's the oldest.
Assert.equal(adapter.getCellText(6, "messageId"), "message7@invalid");
Assert.equal(adapter.getCellText(6, "threadId"), "7");
// And the following rows are the rest of the thread, in ascending order.
Assert.equal(adapter.getCellText(7, "messageId"), "message2@invalid");
Assert.equal(adapter.getCellText(7, "threadId"), "7");
Assert.equal(adapter.getCellText(8, "messageId"), "message4@invalid");
Assert.equal(adapter.getCellText(8, "threadId"), "7");
Assert.equal(adapter.getCellText(9, "messageId"), "message1@invalid");
Assert.equal(adapter.getCellText(9, "threadId"), "1");
// Close thread with ID 3, which is at row 3.
adapter.toggleOpenState(3);
await tree.promiseRowCountChanged(4, -2);
await tree.promiseInvalidated(3, 3);
Assert.equal(adapter.rowCount, 8);
// Row 3 is the newest message in thread 3 again.
Assert.equal(adapter.rowAt(3).rowCount, 2);
Assert.equal(adapter.getCellText(3, "messageId"), "message6@invalid");
Assert.equal(adapter.getCellText(3, "threadId"), "3");
Assert.equal(adapter.getCellText(4, "messageId"), "message7@invalid");
Assert.equal(adapter.getCellText(4, "threadId"), "7");
Assert.equal(adapter.getCellText(5, "messageId"), "message2@invalid");
Assert.equal(adapter.getCellText(5, "threadId"), "7");
Assert.equal(adapter.getCellText(6, "messageId"), "message4@invalid");
Assert.equal(adapter.getCellText(6, "threadId"), "7");
Assert.equal(adapter.getCellText(7, "messageId"), "message1@invalid");
Assert.equal(adapter.getCellText(7, "threadId"), "1");
} finally {
adapter.setTree(null);
}
});
/**
* Tests the threaded view, but only in a single folder so parts of a thread
* are missing.
*/
add_task(async function testThreadedViewPartialThread() {
const liveView = new LiveView();
liveView.initWithFolder(folderDB.getFolderByPath("server1/folderB"));
const adapter = new LiveViewThreadedDataAdapter(liveView);
adapter.sortBy("date", "descending");
adapter.setTree(tree);
try {
Assert.equal(adapter.rowCount, 2);
Assert.equal(adapter.getCellText(0, "messageId"), "message6@invalid");
Assert.equal(adapter.getCellText(1, "messageId"), "message4@invalid");
adapter.toggleOpenState(0);
await tree.promiseRowCountChanged(1, 2);
await tree.promiseInvalidated(0, 2);
Assert.equal(adapter.rowCount, 4);
Assert.equal(adapter.getCellText(0, "messageId"), "message3@invalid");
Assert.equal(adapter.getCellText(1, "messageId"), "message5@invalid");
Assert.equal(adapter.getCellText(2, "messageId"), "message6@invalid");
Assert.equal(adapter.getCellText(3, "messageId"), "message4@invalid");
Assert.ok(adapter.isContainerEmpty(3));
} finally {
adapter.setTree(null);
}
});
const tree = {
rowCountChanged(index, delta) {
info(`rowCountChanged(${index}, ${delta})`);
this._index = index;
this._delta = delta;
this._rowCountDeferred?.resolve();
},
invalidateRow(index) {
info(`invalidateRow(${index})`);
this._start = index;
this._end = index;
this._invalidateDeferred?.resolve();
},
invalidateRange(start, end) {
info(`invalidateRange(${start}, ${end})`);
this._start = start;
this._end = end;
this._invalidateDeferred?.resolve();
},
async promiseRowCountChanged(expectedIndex, expectedDelta) {
if (this._index === undefined) {
this._rowCountDeferred = Promise.withResolvers();
await this._rowCountDeferred.promise;
delete this._rowCountDeferred;
}
this.assertRowCountChanged(expectedIndex, expectedDelta);
},
async promiseInvalidated(expectedStart, expectedEnd) {
if (this._start === undefined) {
this._invalidateDeferred = Promise.withResolvers();
await this._invalidateDeferred.promise;
delete this._invalidateDeferred;
}
this.assertInvalidateRange(expectedStart, expectedEnd);
},
assertRowCountChanged(expectedIndex, expectedDelta) {
Assert.equal(this._index, expectedIndex);
Assert.equal(this._delta, expectedDelta);
delete this._index;
delete this._delta;
},
assertInvalidateRange(expectedStart, expectedEnd) {
Assert.equal(this._start, expectedStart);
Assert.equal(this._end, expectedEnd);
delete this._start;
delete this._end;
},
};