aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_mainwindow.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-27 13:05:17 +0200
committerDanilo M. <danix@danix.xyz>2026-08-27 13:05:17 +0200
commit5570d0e7495a42a90acf951d396c9185b0319eb9 (patch)
tree4052c9060b6ade33577c9bcb285565a1477bd3eb /tests/test_mainwindow.cpp
parent12e841b8e2c4c225ea79de87dc7bb50f0404ee69 (diff)
downloadqtmaildir-5570d0e7495a42a90acf951d396c9185b0319eb9.tar.gz
qtmaildir-5570d0e7495a42a90acf951d396c9185b0319eb9.zip
feat: forward an HTML message with its formattingHEADmaster
Item 171. A forward carried only the plain-text version of the original, so formatting was lost; and an original with no plain-text part at all (30 of 342 sampled inbox messages, ~9%) forwarded as an empty quote with its content silently gone. A forward now sends ONE part chosen by the Send-as-HTML toggle: the original's markup when on, the text quote when off. Not a multipart/alternative, at the user's decision: a forward's shape is already decided by that toggle, and sending both hands the choice to the recipient's client. The toggle is honoured even for an HTML-only original, which then forwards as a text fallback. HtmlSanitiser strips remote content from the forwarded markup, checked by default with a per-forward opt-out. This is the security-critical part: the markup leaves this process and is rendered by the recipient's client, where none of MessageView's protections apply, so forwarding a tracking pixel forwards the tracking. It is an ALLOW-LIST, unlike HtmlBuilder::namespaceCids(), because a missed rewrite is a broken image while a missed strip is a beacon reaching the recipient. An HTML forward does not seed a text quote into the editor. The first build did, then subtracted it when building the HTML part, so the user could edit a quote whose edits were discarded; what the composer shows must be what gets sent. The forwarded message appears in a read-only pane beside the editor instead, a QSplitter at 60/40 with a toggle in the Format menu. A plain forward is unchanged. ComposeContextBuilder::quoteBody() renders htmlBody down to text when there is no plain part, so the plain path never emits an empty quote. Design in docs/superpowers/specs/2026-08-27-forward-html-design.md. Two tests repaired for the splitter: the 60/40 assertion reads stretch factors rather than pixels, since the offscreen platform gives the splitter no width and reports 49/49 whatever the code asks; and theComposerSplitsItsToolbarByScope looked for the body directly in the composer's column. Not yet hand-tested in this arrangement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AtUzfNjMD8fiYfamDd3ywW
Diffstat (limited to 'tests/test_mainwindow.cpp')
-rw-r--r--tests/test_mainwindow.cpp26
1 files changed, 17 insertions, 9 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
index 2fbdb20..08589b2 100644
--- a/tests/test_mainwindow.cpp
+++ b/tests/test_mainwindow.cpp
@@ -12955,15 +12955,23 @@ void TestMainWindow::theComposerSplitsItsToolbarByScope()
auto *column = qobject_cast<QVBoxLayout *>(central->layout());
QVERIFY2(column, "the composer is not laid out in a vertical column");
- int barIndex = -1;
- int bodyIndex = -1;
- for (int i = 0; i < column->count(); ++i) {
- QLayoutItem *item = column->itemAt(i);
- if (item->widget() == editorBar)
- barIndex = i;
- else if (item->widget() == body)
- bodyIndex = i;
- }
+ // The editor sits inside a QSplitter since item 171, so its position in
+ // the column is the SPLITTER's: a forward puts the forwarded message
+ // beside the editor, and the toolbar must stay above both. Walking up to
+ // whichever child of the column contains the body keeps this test about
+ // the toolbar's position rather than about the editor's parentage.
+ const auto columnChildOf = [column](QWidget *widget) {
+ for (QWidget *w = widget; w; w = w->parentWidget()) {
+ for (int i = 0; i < column->count(); ++i) {
+ if (column->itemAt(i)->widget() == w)
+ return i;
+ }
+ }
+ return -1;
+ };
+
+ const int barIndex = columnChildOf(editorBar);
+ const int bodyIndex = columnChildOf(body);
QVERIFY2(barIndex >= 0 && bodyIndex >= 0,
"the editor bar or the body is not in the composer's column");
QVERIFY2(barIndex < bodyIndex, "the editor bar is not above the editor");