diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-27 11:51:06 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-27 11:51:06 +0200 |
| commit | edbf393cb79d20764fd224d32a195f59d19ef743 (patch) | |
| tree | cdb014ec42eac2aec84f2ef2044c66cf136c5c18 /tests/test_composewindow.cpp | |
| parent | 9c782e0c96c19525babc6c7ceb4f1a184a400169 (diff) | |
| download | qtmaildir-edbf393cb79d20764fd224d32a195f59d19ef743.tar.gz qtmaildir-edbf393cb79d20764fd224d32a195f59d19ef743.zip | |
fix: flag a saved draft seen so it is not tagged unread
DraftStore::write() was called with "D", and it uses the flag string
verbatim, so every draft this application wrote landed as :2,D. With
maildir.synchronize_flags on, notmuch tags any message lacking the S
flag `unread`, and a draft the user authored is seen by definition.
The symptom heals itself: the next sync of that folder round-trips the
file, adds S, and the tag goes away. Only the newest draft in a folder
that has not synced since shows it, which is why it read as
intermittent and why measuring an older draft finds nothing wrong.
TestComposeWindow::aSavedDraftIsFlaggedSeen() asserts both flags on the
written filename, verified failing first against "D".
TestMainWindow::anAutosaveWritesADraftAndClearsTheDirtyFlag() asserted
endsWith(":2,D"), pinning the whole flag set where its own comment said
the point was the draft flag "not left bare", so it failed against the
corrected behaviour. It checks for D within the flag set now.
Also reconciles the backlog with the user's notes: records the
forwarded-HTML defect as item 171, closes item 169 (shipped last
session, its row still read open and its section was still in the open
file), and records this fix as item 172.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AtUzfNjMD8fiYfamDd3ywW
Diffstat (limited to 'tests/test_composewindow.cpp')
| -rw-r--r-- | tests/test_composewindow.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/tests/test_composewindow.cpp b/tests/test_composewindow.cpp index 779d48c..0da61ff 100644 --- a/tests/test_composewindow.cpp +++ b/tests/test_composewindow.cpp @@ -20,6 +20,7 @@ #include <QComboBox> #include <QDir> #include <QFile> +#include <QFileInfo> #include <QMenu> #include <QPlainTextEdit> #include <QSignalSpy> @@ -62,6 +63,7 @@ private slots: void onlyTheSetterWritesTheDirtyFlag(); void theMenuBarReachesEveryComposerAction(); void saveDraftWritesAndReports(); + void aSavedDraftIsFlaggedSeen(); void theMenusReuseTheToolbarActions(); void theHtmlMenuItemTracksTheToolbarButton(); void theAgeLineFollowsTheClock(); @@ -746,6 +748,58 @@ void TestComposeWindow::saveDraftWritesAndReports() QVERIFY2(!window.isWindowModified(), "a manual save must clear the marker"); } +/// A draft is authored by the user, so it is SEEN by definition and must never +/// be tagged `unread`. +/// +/// `maildir.synchronize_flags` is on, so the tag is decided by the filename: +/// notmuch tags any message lacking the `S` flag `unread`. Writing a draft as +/// `:2,D` therefore puts it in the Unread view until the folder next syncs, +/// at which point mbsync round-trips the file and the `S` appears. That is +/// what made the defect look intermittent: only the newest draft, in a folder +/// that has not synced since, shows the symptom. Measured on the user's own +/// mail 2026-08-27, where two drafts written two minutes apart differed only +/// in whether their folder had synced afterwards. +/// +/// Asserting on the FILENAME rather than on a notmuch tag is deliberate: the +/// flags are what the code here controls, and a tag assertion would need an +/// indexed database to say the same thing less directly. +void TestComposeWindow::aSavedDraftIsFlaggedSeen() +{ + const Config config = configWithDrafts(); + + ComposeContext context; + context.kind = ComposeContext::Kind::New; + context.accountKey = QStringLiteral("work"); + + ComposeWindow window(context, config, m_dir->path()); + auto *body = window.findChild<QPlainTextEdit *>(QStringLiteral("body")); + QVERIFY(body); + body->setPlainText(QStringLiteral("A draft the user wrote.")); + + QSignalSpy saved(&window, &ComposeWindow::draftSaved); + auto *save = window.findChild<QAction *>(QStringLiteral("compose_save")); + QVERIFY(save); + save->trigger(); + + QCOMPARE(saved.size(), 1); + const QString path = saved.first().first().toString(); + QVERIFY2(!path.isEmpty(), "the save reported no path"); + + // The guard the probe needs: without it a rename that dropped the info + // suffix entirely would pass the S check below by never reaching it. + const QString name = QFileInfo(path).fileName(); + QVERIFY2(name.contains(QStringLiteral(":2,")), + qPrintable(QStringLiteral("no Maildir info suffix in %1").arg(name))); + + const QString flags = name.section(QStringLiteral(":2,"), 1); + QVERIFY2(flags.contains(QLatin1Char('D')), + qPrintable(QStringLiteral("a draft must carry the D flag, got %1") + .arg(flags))); + QVERIFY2(flags.contains(QLatin1Char('S')), + qPrintable(QStringLiteral("a draft must carry the S flag or notmuch " + "tags it unread, got %1").arg(flags))); +} + /// The same QAction objects, shown twice over, exactly as item 140 required /// for the message pane's bar. A copy would drift: an enablement change or a /// new shortcut would reach one surface and not the other. |
