diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-24 10:40:23 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-24 10:40:23 +0200 |
| commit | df5f64f16359c9e34d258758f174187ffc618101 (patch) | |
| tree | 85b1a3fd49ce84f47fb80218a47ff9a383ed67b8 /tests | |
| parent | fabcf080652c6e5d57bf234be5e100769a9b965b (diff) | |
| download | qtmaildir-df5f64f16359c9e34d258758f174187ffc618101.tar.gz qtmaildir-df5f64f16359c9e34d258758f174187ffc618101.zip | |
fix(compose): put the reply cursor on blank space, not on the quote
quote_position names where the QUOTE goes, so the reply belongs on the
other side of it and the cursor has to follow the reply rather than the
buffer. seedBody() moved the cursor to Start under both positions, which
is correct only for Below: under Above, the shipped default, it landed on
the "On ... wrote:" attribution line, so every reply had to have room made
before it could be typed.
End under Above, Start under Below.
The existing theQuotePositionDecidesWhereTheQuoteLands passed throughout
the defect and still does, because the quote was in the right place all
along; only the cursor was not. The new test asserts the cursor's block is
blank, and that typing lands on the correct side of the quote, so a fix
that freed the cursor by inverting the position would not satisfy it.
Also re-measures item 136 in the backlog, which is not the intermittent
race it was filed as: undoMovesTheMessageBack fails 6 runs in 6 when named
alone and passes in the full suite, on a clean tree, so it depends on the
tests before it.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_mainwindow.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp index 98dae12..91fbd44 100644 --- a/tests/test_mainwindow.cpp +++ b/tests/test_mainwindow.cpp @@ -56,6 +56,7 @@ #include "messagesender.h" #include <QCheckBox> #include <QPlainTextEdit> +#include <QTextBlock> #include <QPointer> #include <QListWidget> #include "cardlayout.h" @@ -484,6 +485,7 @@ private slots: void theAttachmentWarningRespectsTheConfiguredThreshold(); void aDisabledAttachmentWarningWarnsAboutNothing(); void theQuotePositionDecidesWhereTheQuoteLands(); + void theCursorStartsOnBlankSpaceNotOnTheQuote(); void theSeededQuoteIsNotAnUndoStep(); void aReplySeedsTheHtmlToggleFromTheOriginal(); void aNewMessageSeedsTheHtmlToggleFromConfig(); @@ -12374,6 +12376,59 @@ void TestMainWindow::theQuotePositionDecidesWhereTheQuoteLands() } } +void TestMainWindow::theCursorStartsOnBlankSpaceNotOnTheQuote() +{ + // The user types their reply where the cursor lands, so that line must be + // blank under BOTH quote positions. Asserting on the buffer's shape is not + // enough: theQuotePositionDecidesWhereTheQuoteLands() already does that and + // passed throughout the defect, because the quote was in the right place + // and the cursor was on top of it. + const QString quote = QStringLiteral("> the original"); + + const struct { + const char *position; + const char *label; + } cases[] = { + { "above", "quote_position=above" }, + { "below", "quote_position=below" }, + }; + + for (const auto &testCase : cases) { + ComposeFixture fixture; + QVERIFY(fixture.build(QStringLiteral("Drafts"), QStringLiteral("Sent"), + QStringLiteral("quote_position=%1") + .arg(QLatin1String(testCase.position)))); + ComposeContext context = newContext(); + context.kind = ComposeContext::Kind::Reply; + context.quotedBody = quote; + + ComposeWindow window(context, fixture.config(), fixture.mailRoot()); + auto *body = window.findChild<QPlainTextEdit *>(QStringLiteral("body")); + QVERIFY(body); + + const QTextCursor cursor = body->textCursor(); + QVERIFY2(cursor.block().text().isEmpty(), + qPrintable(QStringLiteral("%1: the cursor starts on \"%2\", " + "not on a blank line") + .arg(QLatin1String(testCase.label), + cursor.block().text()))); + + // Typing must not land inside the quote either. A blank line that is + // still BELOW the quote would satisfy the check above while leaving the + // reply underneath what it answers, which is what quote_position + // decides and must not be silently inverted. + QTextCursor probe = cursor; + probe.insertText(QStringLiteral("typed")); + const QString text = body->toPlainText(); + const bool typedFirst = text.indexOf(QStringLiteral("typed")) + < text.indexOf(quote); + QCOMPARE(typedFirst, + QLatin1String(testCase.position) == QLatin1String("above") + ? false + : true); + } +} + void TestMainWindow::theSeededQuoteIsNotAnUndoStep() { ComposeFixture fixture; |
