diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_mainwindow.cpp | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp index e89ad69..8ffa806 100644 --- a/tests/test_mainwindow.cpp +++ b/tests/test_mainwindow.cpp @@ -330,6 +330,10 @@ private slots: void anEmptySelectorSetChangesNothing(); void aBracketedMessageSelectorOpensThatMessage(); void anAccountSelectorAloneShowsThatAccountsStartupView(); + void aMessageSelectorFindsItsThreadInAnyAccount(); + void aThreadSelectorFindsItsThreadInAnyAccount(); + void aThreadOutsideTheGivenAccountIsAMissAndRestoresTheView(); + void aThreadThatExistsNowhereIsAMissAndRestoresTheView(); void everyBuiltinFilterButtonCarriesAnIconAndItsText(); void theDraftsButtonIsAbsentWithoutADraftsFolder(); void aQueryInTheMenuCanActuallyBeRun(); @@ -18201,4 +18205,154 @@ void TestMainWindow::anAccountSelectorAloneShowsThatAccountsStartupView() QCOMPARE(model->threadAt(0).subject, QStringLiteral("Work subject")); } +void TestMainWindow::aMessageSelectorFindsItsThreadInAnyAccount() +{ + // The window is scoped to work and the message lives in personal. The + // recovery runs thread:<id> in the dropdown's scope, so without --account + // the conversation was searched for in work alone, came back empty, and + // the list went blank with nothing said. With no account asked for, the + // conversation is found wherever it lives. + WorkerBackedWindow backed; + QVERIFY2(buildTwoAccounts(backed), qPrintable(backed.error())); + + NotmuchWorker probe(backed.config().notmuchConfig()); + const QString threadId = + probe.threadIdForTesting(QStringLiteral("id:p1@example.org")); + QVERIFY(!threadId.isEmpty()); + + MainWindow window(backed.config()); + auto *model = window.findChild<ThreadListModel *>(); + QVERIFY(model); + auto *view = window.findChild<ThreadListView *>(); + QVERIFY(view); + window.selectAccountForTesting(QStringLiteral("work")); + QCOMPARE(window.selectedAccountForTesting(), QStringLiteral("work")); + + LaunchSelectors selectors; + selectors.messageId = QStringLiteral("p1@example.org"); + window.applySelectors(selectors); + + QTRY_VERIFY_WITH_TIMEOUT(view->currentIndex().isValid() + && model->threadFor(view->currentIndex()) + .threadId + == threadId, + 15000); + // "All accounts" is the entry with no account key. + QCOMPARE(window.selectedAccountForTesting(), QString()); +} + +void TestMainWindow::aThreadSelectorFindsItsThreadInAnyAccount() +{ + // The --thread twin of the case above. A separate code path in + // applySelectors(), so it needs its own test: the message one passes with + // this path left scoped to work. + WorkerBackedWindow backed; + QVERIFY2(buildTwoAccounts(backed), qPrintable(backed.error())); + + NotmuchWorker probe(backed.config().notmuchConfig()); + const QString threadId = + probe.threadIdForTesting(QStringLiteral("id:p1@example.org")); + QVERIFY(!threadId.isEmpty()); + + MainWindow window(backed.config()); + auto *model = window.findChild<ThreadListModel *>(); + QVERIFY(model); + auto *view = window.findChild<ThreadListView *>(); + QVERIFY(view); + window.selectAccountForTesting(QStringLiteral("work")); + QCOMPARE(window.selectedAccountForTesting(), QStringLiteral("work")); + + LaunchSelectors selectors; + selectors.threadId = threadId; + window.applySelectors(selectors); + + QTRY_VERIFY_WITH_TIMEOUT(view->currentIndex().isValid() + && model->threadFor(view->currentIndex()) + .threadId + == threadId, + 15000); + QCOMPARE(window.selectedAccountForTesting(), QString()); +} + +/// Waits for the startup view to land and returns the query it ran, so a +/// test can assert the same view came back after a miss. +static QString settledStartupQuery(MainWindow &window, ThreadListModel *model) +{ + if (!QTest::qWaitFor([&]() { return model->rowCount(QModelIndex()) == 2; }, + 15000)) + return QString(); + return window.lastRunQueryForTesting(); +} + +void TestMainWindow::aThreadOutsideTheGivenAccountIsAMissAndRestoresTheView() +{ + // --account work --thread <a personal thread>. The account was asked for, + // so the scope is kept and the thread is not found in it. That is a miss, + // and a miss names itself and leaves the user on the view they had rather + // than on an empty list. + WorkerBackedWindow backed; + QVERIFY2(buildTwoAccounts(backed), qPrintable(backed.error())); + + NotmuchWorker probe(backed.config().notmuchConfig()); + const QString threadId = + probe.threadIdForTesting(QStringLiteral("id:p1@example.org")); + QVERIFY(!threadId.isEmpty()); + + MainWindow window(backed.config()); + auto *model = window.findChild<ThreadListModel *>(); + QVERIFY(model); + auto *status = window.findChild<QLabel *>(QStringLiteral("statusMessage")); + QVERIFY(status); + + const QString before = settledStartupQuery(window, model); + QVERIFY(!before.isEmpty()); + const quint64 generation = window.currentGenerationForTesting(); + + LaunchSelectors selectors; + selectors.account = QStringLiteral("work"); + selectors.threadId = threadId; + window.applySelectors(selectors); + + // The thread query DID run in the work scope, which is what makes this the + // out-of-scope case rather than one refused before reaching notmuch. + QVERIFY(window.currentGenerationForTesting() > generation); + + QTRY_VERIFY_WITH_TIMEOUT(status->text().contains(threadId) + && window.lastRunQueryForTesting() == before + && model->rowCount(QModelIndex()) == 2, + 15000); + QCOMPARE(window.selectedAccountForTesting(), QString()); +} + +void TestMainWindow::aThreadThatExistsNowhereIsAMissAndRestoresTheView() +{ + // Well-formed hex, so it passes the syntax check and reaches notmuch, and + // matches nothing there. A stale link, which is the ordinary miss. + WorkerBackedWindow backed; + QVERIFY2(buildTwoAccounts(backed), qPrintable(backed.error())); + + MainWindow window(backed.config()); + auto *model = window.findChild<ThreadListModel *>(); + QVERIFY(model); + auto *status = window.findChild<QLabel *>(QStringLiteral("statusMessage")); + QVERIFY(status); + + const QString before = settledStartupQuery(window, model); + QVERIFY(!before.isEmpty()); + + const QString missing = QStringLiteral("0123456789abcdef"); + LaunchSelectors selectors; + selectors.threadId = missing; + window.applySelectors(selectors); + + QTRY_VERIFY_WITH_TIMEOUT(status->text().contains(missing) + && window.lastRunQueryForTesting() == before + && model->rowCount(QModelIndex()) == 2, + 15000); + // Still a miss a moment later: the restored query landing must not stamp + // its row count over the notice. + QTest::qWait(200); + QVERIFY(status->text().contains(missing)); +} + #include "test_mainwindow.moc" |
