aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_searchterm.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-31 11:41:08 +0100
committerDanilo M. <danix@danix.xyz>2026-10-31 11:41:08 +0100
commit8804a75ae561a7e504fdce8aea58d3ddc8670b71 (patch)
tree85125d2ba1e1880f3439e7d3462247351c46ff1d /tests/test_searchterm.cpp
parent8078e8180920984de475db796a2725bb2f470dd8 (diff)
downloadqtmaildir-8804a75ae561a7e504fdce8aea58d3ddc8670b71.tar.gz
qtmaildir-8804a75ae561a7e504fdce8aea58d3ddc8670b71.zip
feat: build the query for what a tag change would move
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/test_searchterm.cpp')
-rw-r--r--tests/test_searchterm.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/tests/test_searchterm.cpp b/tests/test_searchterm.cpp
index 7a0dfd7..b704529 100644
--- a/tests/test_searchterm.cpp
+++ b/tests/test_searchterm.cpp
@@ -18,6 +18,7 @@
#include <QtTest>
+#include "config.h"
#include "searchterm.h"
/// The query grammar of the right-click search actions.
@@ -30,6 +31,9 @@ class TestSearchTerm : public QObject
{
Q_OBJECT
private slots:
+ void changesNarrowsToMessagesTheTagsWouldMove();
+ void changesKeepsADisjunctionInsideItsScope();
+ void changesWithNothingToDoMatchesNothing();
void quotesAPlainValue();
void escapesEmbeddedQuotes();
void collapsesWhitespaceAndNewlines();
@@ -185,5 +189,45 @@ void TestSearchTerm::excludeWithNothingToExcludeLeavesTheQuery()
QVERIFY(SearchTerm::exclude(QString(), QString()).isEmpty());
}
+void TestSearchTerm::changesNarrowsToMessagesTheTagsWouldMove()
+{
+ // Item 212. A message already carrying every added tag and none of the
+ // removed ones would not change, so it must not be counted or written.
+ QCOMPARE(SearchTerm::changes(QStringLiteral("from:a@example.org"),
+ { QStringLiteral("promo") },
+ { QStringLiteral("inbox") }),
+ QStringLiteral("(from:a@example.org) AND "
+ "(not tag:promo or tag:inbox)"));
+ QCOMPARE(SearchTerm::changes(QStringLiteral("from:a@example.org"),
+ { QStringLiteral("x"), QStringLiteral("y") },
+ {}),
+ QStringLiteral("(from:a@example.org) AND "
+ "(not tag:x or not tag:y)"));
+ QCOMPARE(SearchTerm::changes(QStringLiteral("from:a@example.org"), {},
+ { QStringLiteral("inbox") }),
+ QStringLiteral("(from:a@example.org) AND (tag:inbox)"));
+}
+
+void TestSearchTerm::changesKeepsADisjunctionInsideItsScope()
+{
+ // `a or b AND c` binds as `a or (b AND c)`, which would write to every
+ // message matching `a` whatever its tags. extend() parenthesises both.
+ QCOMPARE(SearchTerm::changes(QStringLiteral("from:a@example.org or "
+ "from:b@example.org"),
+ { QStringLiteral("promo") }, {}),
+ QStringLiteral("(from:a@example.org or from:b@example.org) AND "
+ "(not tag:promo)"));
+}
+
+void TestSearchTerm::changesWithNothingToDoMatchesNothing()
+{
+ // notmuch reads an EMPTY query as "match everything". A caller writing
+ // through this must never be handed one.
+ QCOMPARE(SearchTerm::changes(QString(), { QStringLiteral("x") }, {}),
+ Config::matchNothingQuery());
+ QCOMPARE(SearchTerm::changes(QStringLiteral("from:a@example.org"), {}, {}),
+ Config::matchNothingQuery());
+}
+
QTEST_MAIN(TestSearchTerm)
#include "test_searchterm.moc"