aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-31 11:58:57 +0100
committerDanilo M. <danix@danix.xyz>2026-10-31 11:58:57 +0100
commit3474936404df92ac08534c010aed94f97e6fca15 (patch)
tree9a182d3d540519b6c9e217b0ab4f95d45d77281a /tests
parentf0786b2bdd9a29531e43f0aa1573c0ab51fc02e1 (diff)
downloadqtmaildir-3474936404df92ac08534c010aed94f97e6fca15.tar.gz
qtmaildir-3474936404df92ac08534c010aed94f97e6fca15.zip
fix: keep the rules banner true after Apply, delete and copy
The dialog stays open after Apply, so a refusal from a failed attempt and the load warnings about a file Apply has just rewritten both outlived what they described. A successful Apply rereads the file and redraws the banner. Deleting the last rule now disables Apply, and copying or deleting a rule re-checks which rules the sync hook will skip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/test_tagrules.cpp83
1 files changed, 82 insertions, 1 deletions
diff --git a/tests/test_tagrules.cpp b/tests/test_tagrules.cpp
index 27496ce..9501213 100644
--- a/tests/test_tagrules.cpp
+++ b/tests/test_tagrules.cpp
@@ -39,6 +39,9 @@ private slots:
void applyEmitsNothingWhenTheSaveFails();
void theArchiveBoxMapsToAllowArchive();
void aRuleTheHookWillSkipIsNamedInTheWarning();
+ void aSuccessfulApplyClearsStaleBanners();
+ void deletingTheLastRuleDisablesApply();
+ void copyingAndDeletingRecheckTheSkipWarning();
void allowArchiveRoundTripsAndIsOmittedWhenFalse();
void allowArchiveIsDroppedFromARuleThatKeepsInbox();
void hookWouldSkipMirrorsThePostNewRefusal();
@@ -1665,12 +1668,17 @@ void TestTagRules::aRuleTheHookWillSkipIsNamedInTheWarning()
writeDialogRules(home, R"({"version": 1, "rules": [
{"id": "promo", "add": ["promo"], "remove": ["inbox"],
"query": "from:a@example.org"},
- {"id": "fine", "add": ["x"], "query": "from:b@example.org"}]})");
+ {"id": "fine", "add": ["x"], "query": "from:b@example.org"},
+ {"id": "dormant", "add": ["y"], "remove": ["inbox"], "enabled": false,
+ "query": "from:c@example.org"}]})");
TagRulesDialog dialog;
QVERIFY2(dialog.warningTextForTest().contains(QStringLiteral("promo")),
qPrintable(dialog.warningTextForTest()));
QVERIFY(!dialog.warningTextForTest().contains(QStringLiteral("fine")));
+ // The hook never runs a disabled rule, so it skips nothing there.
+ QVERIFY2(!dialog.warningTextForTest().contains(QStringLiteral("dormant")),
+ qPrintable(dialog.warningTextForTest()));
dialog.selectRuleForTest(0);
dialog.setArchiveForTest(true);
@@ -1678,5 +1686,78 @@ void TestTagRules::aRuleTheHookWillSkipIsNamedInTheWarning()
qPrintable(dialog.warningTextForTest()));
}
+void TestTagRules::aSuccessfulApplyClearsStaleBanners()
+{
+ // The dialog stays open after Apply, so a refusal from a failed attempt
+ // and a load warning about a file Apply has just rewritten would both
+ // outlive what they describe.
+ QTemporaryDir home;
+ QVERIFY(home.isValid());
+ qputenv("XDG_CONFIG_HOME", home.path().toUtf8());
+ writeDialogRules(home, R"({"version": 1, "rules": [
+ {"id": "justeat orders", "add": ["promo"],
+ "query": "from:a@example.org"}]})");
+
+ TagRulesDialog dialog;
+ const QString needsAttention = QStringLiteral("need attention");
+ QVERIFY2(dialog.warningTextForTest().contains(needsAttention),
+ qPrintable(dialog.warningTextForTest()));
+
+ QSignalSpy spy(&dialog, &TagRulesDialog::applyRequested);
+ dialog.selectRuleForTest(0);
+ dialog.setTagsForTest(QString());
+ dialog.applyForTest();
+ QVERIFY(spy.isEmpty());
+ const QString refusal = QStringLiteral("cannot be saved");
+ QVERIFY2(dialog.warningTextForTest().contains(refusal),
+ qPrintable(dialog.warningTextForTest()));
+
+ dialog.setTagsForTest(QStringLiteral("promo"));
+ dialog.applyForTest();
+ QCOMPARE(spy.size(), 1);
+ QVERIFY2(!dialog.warningTextForTest().contains(refusal),
+ qPrintable(dialog.warningTextForTest()));
+ QVERIFY2(!dialog.warningTextForTest().contains(needsAttention),
+ qPrintable(dialog.warningTextForTest()));
+}
+
+void TestTagRules::deletingTheLastRuleDisablesApply()
+{
+ QTemporaryDir home;
+ QVERIFY(home.isValid());
+ qputenv("XDG_CONFIG_HOME", home.path().toUtf8());
+ writeDialogRules(home, R"({"version": 1, "rules": [
+ {"id": "promo", "add": ["promo"], "query": "from:a@example.org"}]})");
+
+ TagRulesDialog dialog;
+ dialog.selectRuleForTest(0);
+ QVERIFY(dialog.applyEnabledForTest());
+ dialog.deleteRuleForTest();
+ QCOMPARE(dialog.ruleCountForTest(), 0);
+ QVERIFY(!dialog.applyEnabledForTest());
+}
+
+void TestTagRules::copyingAndDeletingRecheckTheSkipWarning()
+{
+ QTemporaryDir home;
+ QVERIFY(home.isValid());
+ qputenv("XDG_CONFIG_HOME", home.path().toUtf8());
+ writeDialogRules(home, R"({"version": 1, "rules": [
+ {"id": "promo", "add": ["promo"], "remove": ["inbox"],
+ "query": "from:a@example.org"}]})");
+
+ TagRulesDialog dialog;
+ dialog.selectRuleForTest(0);
+ dialog.copyRuleForTest(); // selects the copy
+ QVERIFY2(dialog.warningTextForTest().contains(QStringLiteral("promo-copy")),
+ qPrintable(dialog.warningTextForTest()));
+
+ dialog.deleteRuleForTest();
+ QVERIFY2(!dialog.warningTextForTest().contains(QStringLiteral("promo-copy")),
+ qPrintable(dialog.warningTextForTest()));
+ QVERIFY2(dialog.warningTextForTest().contains(QStringLiteral("promo")),
+ qPrintable(dialog.warningTextForTest()));
+}
+
QTEST_MAIN(TestTagRules)
#include "test_tagrules.moc"