summaryrefslogtreecommitdiffstats
path: root/tests/test_signatures.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-24 20:00:45 +0200
committerDanilo M. <danix@danix.xyz>2026-08-24 20:00:45 +0200
commit86af01996dd702bdc3f837e96f154088e8b45538 (patch)
tree26d236b2780ca08e31f12ad70c9f10c1f6663d29 /tests/test_signatures.cpp
parentbe2534ab60d362b2f685130265f727190ccf867a (diff)
downloadqtmaildir-86af01996dd702bdc3f837e96f154088e8b45538.tar.gz
qtmaildir-86af01996dd702bdc3f837e96f154088e8b45538.zip
feat(signatures): replace an existing signature, guarded by a match
Finding a "-- " delimiter is not authority to delete what follows it. The block is replaced only when its text matches one of the signatures on disk, and otherwise the new one is inserted with nothing removed, so a wrong guess adds a visible duplicate rather than destroying the user's writing. A quoted delimiter is never the signature either: the quoted original carries the other party's, and it is not this message's to replace. The block's lower boundary is quoteStart(), not the first quoted line. The attribution introduces the quote and belongs with it, so scanning for '>' alone swallowed "On Mon, someone wrote:" into the signature block: it then matched no known signature, and had it matched, removal would have stranded the attribution above the text it introduces. The boundary the insertion uses and the boundary the removal uses have to be the same one. The guard's test was mutation-checked by making the match unconditional, which fails it. Part of item 152.
Diffstat (limited to 'tests/test_signatures.cpp')
-rw-r--r--tests/test_signatures.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/tests/test_signatures.cpp b/tests/test_signatures.cpp
index 30085fb..5f01cf9 100644
--- a/tests/test_signatures.cpp
+++ b/tests/test_signatures.cpp
@@ -35,6 +35,11 @@ private slots:
void insertingAboveTheQuotePutsItBeforeTheFirstQuotedLine();
void insertingAboveTheQuoteWithNoQuoteIsTheSameAsEnd();
void insertingNothingLeavesTheBufferAlone();
+ void switchingReplacesAKnownSignature();
+ void switchingReplacesAKnownSignatureAboveAQuote();
+ void selectingNoneRemovesAKnownSignature();
+ void aBlockMatchingNoKnownSignatureIsNotRemoved();
+ void aDelimiterInsideTheQuoteIsNotTheSignature();
private:
/// Writes \p files as name -> content into a fresh temporary directory.
@@ -162,5 +167,101 @@ void TestSignatures::insertingNothingLeavesTheBufferAlone()
buffer);
}
+void TestSignatures::switchingReplacesAKnownSignature()
+{
+ const QStringList known = { QStringLiteral("Jane Doe"),
+ QStringLiteral("Jane Doe\nqtmaildir") };
+ const QString buffer = QStringLiteral("Hello.\n\n-- \nJane Doe");
+
+ const QString result = Signatures::replace(
+ buffer, QStringLiteral("Jane Doe\nqtmaildir"), known,
+ Signatures::Position::End);
+
+ QCOMPARE(result,
+ QStringLiteral("Hello.\n\n-- \nJane Doe\nqtmaildir"));
+}
+
+void TestSignatures::switchingReplacesAKnownSignatureAboveAQuote()
+{
+ const QStringList known = { QStringLiteral("Jane Doe"),
+ QStringLiteral("Brief") };
+ const QString buffer = QStringLiteral(
+ "My reply.\n"
+ "\n"
+ "-- \n"
+ "Jane Doe\n"
+ "\n"
+ "On Mon, someone wrote:\n"
+ "> the original\n");
+
+ const QString result = Signatures::replace(
+ buffer, QStringLiteral("Brief"), known,
+ Signatures::Position::AboveQuote);
+
+ QCOMPARE(result, QStringLiteral(
+ "My reply.\n"
+ "\n"
+ "-- \n"
+ "Brief\n"
+ "\n"
+ "On Mon, someone wrote:\n"
+ "> the original\n"));
+}
+
+void TestSignatures::selectingNoneRemovesAKnownSignature()
+{
+ const QStringList known = { QStringLiteral("Jane Doe") };
+ const QString buffer = QStringLiteral("Hello.\n\n-- \nJane Doe");
+
+ const QString result = Signatures::replace(
+ buffer, QString(), known, Signatures::Position::End);
+
+ QCOMPARE(result, QStringLiteral("Hello.\n"));
+}
+
+void TestSignatures::aBlockMatchingNoKnownSignatureIsNotRemoved()
+{
+ // THE test for the data-loss guard, and it must not be dropped. A "-- "
+ // reaches a buffer without the user ever choosing a signature, pasted in
+ // with quoted text from another client. Replacing from there would delete
+ // everything after it silently.
+ const QStringList known = { QStringLiteral("Jane Doe") };
+ const QString buffer = QStringLiteral(
+ "Hello.\n"
+ "\n"
+ "-- \n"
+ "text the user pasted and wants to keep");
+
+ const QString result = Signatures::replace(
+ buffer, QStringLiteral("Jane Doe"), known, Signatures::Position::End);
+
+ // The user's text survives, and the signature is ADDED. A wrong guess
+ // produces a visible duplicate, never a deletion.
+ QVERIFY(result.contains(
+ QStringLiteral("text the user pasted and wants to keep")));
+ QVERIFY(result.endsWith(QStringLiteral("-- \nJane Doe")));
+}
+
+void TestSignatures::aDelimiterInsideTheQuoteIsNotTheSignature()
+{
+ // The quoted original carries the sender's own signature, quoted. A tail
+ // rule would find it, and under End it would append after it; the block
+ // must not be treated as this message's signature whichever way it goes.
+ const QStringList known = { QStringLiteral("Jane Doe") };
+ const QString buffer = QStringLiteral(
+ "My reply.\n"
+ "\n"
+ "On Mon, someone wrote:\n"
+ "> the original\n"
+ "> -- \n"
+ "> Their Name\n");
+
+ const QString result = Signatures::replace(
+ buffer, QStringLiteral("Jane Doe"), known, Signatures::Position::End);
+
+ QVERIFY(result.contains(QStringLiteral("> -- \n> Their Name")));
+ QVERIFY(result.endsWith(QStringLiteral("-- \nJane Doe")));
+}
+
QTEST_MAIN(TestSignatures)
#include "test_signatures.moc"