File indexing completed on 2024-05-05 05:01:19

0001 // SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 #include <QObject>
0005 #include <QTest>
0006 
0007 #include "texthandler.h"
0008 
0009 #include <Quotient/quotient_common.h>
0010 #include <Quotient/syncdata.h>
0011 #include <qnamespace.h>
0012 
0013 #include "models/customemojimodel.h"
0014 #include "neochatconnection.h"
0015 #include "utils.h"
0016 
0017 #include "testutils.h"
0018 
0019 using namespace Quotient;
0020 
0021 class TextHandlerTest : public QObject
0022 {
0023     Q_OBJECT
0024 
0025 private:
0026     Connection *connection = nullptr;
0027     TestUtils::TestRoom *room = nullptr;
0028 
0029 private Q_SLOTS:
0030     void initTestCase();
0031 
0032     void allowedAttributes();
0033     void stripDisallowedTags();
0034     void stripDisallowedAttributes();
0035     void emptyCodeTags();
0036     void formatBlockQuote();
0037 
0038     void sendSimpleStringCase();
0039     void sendSingleParaMarkup();
0040     void sendMultipleSectionMarkup();
0041     void sendBadLinks();
0042     void sendEscapeCode();
0043     void sendCodeClass();
0044     void sendCustomEmoji();
0045     void sendCustomEmojiCode_data();
0046     void sendCustomEmojiCode();
0047 
0048     void receiveStripReply();
0049     void receivePlainTextIn();
0050 
0051     void receiveRichInPlainOut_data();
0052     void receiveRichInPlainOut();
0053     void receivePlainStripHtml();
0054     void receivePlainStripMarkup();
0055     void receiveStripNewlines();
0056 
0057     void receiveRichUserPill();
0058     void receiveRichStrikethrough();
0059     void receiveRichtextIn();
0060     void receiveRichMxcUrl();
0061     void receiveRichPlainUrl();
0062     void receiveRichEmote();
0063     void receiveRichEdited_data();
0064     void receiveRichEdited();
0065     void receiveLineSeparator();
0066     void receiveRichCodeUrl();
0067 };
0068 
0069 void TextHandlerTest::initTestCase()
0070 {
0071     connection = Connection::makeMockConnection(QStringLiteral("@bob:kde.org"));
0072     connection->setAccountData("im.ponies.user_emotes"_ls,
0073                                QJsonObject{{"images"_ls,
0074                                             QJsonObject{{"test"_ls,
0075                                                          QJsonObject{{"body"_ls, "Test custom emoji"_ls},
0076                                                                      {"url"_ls, "mxc://example.org/test"_ls},
0077                                                                      {"usage"_ls, QJsonArray{"emoticon"_ls}}}}}}});
0078     CustomEmojiModel::instance().setConnection(static_cast<NeoChatConnection *>(connection));
0079 
0080     room = new TestUtils::TestRoom(connection, QStringLiteral("#myroom:kde.org"), QLatin1String("test-texthandler-sync.json"));
0081 }
0082 
0083 void TextHandlerTest::allowedAttributes()
0084 {
0085     const QString testInputString1 = QStringLiteral("<p><span data-mx-spoiler><font color=#FFFFFF>Test</font><span></p>");
0086     const QString testOutputString1 = QStringLiteral("<p><span data-mx-spoiler><font color=#FFFFFF>Test</font><span></p>");
0087     // Handle urls where the href has either single (') or double (") quotes.
0088     const QString testInputString2 = QStringLiteral("<p><a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a></p>");
0089     const QString testOutputString2 = QStringLiteral("<p><a href=\"https://kde.org\">link</a><a href='https://kde.org'>link</a></p>");
0090 
0091     TextHandler testTextHandler;
0092     testTextHandler.setData(testInputString1);
0093 
0094     QCOMPARE(testTextHandler.handleSendText(), testOutputString1);
0095     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString1);
0096 
0097     testTextHandler.setData(testInputString2);
0098     QCOMPARE(testTextHandler.handleSendText(), testOutputString2);
0099     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString2);
0100 }
0101 
0102 void TextHandlerTest::stripDisallowedTags()
0103 {
0104     const QString testInputString = QStringLiteral("<p>Allowed</p> <span>Allowed</span> <body>Disallowed</body>");
0105     const QString testOutputString = QStringLiteral("<p>Allowed</p> <span>Allowed</span> Disallowed");
0106 
0107     TextHandler testTextHandler;
0108     testTextHandler.setData(testInputString);
0109 
0110     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0111     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0112 }
0113 
0114 void TextHandlerTest::stripDisallowedAttributes()
0115 {
0116     const QString testInputString = QStringLiteral("<p style=\"font-size:50px;\" color=#FFFFFF>Test</p>");
0117     const QString testOutputString = QStringLiteral("<p>Test</p>");
0118 
0119     TextHandler testTextHandler;
0120     testTextHandler.setData(testInputString);
0121 
0122     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0123     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0124 }
0125 
0126 /**
0127  * Make sure that empty code tags are handled.
0128  * (this was a bug during development hence the test)
0129  */
0130 void TextHandlerTest::emptyCodeTags()
0131 {
0132     const QString testInputString = QStringLiteral("<pre><code></code></pre>");
0133     const QString testOutputString = QStringLiteral("<pre><code></code></pre>");
0134 
0135     TextHandler testTextHandler;
0136     testTextHandler.setData(testInputString);
0137 
0138     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0139     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0140 }
0141 
0142 void TextHandlerTest::formatBlockQuote()
0143 {
0144     auto input = QStringLiteral("<blockquote>\n<p>Lorem Ispum</p>\n</blockquote>");
0145     auto expectedOutput = QStringLiteral("<blockquote><table><tr><td>\u201CLorem Ispum\u201D</td></tr></table></blockquote>");
0146 
0147     TextHandler testTextHandler;
0148     testTextHandler.setData(input);
0149     QCOMPARE(testTextHandler.handleRecieveRichText(), expectedOutput);
0150 }
0151 
0152 void TextHandlerTest::sendSimpleStringCase()
0153 {
0154     const QString testInputString = QStringLiteral("This data should just be put in a paragraph.");
0155     const QString testOutputString = QStringLiteral("<p>This data should just be put in a paragraph.</p>");
0156 
0157     TextHandler testTextHandler;
0158     testTextHandler.setData(testInputString);
0159 
0160     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0161 }
0162 
0163 void TextHandlerTest::sendSingleParaMarkup()
0164 {
0165     const QString testInputString = QStringLiteral(
0166         "Text para with **bold**, *italic*, [link](https://kde.org), ![image](mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e), `inline code`.");
0167     const QString testOutputString = QStringLiteral(
0168         "<p>Text para with <strong>bold</strong>, <em>italic</em>, <a href=\"https://kde.org\">link</a>, <img "
0169         "src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\">, <code>inline code</code>.</p>");
0170 
0171     TextHandler testTextHandler;
0172     testTextHandler.setData(testInputString);
0173 
0174     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0175 }
0176 
0177 void TextHandlerTest::sendMultipleSectionMarkup()
0178 {
0179     const QString testInputString =
0180         QStringLiteral("Text para\n> blockquote\n* List 1\n* List 2\n1. one\n2. two\n# Heading 1\n## Heading 2\nhorizontal rule\n\n---\n```\ncodeblock\n```");
0181     const QString testOutputString = QStringLiteral(
0182         "<p>Text para</p>\n<blockquote>\n<p>blockquote</p>\n</blockquote>\n<ul>\n<li>List 1</li>\n<li>List "
0183         "2</li>\n</ul>\n<ol>\n<li>one</li>\n<li>two</li>\n</ol>\n<h1>Heading 1</h1>\n<h2>Heading 2</h2>\n<p>horizontal "
0184         "rule</p>\n<hr>\n<pre><code>codeblock\n</code></pre>");
0185 
0186     TextHandler testTextHandler;
0187     testTextHandler.setData(testInputString);
0188 
0189     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0190 }
0191 
0192 void TextHandlerTest::sendBadLinks()
0193 {
0194     const QString testInputString = QStringLiteral("[link](kde.org), ![image](https://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e)");
0195     const QString testOutputString = QStringLiteral("<p><a>link</a>, <img alt=\"image\"></p>");
0196 
0197     TextHandler testTextHandler;
0198     testTextHandler.setData(testInputString);
0199 
0200     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0201 }
0202 
0203 /**
0204  * All text between code tags is treated as plain so it should get escaped.
0205  */
0206 void TextHandlerTest::sendEscapeCode()
0207 {
0208     const QString testInputString = QStringLiteral("```\n<p>Test <span style=\"font-size:50px;\">some</span> code</p>\n```");
0209     const QString testOutputString =
0210         QStringLiteral("<pre><code>&lt;p&gt;Test &lt;span style=&quot;font-size:50px;&quot;&gt;some&lt;/span&gt; code&lt;/p&gt;\n</code></pre>");
0211 
0212     TextHandler testTextHandler;
0213     testTextHandler.setData(testInputString);
0214 
0215     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0216 }
0217 
0218 void TextHandlerTest::sendCodeClass()
0219 {
0220     const QString testInputString = QStringLiteral("```html\nsome code\n```\n<pre><code class=\"code-underline\">some more code</code></pre>");
0221     const QString testOutputString = QStringLiteral("<pre><code class=\"language-html\">some code\n</code></pre>\n<pre><code>some more code</code></pre>");
0222 
0223     TextHandler testTextHandler;
0224     testTextHandler.setData(testInputString);
0225 
0226     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0227 }
0228 
0229 void TextHandlerTest::sendCustomEmoji()
0230 {
0231     const QString testInputString = QStringLiteral(":test:");
0232     const QString testOutputString = QStringLiteral(
0233         "<p><img data-mx-emoticon=\"\" src=\"mxc://example.org/test\" alt=\":test:\" title=\":test:\" height=\"32\" vertical-align=\"middle\" /></p>");
0234 
0235     TextHandler testTextHandler;
0236     testTextHandler.setData(testInputString);
0237 
0238     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0239 }
0240 
0241 void TextHandlerTest::sendCustomEmojiCode_data()
0242 {
0243     QTest::addColumn<QString>("testInputString");
0244     QTest::addColumn<QString>("testOutputString");
0245 
0246     QTest::newRow("inline") << QStringLiteral("`:test:`") << QStringLiteral("<p><code>:test:</code></p>");
0247     QTest::newRow("block") << QStringLiteral("```\n:test:\n```") << QStringLiteral("<pre><code>:test:\n</code></pre>");
0248 }
0249 
0250 // Custom emojis in code blocks should be left alone.
0251 void TextHandlerTest::sendCustomEmojiCode()
0252 {
0253     QFETCH(QString, testInputString);
0254     QFETCH(QString, testOutputString);
0255 
0256     TextHandler testTextHandler;
0257     testTextHandler.setData(testInputString);
0258 
0259     QCOMPARE(testTextHandler.handleSendText(), testOutputString);
0260 }
0261 
0262 void TextHandlerTest::receiveStripReply()
0263 {
0264     const QString testInputString = QStringLiteral(
0265         "<mx-reply><blockquote><a href=\"https://matrix.to/#/!somewhere:example.org/$event:example.org\">In reply to</a><a "
0266         "href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a><br />Message replied to.</blockquote></mx-reply>Reply message.");
0267     const QString testOutputString = QStringLiteral("Reply message.");
0268 
0269     TextHandler testTextHandler;
0270     testTextHandler.setData(testInputString);
0271 
0272     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0273     QCOMPARE(testTextHandler.handleRecievePlainText(), testOutputString);
0274 }
0275 
0276 void TextHandlerTest::receiveRichInPlainOut_data()
0277 {
0278     QTest::addColumn<QString>("testInputString");
0279     QTest::addColumn<QString>("testOutputString");
0280 
0281     QTest::newRow("ampersand") << QStringLiteral("a &amp; b") << QStringLiteral("a & b");
0282     QTest::newRow("quote") << QStringLiteral("&quot;a and b&quot;") << QStringLiteral("\"a and b\"");
0283     QTest::newRow("new line") << QStringLiteral("new<br>line") << QStringLiteral("new\nline");
0284 }
0285 
0286 void TextHandlerTest::receiveRichInPlainOut()
0287 {
0288     QFETCH(QString, testInputString);
0289     QFETCH(QString, testOutputString);
0290 
0291     TextHandler testTextHandler;
0292     testTextHandler.setData(testInputString);
0293 
0294     QCOMPARE(testTextHandler.handleRecievePlainText(Qt::RichText), testOutputString);
0295 }
0296 
0297 void TextHandlerTest::receivePlainTextIn()
0298 {
0299     const QString testInputString = QStringLiteral("<plain text in tag bracket>\nTest link https://kde.org.");
0300     const QString testOutputStringRich = QStringLiteral("&lt;plain text in tag bracket&gt;<br>Test link <a href=\"https://kde.org\">https://kde.org</a>.");
0301     QString testOutputStringPlain = QStringLiteral("<plain text in tag bracket>\nTest link https://kde.org.");
0302 
0303     // Make sure quotes are maintained in a plain string.
0304     const QString testInputString2 = QStringLiteral("last line is \"Time to switch to a new topic.\"");
0305     const QString testOutputString2 = QStringLiteral("last line is \"Time to switch to a new topic.\"");
0306 
0307     TextHandler testTextHandler;
0308     testTextHandler.setData(testInputString);
0309 
0310     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::PlainText), testOutputStringRich);
0311     QCOMPARE(testTextHandler.handleRecievePlainText(), testOutputStringPlain);
0312 
0313     testTextHandler.setData(testInputString2);
0314     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::PlainText), testOutputString2);
0315     QCOMPARE(testTextHandler.handleRecievePlainText(), testOutputString2);
0316 }
0317 
0318 void TextHandlerTest::receiveStripNewlines()
0319 {
0320     const QString testInputStringPlain = QStringLiteral("Test\nmany\nnew\nlines.");
0321     const QString testInputStringRich = QStringLiteral("Test<br>many<br />new<br>lines.");
0322     const QString testOutputString = QStringLiteral("Test many new lines.");
0323 
0324     const QString testInputStringPlain2 = QStringLiteral("* List\n* Items");
0325     const QString testOutputString2 = QStringLiteral("List Items");
0326 
0327     TextHandler testTextHandler;
0328     testTextHandler.setData(testInputStringPlain);
0329 
0330     QCOMPARE(testTextHandler.handleRecievePlainText(Qt::PlainText, true), testOutputString);
0331     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::PlainText, nullptr, nullptr, true), testOutputString);
0332 
0333     testTextHandler.setData(testInputStringRich);
0334     QCOMPARE(testTextHandler.handleRecievePlainText(Qt::RichText, true), testOutputString);
0335     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, nullptr, nullptr, true), testOutputString);
0336 
0337     testTextHandler.setData(testInputStringPlain2);
0338     QCOMPARE(testTextHandler.handleRecievePlainText(Qt::RichText, true), testOutputString2);
0339 }
0340 
0341 /**
0342  * For a plain text output of a received string all html is stripped except for
0343  * code which is unescaped if it's html.
0344  */
0345 void TextHandlerTest::receivePlainStripHtml()
0346 {
0347     const QString testInputString = QStringLiteral("<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>");
0348     const QString testOutputString = QStringLiteral("Test Some code <strong>with tags</strong>");
0349 
0350     TextHandler testTextHandler;
0351     testTextHandler.setData(testInputString);
0352 
0353     QCOMPARE(testTextHandler.handleRecievePlainText(Qt::RichText), testOutputString);
0354 }
0355 
0356 void TextHandlerTest::receivePlainStripMarkup()
0357 {
0358     const QString testInputString = QStringLiteral("**bold** `<p>inline code</p>` *italic*");
0359     const QString testOutputString = QStringLiteral("bold <p>inline code</p> italic");
0360 
0361     TextHandler testTextHandler;
0362     testTextHandler.setData(testInputString);
0363 
0364     QCOMPARE(testTextHandler.handleRecievePlainText(), testOutputString);
0365 }
0366 
0367 void TextHandlerTest::receiveRichUserPill()
0368 {
0369     const QString testInputString = QStringLiteral("<p><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></p>");
0370     const QString testOutputString = QStringLiteral("<p><b><a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a></b></p>");
0371 
0372     TextHandler testTextHandler;
0373     testTextHandler.setData(testInputString);
0374 
0375     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0376 }
0377 
0378 void TextHandlerTest::receiveRichStrikethrough()
0379 {
0380     const QString testInputString = QStringLiteral("<p><del>Test</del></p>");
0381     const QString testOutputString = QStringLiteral("<p><s>Test</s></p>");
0382 
0383     TextHandler testTextHandler;
0384     testTextHandler.setData(testInputString);
0385 
0386     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0387 }
0388 
0389 void TextHandlerTest::receiveRichtextIn()
0390 {
0391     const QString testInputString = QStringLiteral("<p>Test</p> <pre><code>Some code <strong>with tags</strong></code></pre>");
0392     const QString testOutputString = QStringLiteral("<p>Test</p> <pre><code>Some code &lt;strong&gt;with tags&lt;/strong&gt;</code></pre>");
0393 
0394     TextHandler testTextHandler;
0395     testTextHandler.setData(testInputString);
0396 
0397     QCOMPARE(testTextHandler.handleRecieveRichText(), testOutputString);
0398 }
0399 
0400 void TextHandlerTest::receiveRichMxcUrl()
0401 {
0402     const QString testInputString = QStringLiteral(
0403         "<img src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e\" alt=\"image\"><img src=\"mxc://kde.org/34c3464b3a1bd7f55af2d559e07d2c773c430e73\" "
0404         "alt=\"image\">");
0405     const QString testOutputString = QStringLiteral(
0406         "<img "
0407         "src=\"mxc://kde.org/aebd3ffd40503e1ef0525bf8f0d60282fec6183e?user_id=@bob:kde.org&room_id=%23myroom:kde.org&event_id=$143273582443PhrSn:example.org\" "
0408         "alt=\"image\"><img "
0409         "src=\"mxc://kde.org/34c3464b3a1bd7f55af2d559e07d2c773c430e73?user_id=@bob:kde.org&room_id=%23myroom:kde.org&event_id=$143273582443PhrSn:example.org\" "
0410         "alt=\"image\">");
0411 
0412     TextHandler testTextHandler;
0413     testTextHandler.setData(testInputString);
0414 
0415     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(0).get()), testOutputString);
0416 }
0417 
0418 /**
0419  * For when your rich input string has a plain text url left in.
0420  *
0421  * This test is to show that a url that is already rich will be left alone but a
0422  * plain one will be linkified.
0423  */
0424 void TextHandlerTest::receiveRichPlainUrl()
0425 {
0426     // This is an actual link that caused trouble which is why it's so long. Keeping
0427     // so we can confirm consistent behaviour for complex urls.
0428     const QString testInputStringLink1 = QStringLiteral(
0429         "https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&amp;via=matrix.org&amp;via=fedora.im "
0430         "<a "
0431         "href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/"
0432         "$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&amp;via=matrix.org&amp;via=fedora.im\">Link already rich</a>");
0433     const QString testOutputStringLink1 = QStringLiteral(
0434         "<a "
0435         "href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/"
0436         "$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&amp;via=matrix.org&amp;via=fedora.im\">https://matrix.to/#/"
0437         "!RvzunyTWZGfNxJVQqv:matrix.org/$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&amp;via=matrix.org&amp;via=fedora.im</a> <a "
0438         "href=\"https://matrix.to/#/!RvzunyTWZGfNxJVQqv:matrix.org/"
0439         "$-9TJVTh5PvW6MvIhFDwteiyLBVGriinueO5eeIazQS8?via=libera.chat&amp;via=matrix.org&amp;via=fedora.im\">Link already rich</a>");
0440 
0441     // Another real case. The linkification wasn't handling it when a single link
0442     // contains what looks like and email. It was been broken into 3 but needs to
0443     // be just single link.
0444     const QString testInputStringLink2 = QStringLiteral("https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/");
0445     const QString testOutputStringLink2 = QStringLiteral(
0446         "<a "
0447         "href=\"https://lore.kernel.org/lkml/CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/\">https://lore.kernel.org/lkml/"
0448         "CAHk-=wio46vC4t6xXD-sFqjoPwFm_u515jm3suzmkGxQTeA1_A@mail.gmail.com/</a>");
0449 
0450     QString testInputStringEmail = QStringLiteral(R"(email@example.com <a href="mailto:email@example.com">Link already rich</a>)");
0451     QString testOutputStringEmail =
0452         QStringLiteral(R"(<a href="mailto:email@example.com">email@example.com</a> <a href="mailto:email@example.com">Link already rich</a>)");
0453 
0454     QString testInputStringMxId = QStringLiteral("@user:kde.org <a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a>");
0455     QString testOutputStringMxId = QStringLiteral(
0456         "<b><a href=\"https://matrix.to/#/@user:kde.org\">@user:kde.org</a></b> <b><a href=\"https://matrix.to/#/@user:kde.org\">Link already rich</a></b>");
0457 
0458     TextHandler testTextHandler;
0459     testTextHandler.setData(testInputStringLink1);
0460 
0461     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringLink1);
0462 
0463     testTextHandler.setData(testInputStringLink2);
0464     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringLink2);
0465 
0466     testTextHandler.setData(testInputStringEmail);
0467     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringEmail);
0468 
0469     testTextHandler.setData(testInputStringMxId);
0470     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText), testOutputStringMxId);
0471 }
0472 
0473 // Test that user pill is add to an emote message.
0474 // N.B. The second message in the test timeline is marked as an emote.
0475 void TextHandlerTest::receiveRichEmote()
0476 {
0477     auto event = room->messageEvents().at(1).get();
0478     auto author = room->user(event->senderId());
0479     const QString testInputString = QStringLiteral("This is an emote.");
0480     const QString testOutputString = QStringLiteral("* <a href=\"https://matrix.to/#/@example:example.org\" style=\"color:")
0481         + Utils::getUserColor(author->hueF()).name() + QStringLiteral("\">@example:example.org</a> This is an emote.");
0482 
0483     TextHandler testTextHandler;
0484     testTextHandler.setData(testInputString);
0485 
0486     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, event), testOutputString);
0487 }
0488 
0489 void TextHandlerTest::receiveRichEdited_data()
0490 {
0491     QTest::addColumn<QString>("testInputString");
0492     QTest::addColumn<QString>("testOutputString");
0493 
0494     QTest::newRow("basic") << QStringLiteral("Edited") << QStringLiteral("Edited <span style=\"color:#000000\">(edited)</span>");
0495     QTest::newRow("multiple paragraphs") << QStringLiteral("<p>Edited</p>\n<p>Edited</p>")
0496                                          << QStringLiteral("<p>Edited</p>\n<p>Edited <span style=\"color:#000000\">(edited)</span></p>");
0497     QTest::newRow("blockquote")
0498         << QStringLiteral("<blockquote>Edited</blockquote>")
0499         << QStringLiteral("<blockquote><table><tr><td>\u201CEdited\u201D</td></tr></table></blockquote><p> <span style=\"color:#000000\">(edited)</span></p>");
0500 }
0501 
0502 void TextHandlerTest::receiveRichEdited()
0503 {
0504     QFETCH(QString, testInputString);
0505     QFETCH(QString, testOutputString);
0506 
0507     TextHandler testTextHandler;
0508     testTextHandler.setData(testInputString);
0509 
0510     QCOMPARE(testTextHandler.handleRecieveRichText(Qt::RichText, room, room->messageEvents().at(2).get()), testOutputString);
0511 }
0512 
0513 void TextHandlerTest::receiveLineSeparator()
0514 {
0515     auto text = QStringLiteral("foo\u2028bar");
0516     TextHandler textHandler;
0517     textHandler.setData(text);
0518     QCOMPARE(textHandler.handleRecievePlainText(Qt::PlainText, true), QStringLiteral("foo bar"));
0519 }
0520 
0521 void TextHandlerTest::receiveRichCodeUrl()
0522 {
0523     auto input = QStringLiteral("<code>https://kde.org</code>");
0524     TextHandler testTextHandler;
0525     testTextHandler.setData(input);
0526     QCOMPARE(testTextHandler.handleRecieveRichText(), input);
0527 }
0528 
0529 QTEST_MAIN(TextHandlerTest)
0530 #include "texthandlertest.moc"