File indexing completed on 2024-06-02 05:26:28

0001 /*
0002    SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "richtextcomposertest.h"
0008 #include "../richtextcomposer.h"
0009 #include <KCodecs>
0010 #include <QSignalSpy>
0011 #include <QTest>
0012 
0013 #include <KActionCollection>
0014 #include <KIconLoader>
0015 #include <QAction>
0016 
0017 #include "kpimtextedit/richtextcomposer.h"
0018 #include "kpimtextedit/richtextcomposercontroler.h"
0019 #include "kpimtextedit/richtextcomposerimages.h"
0020 #include <QBuffer>
0021 #include <QStandardPaths>
0022 #include <QTextBlock>
0023 #include <QTextCursor>
0024 
0025 using namespace KPIMTextEdit;
0026 
0027 Q_DECLARE_METATYPE(KPIMTextEdit::RichTextComposer::Mode)
0028 RichTextComposerTest::RichTextComposerTest(QObject *parent)
0029     : QObject(parent)
0030 {
0031     qRegisterMetaType<KPIMTextEdit::RichTextComposer::Mode>();
0032     QIcon::setThemeName(QStringLiteral("breeze"));
0033     QStandardPaths::setTestModeEnabled(true);
0034 }
0035 
0036 RichTextComposerTest::~RichTextComposerTest() = default;
0037 
0038 void RichTextComposerTest::testFormattingUsed()
0039 {
0040     // This method tries to test everything that krichtextedit makes available, so
0041     // we can sure that in KMail, when the user uses some formatting, the mail is actually
0042     // sent as HTML mail
0043 
0044     KPIMTextEdit::RichTextComposer textEdit;
0045     textEdit.createActions(new KActionCollection(this));
0046 
0047     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0048 
0049     // Insert some text.
0050     QTextCursor cursor(textEdit.document());
0051     cursor.insertText(QStringLiteral("Hello World!!"));
0052     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0053     cursor.setPosition(1);
0054     textEdit.setTextCursor(cursor);
0055 
0056     //
0057     // Test link
0058     //
0059     QString someUrl = QStringLiteral("www.test.de");
0060     QString altText = QStringLiteral("Hello");
0061     textEdit.composerControler()->updateLink(someUrl, altText);
0062     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0063     QCOMPARE(textEdit.composerControler()->currentLinkUrl(), someUrl);
0064     QCOMPARE(textEdit.composerControler()->currentLinkText(), altText);
0065 
0066     cursor.setPosition(1);
0067     textEdit.setTextCursor(cursor);
0068     textEdit.composerControler()->updateLink(QString(), QStringLiteral("Hello"));
0069     QVERIFY(textEdit.composerControler()->currentLinkUrl().isEmpty());
0070     QVERIFY(!textEdit.composerControler()->currentLinkText().isEmpty());
0071     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0072 
0073     //
0074     // Test alignment
0075     //
0076     cursor.setPosition(1);
0077     textEdit.setTextCursor(cursor);
0078     textEdit.composerControler()->alignRight();
0079     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0080     QCOMPARE(textEdit.alignment(), Qt::AlignRight);
0081     textEdit.composerControler()->alignLeft();
0082     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0083     textEdit.composerControler()->alignCenter();
0084     QCOMPARE(textEdit.alignment(), Qt::AlignHCenter);
0085     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0086     textEdit.composerControler()->alignJustify();
0087     QCOMPARE(textEdit.alignment(), Qt::AlignJustify);
0088     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0089     textEdit.composerControler()->alignLeft();
0090     QCOMPARE(textEdit.alignment(), Qt::AlignLeft);
0091     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0092 
0093     //
0094     // Test layout direction
0095     //
0096     textEdit.selectAll();
0097     QTextCharFormat direction;
0098     direction.setLayoutDirection(Qt::RightToLeft);
0099     textEdit.mergeCurrentCharFormat(direction);
0100     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0101     direction.setLayoutDirection(Qt::LeftToRight);
0102     textEdit.mergeCurrentCharFormat(direction);
0103     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0104 
0105     //
0106     // Test lists
0107     //
0108     textEdit.composerControler()->setListStyle(QTextListFormat::ListCircle);
0109     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0110     textEdit.composerControler()->setListStyle(0);
0111     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0112 
0113     //
0114     // Test font attributes
0115     //
0116     textEdit.setFontFamily(QStringLiteral("Times"));
0117     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0118     textEdit.setFontFamily(textEdit.document()->defaultFont().family());
0119     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0120     textEdit.composerControler()->setFontSize(48);
0121     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0122     textEdit.composerControler()->setFontSize(textEdit.document()->defaultFont().pointSize());
0123     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0124     QFont myFont = textEdit.document()->defaultFont();
0125     myFont.setStyle(QFont::StyleOblique);
0126     textEdit.composerControler()->setFont(myFont);
0127     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0128     textEdit.composerControler()->setFont(textEdit.document()->defaultFont());
0129     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0130 
0131     //
0132     // Test bold, italic, underline and strikeout
0133     //
0134     textEdit.composerControler()->setTextBold(true);
0135     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0136     textEdit.composerControler()->setTextBold(false);
0137     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0138     textEdit.composerControler()->setTextUnderline(true);
0139     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0140     textEdit.composerControler()->setTextUnderline(false);
0141     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0142     textEdit.composerControler()->setTextItalic(true);
0143     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0144     textEdit.composerControler()->setTextItalic(false);
0145     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0146     textEdit.composerControler()->setTextStrikeOut(true);
0147     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0148     textEdit.composerControler()->setTextStrikeOut(false);
0149     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0150 
0151     //
0152     // Color
0153     //
0154     QColor oldForeground = textEdit.document()->firstBlock().charFormat().foreground().color();
0155     textEdit.composerControler()->setTextForegroundColor(Qt::red);
0156     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0157     textEdit.composerControler()->setTextForegroundColor(oldForeground);
0158     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0159     QColor oldBackground = textEdit.document()->firstBlock().charFormat().background().color();
0160     textEdit.composerControler()->setTextBackgroundColor(Qt::red);
0161     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0162     textEdit.composerControler()->setTextBackgroundColor(oldBackground);
0163     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0164 
0165     //
0166     // Horizontal rule
0167     //
0168     textEdit.composerControler()->insertHorizontalRule();
0169     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0170     // No way to easily remove the horizontal line, so clear the text edit and start over
0171     textEdit.clear();
0172     cursor.insertText(QStringLiteral("Hello World!!"));
0173     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0174     cursor.setPosition(1);
0175     textEdit.setTextCursor(cursor);
0176 
0177     //
0178     // Sub and superscript
0179     //
0180     textEdit.composerControler()->setTextSuperScript(true);
0181     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0182     textEdit.composerControler()->setTextSuperScript(false);
0183     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0184     textEdit.composerControler()->setTextSubScript(true);
0185     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0186     textEdit.composerControler()->setTextSubScript(false);
0187     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0188 
0189     //
0190     // Image
0191     //
0192     const QString imagePath = KIconLoader::global()->iconPath(QStringLiteral("folder-new"), KIconLoader::Small, false);
0193     textEdit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(imagePath));
0194     QVERIFY(textEdit.composerControler()->isFormattingUsed());
0195     cursor = textEdit.textCursor();
0196     cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1);
0197     cursor.removeSelectedText();
0198     QVERIFY(!textEdit.composerControler()->isFormattingUsed());
0199 }
0200 
0201 void RichTextComposerTest::testQuoting()
0202 {
0203     KPIMTextEdit::RichTextComposer edit;
0204     edit.createActions(new KActionCollection(this));
0205     QVERIFY(edit.isLineQuoted(QStringLiteral("> Hello")));
0206     QVERIFY(edit.isLineQuoted(QStringLiteral(">Hello")));
0207     QVERIFY(!edit.isLineQuoted(QStringLiteral("Hello")));
0208     QCOMPARE(edit.quoteLength(QStringLiteral("Hello")), 0);
0209     QCOMPARE(edit.quoteLength(QStringLiteral(">Hello")), 1);
0210     QCOMPARE(edit.quoteLength(QStringLiteral("> Hello")), 2);
0211     QCOMPARE(edit.quoteLength(QStringLiteral(">>>Hello")), 3);
0212     QCOMPARE(edit.quoteLength(QStringLiteral("> > > Hello")), 6);
0213     QCOMPARE(edit.quoteLength(QStringLiteral("|Hello")), 1);
0214     QCOMPARE(edit.quoteLength(QStringLiteral("| |Hello")), 3);
0215 }
0216 
0217 void RichTextComposerTest::testCleanText()
0218 {
0219     KPIMTextEdit::RichTextComposer edit;
0220     edit.createActions(new KActionCollection(this));
0221     QString html(QStringLiteral("<html><head></head><body>Heelllo&nbsp;World<br>Bye!</body></html>"));
0222     QString plain(QStringLiteral("Heelllo World\nBye!"));
0223     edit.setTextOrHtml(html);
0224     edit.composerControler()->composerImages()->addImage(
0225         QUrl::fromLocalFile(KIconLoader::global()->iconPath(QStringLiteral("folder-new"), KIconLoader::Small, false)));
0226     QVERIFY(edit.textMode() == KPIMTextEdit::RichTextComposer::Rich);
0227     QCOMPARE(edit.composerControler()->toCleanPlainText(), plain);
0228 
0229     edit.show(); // < otherwise toWrappedPlainText can't work, it needs a layout
0230     QCOMPARE(edit.composerControler()->toWrappedPlainText(), plain);
0231 }
0232 
0233 void RichTextComposerTest::testEnter_data()
0234 {
0235     QTest::addColumn<QString>("initalText");
0236     QTest::addColumn<QString>("expectedText");
0237     QTest::addColumn<int>("cursorPos");
0238 
0239     QTest::newRow("") << QStringLiteral("> Hello World") << QStringLiteral("> Hello \n> World") << 8;
0240     QTest::newRow("") << QStringLiteral("Hello World") << QStringLiteral("Hello \nWorld") << 6;
0241     QTest::newRow("") << QStringLiteral("> Hello World") << QStringLiteral("> Hello World\n") << 13;
0242     QTest::newRow("") << QStringLiteral(">Hello World") << QStringLiteral(">Hello \n>World") << 7;
0243     QTest::newRow("") << QStringLiteral("> > Hello World") << QStringLiteral("> > Hello \n> > World") << 10;
0244     QTest::newRow("") << QStringLiteral("| | Hello World") << QStringLiteral("| | Hello \n| | World") << 10;
0245 }
0246 
0247 void RichTextComposerTest::testEnter()
0248 {
0249     QFETCH(QString, initalText);
0250     QFETCH(QString, expectedText);
0251     QFETCH(int, cursorPos);
0252 
0253     KPIMTextEdit::RichTextComposer edit;
0254     edit.createActions(new KActionCollection(this));
0255     edit.setPlainText(initalText);
0256     QTextCursor textCursor(edit.document());
0257     textCursor.setPosition(cursorPos);
0258     edit.setTextCursor(textCursor);
0259 
0260     QTest::keyClick(&edit, Qt::Key_Return);
0261     QCOMPARE(edit.toPlainText(), expectedText);
0262 }
0263 
0264 void RichTextComposerTest::testImages()
0265 {
0266     KPIMTextEdit::RichTextComposer edit;
0267     edit.createActions(new KActionCollection(this));
0268     QString image1Path = KIconLoader::global()->iconPath(QStringLiteral("folder-new"), KIconLoader::Small, false);
0269     QString image2Path = KIconLoader::global()->iconPath(QStringLiteral("arrow-up"), KIconLoader::Small, false);
0270 
0271     // Add one image, check that embeddedImages() returns the right stuff
0272     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image1Path));
0273     KPIMTextEdit::ImageList images = edit.composerControler()->composerImages()->embeddedImages();
0274     KPIMTextEdit::ImageWithNameList imagesWithNames = edit.composerControler()->composerImages()->imagesWithName();
0275     QCOMPARE(images.size(), 1);
0276     QCOMPARE(imagesWithNames.size(), 1);
0277     EmbeddedImage *image = images.first().data();
0278     ImageWithName *imageWithName = imagesWithNames.first().data();
0279     QCOMPARE(image->imageName, QString::fromLatin1("folder-new.png"));
0280     QCOMPARE(imageWithName->name, QString::fromLatin1("folder-new.png"));
0281 
0282     // Also check that it loads the correct image
0283     QImage diskImage(image1Path);
0284     QBuffer buffer;
0285     buffer.open(QIODevice::WriteOnly);
0286     diskImage.save(&buffer, "PNG");
0287     QBuffer imageWithNameBuffer;
0288     imageWithNameBuffer.open(QIODevice::WriteOnly);
0289     imageWithName->image.save(&imageWithNameBuffer, "PNG");
0290     QByteArray encodedImage = KCodecs::Codec::codecForName("base64")->encode(buffer.buffer());
0291     QCOMPARE(image->image, encodedImage);
0292     QCOMPARE(buffer.buffer(), imageWithNameBuffer.buffer());
0293 
0294     // No image should be there after clearing
0295     edit.clear();
0296     QVERIFY(edit.composerControler()->composerImages()->embeddedImages().isEmpty());
0297     QVERIFY(edit.composerControler()->composerImages()->imagesWithName().isEmpty());
0298 
0299     // Check that manually removing the image also empties the image list
0300     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image1Path));
0301     QCOMPARE(edit.composerControler()->composerImages()->embeddedImages().size(), 1);
0302     QCOMPARE(edit.composerControler()->composerImages()->imagesWithName().size(), 1);
0303     QTextCursor cursor = edit.textCursor();
0304     cursor.setPosition(0, QTextCursor::MoveAnchor);
0305     cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1);
0306     cursor.removeSelectedText();
0307     QVERIFY(edit.composerControler()->composerImages()->embeddedImages().isEmpty());
0308     QVERIFY(edit.composerControler()->composerImages()->imagesWithName().isEmpty());
0309 
0310     // Check that adding the identical image two times only adds the image once
0311     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image1Path));
0312     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image1Path));
0313     QCOMPARE(edit.composerControler()->composerImages()->embeddedImages().size(), 1);
0314     QCOMPARE(edit.composerControler()->composerImages()->imagesWithName().size(), 1);
0315 
0316     // Another different image added, and we should have two images
0317     edit.clear();
0318     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image1Path));
0319     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image2Path));
0320     images = edit.composerControler()->composerImages()->embeddedImages();
0321     imagesWithNames = edit.composerControler()->composerImages()->imagesWithName();
0322     QCOMPARE(images.size(), 2);
0323     QCOMPARE(imagesWithNames.size(), 2);
0324     KPIMTextEdit::EmbeddedImage *image1 = images.first().data();
0325     KPIMTextEdit::EmbeddedImage *image2 = images.last().data();
0326     KPIMTextEdit::ImageWithName *imageWithName1 = imagesWithNames.first().data();
0327     KPIMTextEdit::ImageWithName *imageWithName2 = imagesWithNames.last().data();
0328     QCOMPARE(image1->imageName,
0329              QString::fromLatin1("folder-new2.png")); // ### FIXME: should be folder-new.png, but QTextEdit provides no way to remove cached resources!
0330     QCOMPARE(imageWithName1->name, QString::fromLatin1("folder-new2.png"));
0331     QCOMPARE(image2->imageName, QString::fromLatin1("arrow-up.png"));
0332     QCOMPARE(imageWithName2->name, QString::fromLatin1("arrow-up.png"));
0333     QVERIFY(image1->contentID != image2->contentID);
0334 }
0335 
0336 void RichTextComposerTest::testImageHtmlCode()
0337 {
0338     KPIMTextEdit::RichTextComposer edit;
0339     edit.createActions(new KActionCollection(this));
0340     QString image1Path = KIconLoader::global()->iconPath(QStringLiteral("folder-new"), KIconLoader::Small, false);
0341     QString image2Path = KIconLoader::global()->iconPath(QStringLiteral("arrow-up"), KIconLoader::Small, false);
0342     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image1Path));
0343     edit.composerControler()->composerImages()->addImage(QUrl::fromLocalFile(image2Path));
0344     KPIMTextEdit::ImageList images = edit.composerControler()->composerImages()->embeddedImages();
0345     QCOMPARE(images.size(), 2);
0346     KPIMTextEdit::EmbeddedImage *image1 = images.first().data();
0347     KPIMTextEdit::EmbeddedImage *image2 = images.last().data();
0348     QString startHtml = QStringLiteral("<img src=\"arrow-up.png\"><img src=\"folder-new.png\">Bla<b>Blub</b>");
0349     QString endHtml = QStringLiteral("<img src=\"cid:%1\"><img src=\"cid:%2\">Bla<b>Blub</b>").arg(image2->contentID, image1->contentID);
0350     QCOMPARE(KPIMTextEdit::RichTextComposerImages::imageNamesToContentIds(startHtml.toLatin1(), images), endHtml.toLatin1());
0351 }
0352 
0353 void RichTextComposerTest::testDeleteLine_data()
0354 {
0355     QTest::addColumn<QString>("initalText");
0356     QTest::addColumn<QString>("expectedText");
0357     QTest::addColumn<int>("cursorPos");
0358 
0359     QTest::newRow("delete1") << QStringLiteral("line1\nline2\nline3") << QStringLiteral("line1\nline3") << 6;
0360     QTest::newRow("delete2") << QStringLiteral("line1\nline2\nline3") << QStringLiteral("line2\nline3") << 5;
0361     QTest::newRow("delete3") << QStringLiteral("line1\nline2\nline3") << QStringLiteral("line1\nline3") << 11;
0362     QTest::newRow("delete4") << QStringLiteral("line1\nline2\nline3") << QStringLiteral("line2\nline3") << 0;
0363     QTest::newRow("delete5") << QStringLiteral("line1\nline2\nline3") << QStringLiteral("line1\nline2") << 17;
0364     QTest::newRow("delete6") << QStringLiteral("line1") << QString() << 0;
0365     QTest::newRow("delete7") << QStringLiteral("line1") << QString() << 5;
0366 
0367     // Now, test deletion with word wrapping. The line with the Ms is so long that it will get wrapped
0368     QTest::newRow("delete8") << QStringLiteral("line1\nMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3")
0369                              << QStringLiteral("line1\nMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3") << 6;
0370     QTest::newRow("delete9") << QStringLiteral("line1\nMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3")
0371                              << QStringLiteral("line1\nMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\nline3") << 13;
0372 }
0373 
0374 void RichTextComposerTest::testDeleteLine()
0375 {
0376 #if 0
0377     QFETCH(QString, initalText);
0378     QFETCH(QString, expectedText);
0379     QFETCH(int, cursorPos);
0380 
0381     KPIMTextEdit::RichTextComposer edit;
0382     edit.createActions(new KActionCollection(this));
0383     edit.setPlainText(initalText);
0384     QTextCursor cursor = edit.textCursor();
0385     cursor.setPosition(cursorPos);
0386     edit.setTextCursor(cursor);
0387 
0388     edit.show(); // we need a layout for this to work
0389 
0390     edit.composerControler()->deleteCurrentLine();
0391     QCOMPARE(edit.toPlainText(), expectedText);
0392 #endif
0393 }
0394 
0395 void RichTextComposerTest::testLoadImage()
0396 {
0397     KPIMTextEdit::RichTextComposer edit;
0398     edit.createActions(new KActionCollection(this));
0399     QString image1Path = KIconLoader::global()->iconPath(QStringLiteral("folder-new"), KIconLoader::Small, false);
0400     QString image2Path = KIconLoader::global()->iconPath(QStringLiteral("arrow-up"), KIconLoader::Small, false);
0401     QImage image1;
0402     QImage image2;
0403     QVERIFY(image1.load(image1Path));
0404     QVERIFY(image2.load(image2Path));
0405 
0406     edit.setHtml(QStringLiteral("Bla<img src=\"folder-new.png\">Bla"));
0407 
0408     // First try to load an image with a name that doesn't match, it should fail
0409     edit.composerControler()->composerImages()->loadImage(image1, QStringLiteral("doesntmatch"), QStringLiteral("folder-new"));
0410     QVERIFY(!edit.document()->resource(QTextDocument::ImageResource, QUrl(QStringLiteral("folder-new"))).isValid());
0411 
0412     // Now, load the image for real
0413     edit.composerControler()->composerImages()->loadImage(image1, QStringLiteral("folder-new.png"), QStringLiteral("folder-new"));
0414     QVERIFY(edit.document()->resource(QTextDocument::ImageResource, QUrl(QStringLiteral("folder-new"))).isValid());
0415 
0416     // New test with a new textedit (so that we don't use the cached resources
0417     // This example has two images in the same text block, make sure that doesn't crash (bug 204214)
0418     KPIMTextEdit::RichTextComposer edit2;
0419     edit2.createActions(new KActionCollection(this));
0420     edit2.setHtml(QStringLiteral("<img src=\"folder-new.png\"><img src=\"folder-new.png\">"));
0421     edit2.composerControler()->composerImages()->loadImage(image1, QStringLiteral("folder-new.png"), QStringLiteral("folder-new"));
0422     QVERIFY(edit.document()->resource(QTextDocument::ImageResource, QUrl(QStringLiteral("folder-new"))).isValid());
0423     QCOMPARE(edit.composerControler()->composerImages()->embeddedImages().size(), 1);
0424 }
0425 
0426 void RichTextComposerTest::testWrappedPlainText_data()
0427 {
0428     QTest::addColumn<QString>("input");
0429     QTest::addColumn<QString>("output");
0430 
0431     QString defaultStr = QStringLiteral(
0432         "http://example.org/test-test-test-test-test-test-test-test-test-test-test-test-test\n  "
0433         "https://example.org/test-test-test-test-test-test-test-test-test-test-test-test-test\ntest "
0434         "ftp://example.org/test-test-test-test-test-test-test-test-test-test-test-test-test\nftps://example.org/"
0435         "test-test-test-test-test-test-test-test-test-test-test-test-test\n  "
0436         "ldap://example.org/test-test-test-test-test-test-test-test-test-test-test-test-test");
0437     QTest::newRow("default") << defaultStr << defaultStr;
0438     QTest::newRow("empty") << QString() << QString();
0439     QTest::newRow("wrap") << QStringLiteral("foosdfsdf sdsf sdfsdfsfs fsf sdfs df sfsdf dsf sdfsdf sf sf sfsdf sdsdf")
0440                           << QStringLiteral("foosdfsdf sdsf sdfsdfsfs fsf sdfs df sfsdf \ndsf sdfsdf sf sf sfsdf sdsdf");
0441     QTest::newRow("wrap-2") << QStringLiteral("test-test-test-test-test-test-test-test-test-test-test-test-test")
0442                             << QStringLiteral("test-test-test-test-test-test-test-test-\ntest-test-test-test-test");
0443     QTest::newRow("wrap-3") << QStringLiteral("test-test-test-test-test-test-test-test-test-test-test-test-test\n\n")
0444                             << QStringLiteral("test-test-test-test-test-test-test-test-\ntest-test-test-test-test\n\n");
0445 }
0446 
0447 void RichTextComposerTest::testWrappedPlainText()
0448 {
0449     QFETCH(QString, input);
0450     QFETCH(QString, output);
0451     KPIMTextEdit::RichTextComposer edit;
0452     edit.createActions(new KActionCollection(this));
0453     edit.setPlainText(input);
0454 
0455     edit.show(); // < otherwise toWrappedPlainText can't work, it needs a layout
0456 
0457     QCOMPARE(edit.composerControler()->toWrappedPlainText(), output);
0458 }
0459 
0460 void RichTextComposerTest::testEnableDisableActions()
0461 {
0462     KPIMTextEdit::RichTextComposer composer;
0463     auto actionCollection = new KActionCollection(&composer);
0464     composer.createActions(actionCollection);
0465     bool enableAction = true;
0466     composer.setEnableActions(enableAction);
0467     for (QAction *act : composer.actions()) {
0468         QCOMPARE(act->isEnabled(), enableAction);
0469     }
0470 
0471     enableAction = false;
0472     composer.setEnableActions(enableAction);
0473     for (QAction *act : composer.actions()) {
0474         QCOMPARE(act->isEnabled(), enableAction);
0475     }
0476 }
0477 
0478 void RichTextComposerTest::shouldHaveDefaultValue()
0479 {
0480     KPIMTextEdit::RichTextComposer composer;
0481     auto actionCollection = new KActionCollection(&composer);
0482     composer.createActions(actionCollection);
0483     QCOMPARE(composer.linePosition(), 0);
0484     QCOMPARE(composer.columnNumber(), 0);
0485     QCOMPARE(composer.textMode(), KPIMTextEdit::RichTextComposer::Plain);
0486     QVERIFY(!composer.acceptRichText());
0487     QVERIFY(!composer.quotePrefixName().isEmpty());
0488 }
0489 
0490 void RichTextComposerTest::shouldChangeMode()
0491 {
0492     KPIMTextEdit::RichTextComposer composer;
0493     auto actionCollection = new KActionCollection(&composer);
0494     composer.createActions(actionCollection);
0495     QSignalSpy spy(&composer, &RichTextComposer::textModeChanged);
0496     composer.activateRichText();
0497     QCOMPARE(composer.textMode(), KPIMTextEdit::RichTextComposer::Rich);
0498     QVERIFY(composer.acceptRichText());
0499     QCOMPARE(spy.count(), 1);
0500 }
0501 
0502 QTEST_MAIN(RichTextComposerTest)
0503 
0504 #include "moc_richtextcomposertest.cpp"