MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.9% 31 / 0 / 32
Functions: 100.0% 3 / 0 / 3
Branches: 66.2% 45 / 0 / 68

presentation/ComposeReplyPrefillResume.cpp
Line Branch Exec Source
1 // Sprint 108 S108.7.2 (D-21): a draft of the drafts folder becomes a
2 // composer again. MailJD's own drafts carry X-MailJD-Draft (identity and
3 // format, ComposeDraftHeader); foreign drafts open with the account's
4 // default address and their HTML goes through ComposeHtmlImport like any
5 // pasted HTML (D-9). The draft's files are exported like a forward's.
6 #include "ComposeReplyPrefill.h"
7
8 #include "ComposeLog.h"
9 #include "ComposeQuoteSource.h"
10 #include "ComposeRecipients.h"
11 #include "QuickComposeForwardAttachments.h"
12 #include "data/ComposeDraftHeader.h"
13 #include "data/MailCache.h"
14 #include "service/MimeParser.h"
15
16 #include <QTemporaryDir>
17
18 2 bool ComposeReplyPrefill::requestDraftResume(int requestToken) {
19
1/1
✓ Branch 3 → 4 taken 2 times.
4 return startComposeSource(requestToken, [this]() -> SourceBuilder {
20 // The resumed draft's files live with the scratch of the last forward
21 // (the session copies them into its own draft store when it opens).
22
1/1
✓ Branch 2 → 3 taken 2 times.
2 std::shared_ptr<QTemporaryDir> scratch = QuickComposeForwardAttachments::makeScratch(m_profileDirectory);
23 2 m_forwardScratch = scratch;
24 4 return [scratch](MailCache &reader, const MailCache::ComposeSourceSnapshot &source, const MailId &id) -> QVariantMap {
25
1/1
✓ Branch 2 → 3 taken 2 times.
2 const auto envelope = MimeParser::messageHeaders(source.envelopePrefix);
26 2 QVariantMap draft;
27
3/3
✓ Branch 6 → 7 taken 2 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 12 → 13 taken 2 times.
6 draft.insert(QStringLiteral("to"), ComposeRecipients::decodedField(envelope.value(QStringLiteral("to"), source.header.to)));
28
3/3
✓ Branch 24 → 25 taken 2 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 30 → 31 taken 2 times.
6 draft.insert(QStringLiteral("cc"), ComposeRecipients::decodedField(envelope.value(QStringLiteral("cc"))));
29
3/3
✓ Branch 43 → 44 taken 2 times.
✓ Branch 44 → 45 taken 2 times.
✓ Branch 49 → 50 taken 2 times.
6 draft.insert(QStringLiteral("bcc"), ComposeRecipients::decodedField(envelope.value(QStringLiteral("bcc"))));
30
1/1
✓ Branch 62 → 63 taken 2 times.
4 draft.insert(QStringLiteral("subject"), source.header.subject);
31
4/4
✓ Branch 70 → 71 taken 2 times.
✓ Branch 71 → 72 taken 2 times.
✓ Branch 72 → 73 taken 2 times.
✓ Branch 77 → 78 taken 2 times.
6 draft.insert(QStringLiteral("inReplyTo"), envelope.value(QStringLiteral("in-reply-to")).trimmed().left(998));
32
1/1
✓ Branch 91 → 92 taken 2 times.
4 draft.insert(QStringLiteral("references"), source.header.references);
33
2/2
✓ Branch 99 → 100 taken 2 times.
✓ Branch 100 → 101 taken 2 times.
4 const auto header = ComposeDraftHeader::parse(envelope.value(QStringLiteral("x-mailjd-draft")));
34
6/7
✓ Branch 106 → 107 taken 2 times.
✗ Branch 106 → 111 not taken.
✓ Branch 109 → 110 taken 1 time.
✓ Branch 109 → 111 taken 1 time.
✓ Branch 112 → 113 taken 1 time.
✓ Branch 112 → 123 taken 1 time.
✓ Branch 118 → 119 taken 1 time.
3 if (header && !header->identity.isEmpty()) draft.insert(QStringLiteral("identityId"), header->identity);
35 // The draft's own text: the formatted part when it has one (and it was
36 // written formatted), else the plain one.
37
2/3
✓ Branch 123 → 124 taken 2 times.
✗ Branch 123 → 125 not taken.
✓ Branch 124 → 126 taken 2 times.
2 const QString html = source.bodyPresent ? ComposeQuoteSource::cleanHtml(source.quoteHtml) : QString();
38
2/4
✓ Branch 127 → 128 taken 2 times.
✗ Branch 127 → 134 not taken.
✓ Branch 130 → 131 taken 2 times.
✗ Branch 130 → 134 not taken.
2 const bool formatted = header && header->formatted ? *header->formatted : !html.isEmpty();
39
2/5
✗ Branch 136 → 137 not taken.
✓ Branch 136 → 140 taken 2 times.
✗ Branch 138 → 139 not taken.
✗ Branch 138 → 140 not taken.
✓ Branch 145 → 146 taken 2 times.
4 draft.insert(QStringLiteral("formatted"), formatted && !html.isEmpty());
40
2/3
✓ Branch 149 → 150 taken 2 times.
✗ Branch 149 → 151 not taken.
✓ Branch 156 → 157 taken 2 times.
4 draft.insert(QStringLiteral("body"), source.bodyPresent ? source.quoteText : QString());
41
1/3
✗ Branch 161 → 162 not taken.
✓ Branch 161 → 171 taken 2 times.
✗ Branch 166 → 167 not taken.
2 if (formatted) draft.insert(QStringLiteral("html"), html);
42
1/2
✓ Branch 172 → 173 taken 2 times.
✗ Branch 172 → 190 not taken.
2 if (scratch) {
43
2/2
✓ Branch 174 → 175 taken 2 times.
✓ Branch 175 → 176 taken 2 times.
2 const QStringList files = QuickComposeForwardAttachments::exportTo(reader, id.folderId, id.uid, scratch->path());
44
1/3
✗ Branch 178 → 179 not taken.
✓ Branch 178 → 188 taken 2 times.
✗ Branch 183 → 184 not taken.
2 if (!files.isEmpty()) draft.insert(QStringLiteral("attachments"), files);
45 2 }
46
1/1
✓ Branch 194 → 195 taken 2 times.
4 draft.insert(QStringLiteral("resumedUid"), id.uid);
47
1/1
✓ Branch 202 → 203 taken 2 times.
4 draft.insert(QStringLiteral("resumedUidValidity"), source.uidValidity);
48
1/1
✓ Branch 211 → 212 taken 2 times.
4 draft.insert(QStringLiteral("ownDraft"), header.has_value());
49
2/7
✓ Branch 215 → 216 taken 2 times.
✗ Branch 219 → 220 not taken.
✗ Branch 220 → 221 not taken.
✗ Branch 222 → 223 not taken.
✗ Branch 223 → 224 not taken.
✗ Branch 233 → 217 not taken.
✓ Branch 233 → 234 taken 2 times.
2 qCInfo(lcCompose) << "draft resumed from the drafts folder; own" << header.has_value() << "formatted"
50 ✗ << (formatted && !html.isEmpty());
51 2 return draft;
52
1/1
✓ Branch 5 → 6 taken 2 times.
6 };
53 6 });
54 }
55