aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_mainwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_mainwindow.cpp')
-rw-r--r--tests/test_mainwindow.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
index f97b9bd..1c54ebb 100644
--- a/tests/test_mainwindow.cpp
+++ b/tests/test_mainwindow.cpp
@@ -545,6 +545,7 @@ private slots:
void aNewMessageSeedsTheHtmlToggleFromConfig();
void disablingInputsCoversEveryFieldAndTheToolbar();
void aFiledSentCopyIsAnnouncedForIndexing();
+ void aSentMessageAppearsInASentViewAlreadyOnScreen();
void aFailedSendCanBeRetriedWithoutFilingTheWrongCopy();
void anUnchangedMessageIsNotWrittenAgain();
void closingInsideTheDebounceStillSavesTheDraft();
@@ -15136,6 +15137,87 @@ void TestMainWindow::aFiledSentCopyIsAnnouncedForIndexing()
.arg(announced, sentCur)));
}
+/// Item 192's second half, from the user: indexing is not repainting.
+///
+/// The sent copy became findable the instant it was indexed and the Sent view
+/// on screen still did not show it, because nothing re-ran the query. A
+/// `path:` view is built once and holds whatever the index said then; the
+/// model cannot insert the row optimistically either, since item 170's
+/// constraint applies, the query never returned that thread.
+///
+/// So the worker reports indexChanged() and the window refreshes. Asserted
+/// end to end through a real send rather than by emitting the signal: what is
+/// unproven is that the send path reaches the refresh, and a test that emits
+/// the signal itself proves only that the connection compiles.
+///
+/// refreshCurrentQuery(), which is why the query bar is never touched again
+/// after the first run: a test that re-ran the query by hand would pass
+/// against the defect.
+void TestMainWindow::aSentMessageAppearsInASentViewAlreadyOnScreen()
+{
+ WorkerBackedWindow backed;
+ // One message, in a folder the Sent view does NOT cover. It exists so the
+ // fixture indexes at all (notmuch refuses an empty tree) and so a Sent
+ // view showing zero rows is a real answer rather than an empty database.
+ QVERIFY(backed.fixture().addMessage(
+ QStringLiteral("work/inbox"), QStringLiteral("sv0@example.org"),
+ QStringLiteral("Unrelated"), QStringLiteral("other@example.org"),
+ // Friday, verified with `date -d 2026-08-14 +%A`. Qt::RFC2822Date
+ // validates the weekday against the date.
+ QStringLiteral("Fri, 14 Aug 2026 10:00:00 +0200"),
+ QStringLiteral("Body text."), false));
+ QVERIFY2(backed.buildWithAccounts(
+ { { QStringLiteral("work"), QStringLiteral("work"),
+ QString(), QStringLiteral("/bin/true"),
+ QStringLiteral("you@example.org"), QString(),
+ QStringLiteral("Sent") } },
+ QStringLiteral("send_delay_ms=0")),
+ qPrintable(backed.error()));
+
+ MainWindow window(backed.config());
+ auto *model = window.findChild<ThreadListModel *>();
+ auto *queryEdit =
+ window.findChild<QLineEdit *>(QStringLiteral("queryEdit"));
+ QVERIFY(model && queryEdit);
+
+ // The Sent view as the application builds it: a path query over the
+ // account's sent folder. Run BEFORE the send, which is the whole point,
+ // and never run again by this test.
+ queryEdit->setText(QStringLiteral("path:\"work/Sent/**\""));
+ queryEdit->returnPressed();
+
+ // The mail root is what the composer needs and it arrives asynchronously,
+ // so this waits on it as well: openComposer() refuses without one and the
+ // send would never happen, which reads exactly like the defect.
+ QTRY_VERIFY_WITH_TIMEOUT(!window.mailRootForTesting().isEmpty(), 15000);
+ QApplication::processEvents();
+
+ // The guard. An empty view here is the state the refresh must change, and
+ // a test that started from a non-empty one could not tell a refresh from
+ // the row that was already there.
+ QCOMPARE(model->rowCount(QModelIndex()), 0);
+
+ auto *compose = window.findChild<QAction *>(QStringLiteral("compose"));
+ QVERIFY(compose);
+ compose->trigger();
+ QTRY_VERIFY_WITH_TIMEOUT(window.openComposerCount() == 1, 15000);
+ ComposeWindow *composer = window.openComposersForTest().value(0);
+ QVERIFY(composer);
+
+ auto *to = composer->findChild<QLineEdit *>(QStringLiteral("to"));
+ auto *body = composer->findChild<QPlainTextEdit *>(QStringLiteral("body"));
+ auto *sendAction =
+ composer->findChild<QAction *>(QStringLiteral("compose_send"));
+ QVERIFY(to && body && sendAction);
+ to->setText(QStringLiteral("someone@example.org"));
+ body->setPlainText(QStringLiteral("Text."));
+ sendAction->trigger();
+
+ // No further gesture: no second returnPressed(), no sync. The row must
+ // arrive because the index changed and the window noticed.
+ QTRY_VERIFY_WITH_TIMEOUT(model->rowCount(QModelIndex()) == 1, 15000);
+}
+
void TestMainWindow::disablingInputsCoversEveryFieldAndTheToolbar()
{
ComposeFixture fixture;