aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-28 11:26:41 +0200
committerDanilo M. <danix@danix.xyz>2026-08-28 11:26:41 +0200
commit9bec59c98a9f00e6e7f2c0181659a7639bc04e72 (patch)
treeb250c7e96c26626a554e3b26b020ce2ecb1fd921 /tests
parent0133fb982da2dcbbfacb9e89b0de79dd483b39fb (diff)
downloadqtmaildir-9bec59c98a9f00e6e7f2c0181659a7639bc04e72.tar.gz
qtmaildir-9bec59c98a9f00e6e7f2c0181659a7639bc04e72.zip
feat: let a row say whether it is a conversation
One predicate for the question every scope, label and membership decision in item 177 keys on. It repeats hasChildren()'s rule deliberately: an expander and a conversation are the same fact, including that a loaded thread trusts its children over a count that included duplicates.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_threadlistmodel.cpp79
1 files changed, 79 insertions, 0 deletions
diff --git a/tests/test_threadlistmodel.cpp b/tests/test_threadlistmodel.cpp
index 9ca35e3..df579e6 100644
--- a/tests/test_threadlistmodel.cpp
+++ b/tests/test_threadlistmodel.cpp
@@ -105,6 +105,10 @@ private slots:
void aRowCarriesItsSenderAndAccountAddress();
void aMessageRowCarriesItsOwnSenderAndAddress();
void aFlatViewsAvatarFollowsTheRecipient();
+ void aSummaryWithOneMessageIsAMessageRow();
+ void aSummaryWithRepliesIsAConversationRow();
+ void aLoadedThreadTrustsItsChildrenOverItsCount();
+ void aMessageRowIsNeverAConversationRow();
};
static ThreadSummary makeThread(const QString &id, const QString &subject)
@@ -2343,5 +2347,80 @@ void TestThreadListModel::theTrashViewDrawsNoDoomedFill()
QVERIFY(first.data(Qt::BackgroundRole).isValid());
}
+void TestThreadListModel::aSummaryWithOneMessageIsAMessageRow()
+{
+ ThreadListModel model;
+ ThreadSummary one = makeThread(QStringLiteral("t1"), QStringLiteral("Alone"));
+ one.totalCount = 1;
+ one.firstMessageId = QStringLiteral("m1");
+ model.appendBatch({ one });
+
+ const QModelIndex row = model.index(0, 0, QModelIndex());
+ QVERIFY2(!model.isConversationRow(row),
+ "a thread of one message is not a conversation: it has no replies "
+ "to stand for, and must open its message on one click");
+}
+
+void TestThreadListModel::aSummaryWithRepliesIsAConversationRow()
+{
+ ThreadListModel model;
+ ThreadSummary many = makeThread(QStringLiteral("t1"), QStringLiteral("Talk"));
+ many.totalCount = 4;
+ many.firstMessageId = QStringLiteral("m1");
+ model.appendBatch({ many });
+
+ const QModelIndex row = model.index(0, 0, QModelIndex());
+ QVERIFY(model.isConversationRow(row));
+}
+
+void TestThreadListModel::aLoadedThreadTrustsItsChildrenOverItsCount()
+{
+ // notmuch's totalCount counts duplicates, so a "thread of 2" can load with
+ // no replies at all. Once loaded the children are the truth, exactly as
+ // hasChildren() already decides.
+ ThreadListModel model;
+ ThreadSummary many = makeThread(QStringLiteral("t1"), QStringLiteral("Dupe"));
+ many.totalCount = 2;
+ many.firstMessageId = QStringLiteral("m1");
+ model.appendBatch({ many });
+
+ MessageNode root;
+ root.messageId = QStringLiteral("m1");
+ root.threadId = QStringLiteral("t1");
+ root.depth = 0;
+ model.setThreadMessages(QStringLiteral("t1"), { root });
+
+ const QModelIndex row = model.index(0, 0, QModelIndex());
+ QVERIFY2(!model.isConversationRow(row),
+ "a thread whose count came from duplicates still claims to be a "
+ "conversation after loading no replies at all");
+}
+
+void TestThreadListModel::aMessageRowIsNeverAConversationRow()
+{
+ ThreadListModel model;
+ ThreadSummary many = makeThread(QStringLiteral("t1"), QStringLiteral("Talk"));
+ many.totalCount = 2;
+ many.firstMessageId = QStringLiteral("m1");
+ model.appendBatch({ many });
+
+ MessageNode root;
+ root.messageId = QStringLiteral("m1");
+ root.threadId = QStringLiteral("t1");
+ root.depth = 0;
+ MessageNode reply;
+ reply.messageId = QStringLiteral("m2");
+ reply.threadId = QStringLiteral("t1");
+ reply.depth = 1;
+ model.setThreadMessages(QStringLiteral("t1"), { root, reply });
+
+ const QModelIndex thread = model.index(0, 0, QModelIndex());
+ const QModelIndex replyRow = model.index(0, 0, thread);
+ QVERIFY(model.isMessageRow(replyRow));
+ QVERIFY2(!model.isConversationRow(replyRow),
+ "a reply row answered yes, so an action on it would scope to the "
+ "whole conversation");
+}
+
QTEST_MAIN(TestThreadListModel)
#include "test_threadlistmodel.moc"