aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_mainwindow.cpp44
-rw-r--r--tests/test_threadlistmodel.cpp42
2 files changed, 86 insertions, 0 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
index b4d9e4a..ab904f9 100644
--- a/tests/test_mainwindow.cpp
+++ b/tests/test_mainwindow.cpp
@@ -25,10 +25,13 @@
#include <QStandardPaths>
#include <QTemporaryDir>
+#include <QTableView>
+
#include "config.h"
#include "keymap.h"
#include "mainwindow.h"
#include "messageview.h"
+#include "threadlistmodel.h"
/// MainWindow is mostly wiring, and the parts that need a real database are
/// still verified manually. What is checked here is the action registry: the
@@ -47,6 +50,7 @@ private slots:
void uiStateIsNotWrittenIntoTheUserConfig();
void uiStateSurvivesARestart();
void missingUiStateLeavesTheDefaults();
+ void headerStateFromADifferentColumnLayoutIsDiscarded();
};
void TestMainWindow::everyKnownActionIsRegistered()
@@ -222,6 +226,46 @@ void TestMainWindow::missingUiStateLeavesTheDefaults()
QStandardPaths::setTestModeEnabled(false);
}
+void TestMainWindow::headerStateFromADifferentColumnLayoutIsDiscarded()
+{
+ // The upgrade hazard: a 0.3.0 state file holds a three-column header blob,
+ // and 0.4.0 added the attachment column in front. QHeaderView::
+ // restoreState() returns TRUE for a blob with fewer sections than the
+ // model and applies the old widths shifted one column right, mangling the
+ // layout with no error to detect it by (verified on Qt 6.11). The stored
+ // column count is what makes that detectable.
+ QStandardPaths::setTestModeEnabled(true);
+ QFile::remove(MainWindow::uiStatePath());
+
+ {
+ const Config config;
+ MainWindow window(config);
+ window.close();
+ }
+
+ // Forge a state file from an older layout: same blob, wrong column count.
+ {
+ QSettings state(MainWindow::uiStatePath(), QSettings::IniFormat);
+ state.setValue(QStringLiteral("threadlist/columns"),
+ int(ThreadListModel::ColumnCount) - 1);
+ state.setValue(QStringLiteral("threadlist/header"),
+ QByteArray("not a header this model could have saved"));
+ }
+
+ // Constructing must not apply it, and must not crash on the garbage blob.
+ const Config config;
+ MainWindow reopened(config);
+
+ auto *view = reopened.findChild<QTableView *>();
+ QVERIFY(view);
+ QCOMPARE(view->columnWidth(ThreadListModel::AttachmentColumn), 28);
+ QCOMPARE(view->columnWidth(ThreadListModel::DateColumn), 130);
+ QCOMPARE(view->columnWidth(ThreadListModel::SubjectColumn), 520);
+
+ QFile::remove(MainWindow::uiStatePath());
+ QStandardPaths::setTestModeEnabled(false);
+}
+
// Constructing a MainWindow needs a QApplication and a platform plugin. The
// test has no display under ctest, so it runs offscreen unless the caller
// asked for something else.
diff --git a/tests/test_threadlistmodel.cpp b/tests/test_threadlistmodel.cpp
index e8a5fa8..97f7fde 100644
--- a/tests/test_threadlistmodel.cpp
+++ b/tests/test_threadlistmodel.cpp
@@ -38,6 +38,7 @@ private slots:
void unreadStylingSurvivesAnAccountChip();
void accountChipUsesTheConfiguredColour();
void deletedThreadsAreRedAndStruckThrough();
+ void attachmentColumnIsFirstAndMarksOnlyTaggedThreads();
void spamThreadsAreOrangeAndStruckThrough();
void doomedStylingCoversEveryColumn();
void ordinaryThreadsCarryNoRowColour();
@@ -472,5 +473,46 @@ void TestThreadListModel::modelPassesQtTester()
model.clear();
}
+void TestThreadListModel::attachmentColumnIsFirstAndMarksOnlyTaggedThreads()
+{
+ // Leftmost, and narrow: the point is to see an attachment without opening
+ // the thread, which only works if the column is never scrolled away.
+ QCOMPARE(ThreadListModel::AttachmentColumn, 0);
+
+ ThreadSummary plain = makeThread(QStringLiteral("t1"),
+ QStringLiteral("no attachment"));
+ ThreadSummary withFile = makeThread(QStringLiteral("t2"),
+ QStringLiteral("has one"));
+ // notmuch applies this tag itself while indexing, so no MIME parsing and
+ // no extra worker query are involved.
+ withFile.tags.append(QStringLiteral("attachment"));
+
+ ThreadListModel model;
+ model.appendBatch({ plain, withFile });
+
+ const QModelIndex plainCell =
+ model.index(0, ThreadListModel::AttachmentColumn);
+ const QModelIndex fileCell =
+ model.index(1, ThreadListModel::AttachmentColumn);
+
+ QVERIFY(model.data(plainCell, Qt::DisplayRole).toString().isEmpty());
+ QCOMPARE(model.data(fileCell, Qt::DisplayRole).toString(),
+ ThreadListModel::attachmentGlyph());
+
+ // The glyph must be something a font can draw. An unrenderable codepoint
+ // shows as a tofu box, which reads as breakage rather than as a marker.
+ QVERIFY(!ThreadListModel::attachmentGlyph().isEmpty());
+
+ // Only the marked thread gets a tooltip, or an empty cell would claim to
+ // have an attachment on hover.
+ QVERIFY(model.data(plainCell, Qt::ToolTipRole).toString().isEmpty());
+ QVERIFY(!model.data(fileCell, Qt::ToolTipRole).toString().isEmpty());
+
+ // The header carries no text: a label would set a minimum width far wider
+ // than the icon and defeat the narrow column.
+ QVERIFY(model.headerData(ThreadListModel::AttachmentColumn, Qt::Horizontal,
+ Qt::DisplayRole).toString().isEmpty());
+}
+
QTEST_MAIN(TestThreadListModel)
#include "test_threadlistmodel.moc"