File indexing completed on 2024-05-05 05:17:16

0001 /*
0002     SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
0003     SPDX-FileCopyrightText: 2008 Thomas McGuire <mcguire@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #undef QT_USE_FAST_CONCATENATION
0009 #undef QT_USE_FAST_OPERATOR_PLUS
0010 
0011 #include "signaturetest.h"
0012 #include <QTest>
0013 
0014 #include "../src/widgets/signaturerichtexteditor.cpp"
0015 #include "signature.h"
0016 
0017 #include <KActionCollection>
0018 #include <KConfig>
0019 #include <KConfigGroup>
0020 #include <KShell>
0021 #include <QDir>
0022 #include <QStandardPaths>
0023 
0024 #include <KPIMTextEdit/RichTextComposer>
0025 #include <KPIMTextEdit/RichTextComposerControler>
0026 #include <KPIMTextEdit/RichTextComposerImages>
0027 using namespace KIdentityManagementCore;
0028 using namespace KPIMTextEdit;
0029 
0030 QTEST_MAIN(SignatureTester)
0031 
0032 void SignatureTester::testEqualSignatures()
0033 {
0034     Signature sig1;
0035     sig1.setText(QStringLiteral("Hello World"));
0036     sig1.setEnabledSignature(true);
0037     Signature sig2(sig1);
0038     QVERIFY(sig1 == sig2);
0039     QCOMPARE(sig2.text(), QStringLiteral("Hello World"));
0040     QCOMPARE(sig2.type(), Signature::Inlined);
0041     QCOMPARE(sig2.rawText(), QStringLiteral("Hello World"));
0042     QVERIFY(!sig2.isInlinedHtml());
0043     QCOMPARE(sig2.withSeparator(), QStringLiteral("-- \nHello World"));
0044     QVERIFY(sig2.isEnabledSignature());
0045 
0046     Signature sig3 = sig1;
0047     QVERIFY(sig1 == sig3);
0048     QCOMPARE(sig3.text(), QStringLiteral("Hello World"));
0049     QCOMPARE(sig3.type(), Signature::Inlined);
0050     QCOMPARE(sig3.rawText(), QStringLiteral("Hello World"));
0051     QVERIFY(!sig3.isInlinedHtml());
0052     QCOMPARE(sig3.withSeparator(), QStringLiteral("-- \nHello World"));
0053     QVERIFY(sig3.isEnabledSignature());
0054 }
0055 
0056 void SignatureTester::testSignatures()
0057 {
0058     Signature sig1;
0059     sig1.setText(QStringLiteral("Hello World"));
0060     QCOMPARE(sig1.text(), QStringLiteral("Hello World"));
0061     QCOMPARE(sig1.type(), Signature::Inlined);
0062     QCOMPARE(sig1.rawText(), QStringLiteral("Hello World"));
0063     QVERIFY(!sig1.isInlinedHtml());
0064     QCOMPARE(sig1.withSeparator(), QStringLiteral("-- \nHello World"));
0065     QVERIFY(!sig1.isEnabledSignature());
0066 
0067     Signature sig2;
0068     sig2.setText(QStringLiteral("<b>Hello</b> World"));
0069     sig2.setInlinedHtml(true);
0070     QVERIFY(sig2.isInlinedHtml());
0071     QCOMPARE(sig2.type(), Signature::Inlined);
0072     QCOMPARE(sig2.rawText(), QStringLiteral("<b>Hello</b> World"));
0073     QCOMPARE(sig2.withSeparator(), QStringLiteral("-- <br><b>Hello</b> World"));
0074     QVERIFY(!sig2.isEnabledSignature());
0075 
0076     const QString dataFilePath = QStringLiteral(SIGNATURETEST_DATA_FILE);
0077     // Read this very file in, we use it for the tests
0078     QFile thisFile(dataFilePath);
0079     thisFile.open(QIODevice::ReadOnly);
0080     QString fileContent = QString::fromUtf8(thisFile.readAll());
0081 
0082     if (!QStandardPaths::findExecutable(QStringLiteral("cat")).isEmpty()) {
0083         Signature sig3;
0084         sig3.setPath(QStringLiteral("cat ") + KShell::quoteArg(dataFilePath), true);
0085         QCOMPARE(sig3.rawText(), fileContent);
0086         QVERIFY(!sig3.isInlinedHtml());
0087         QVERIFY(sig3.text().isEmpty());
0088         QCOMPARE(sig3.type(), Signature::FromCommand);
0089         QCOMPARE(sig3.withSeparator(), QString(QStringLiteral("-- \n") + fileContent));
0090         QVERIFY(!sig3.isEnabledSignature());
0091     }
0092 
0093     Signature sig4;
0094     sig4.setPath(dataFilePath, false);
0095     QCOMPARE(sig4.rawText(), fileContent);
0096     QVERIFY(!sig4.isInlinedHtml());
0097     QVERIFY(sig4.text().isEmpty());
0098     QCOMPARE(sig4.type(), Signature::FromFile);
0099     QCOMPARE(sig4.withSeparator(), QString(QStringLiteral("-- \n") + fileContent));
0100     QVERIFY(!sig4.isEnabledSignature());
0101 }
0102 
0103 static void setCursorPos(QTextEdit &edit, int pos)
0104 {
0105     QTextCursor cursor(edit.document());
0106     cursor.setPosition(pos);
0107     edit.setTextCursor(cursor);
0108 }
0109 
0110 void SignatureTester::testTextEditInsertion()
0111 {
0112     KPIMTextEdit::RichTextComposer edit;
0113     edit.createActions(new KActionCollection(this));
0114     Signature sig;
0115     sig.setEnabledSignature(true);
0116     sig.setText(QStringLiteral("Hello World"));
0117 
0118     // Test inserting signature at start, with separators. Make sure two new
0119     // lines are inserted before the signature
0120 
0121     edit.setPlainText(QStringLiteral("Bla Bla"));
0122     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::Start, Signature::AddSeparator | Signature::AddNewLines, &edit);
0123     QVERIFY(edit.textMode() == KPIMTextEdit::RichTextComposer::Plain);
0124     QCOMPARE(edit.toPlainText(), QStringLiteral("\n\n-- \nHello World\nBla Bla"));
0125 
0126     // Test inserting signature at end. make sure cursor position is preserved
0127     edit.clear();
0128     edit.setPlainText(QStringLiteral("Bla Bla"));
0129     setCursorPos(edit, 4);
0130     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::End, Signature::AddSeparator | Signature::AddNewLines, &edit);
0131     QCOMPARE(edit.toPlainText(), QStringLiteral("Bla Bla\n-- \nHello World"));
0132     QCOMPARE(edit.textCursor().position(), 4);
0133 
0134     // test inserting a signature at cursor position. make sure the signature is inserted
0135     // to the beginning of the line and make sure modified state is preserved
0136     edit.clear();
0137     edit.setPlainText(QStringLiteral("Bla Bla"));
0138     setCursorPos(edit, 4);
0139     edit.document()->setModified(false);
0140     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::AtCursor, Signature::AddSeparator | Signature::AddNewLines, &edit);
0141     QCOMPARE(edit.toPlainText(), QStringLiteral("-- \nHello World\nBla Bla"));
0142     QCOMPARE(edit.textCursor().position(), 20);
0143     QVERIFY(!edit.document()->isModified());
0144 
0145     // make sure undo undoes everything in one go
0146     edit.undo();
0147     QCOMPARE(edit.toPlainText(), QStringLiteral("Bla Bla"));
0148 
0149     // test inserting signature without separator.
0150     // make sure cursor position and modified state is preserved.
0151     edit.clear();
0152     edit.setPlainText(QStringLiteral("Bla Bla"));
0153     setCursorPos(edit, 4);
0154     edit.document()->setModified(true);
0155     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::End, Signature::AddNewLines, &edit);
0156     QCOMPARE(edit.toPlainText(), QStringLiteral("Bla Bla\nHello World"));
0157     QCOMPARE(edit.textCursor().position(), 4);
0158     QVERIFY(edit.document()->isModified());
0159 
0160     sig.setText(QStringLiteral("Hello<br>World"));
0161     sig.setInlinedHtml(true);
0162 
0163     // test that html signatures turn html on and have correct line endings (<br> vs \n)
0164     edit.clear();
0165     edit.setPlainText(QStringLiteral("Bla Bla"));
0166     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::End, Signature::AddSeparator | Signature::AddNewLines, &edit);
0167     QVERIFY(edit.textMode() == KPIMTextEdit::RichTextComposer::Rich);
0168     QCOMPARE(edit.toPlainText(), QStringLiteral("Bla Bla\n-- \nHello\nWorld"));
0169 }
0170 
0171 void SignatureTester::testBug167961()
0172 {
0173     KPIMTextEdit::RichTextComposer edit;
0174     edit.createActions(new KActionCollection(this));
0175     Signature sig;
0176     sig.setEnabledSignature(true);
0177     sig.setText(QStringLiteral("BLA"));
0178 
0179     // Test that the cursor is still at the start when appending a sig into
0180     // an empty text edit
0181     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::End, Signature::AddSeparator | Signature::AddNewLines, &edit);
0182     QCOMPARE(edit.textCursor().position(), 0);
0183 
0184     // When prepending a sig, the cursor should also be at the start, see bug 211634
0185     edit.clear();
0186     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::Start, Signature::AddSeparator | Signature::AddNewLines, &edit);
0187     QCOMPARE(edit.textCursor().position(), 0);
0188 }
0189 
0190 // Make writeConfig() public, we need it
0191 class MySignature : public Signature
0192 {
0193 public:
0194     using Signature::readConfig;
0195     using Signature::writeConfig;
0196 };
0197 
0198 void SignatureTester::testImages()
0199 {
0200     KPIMTextEdit::RichTextComposer edit;
0201     edit.createActions(new KActionCollection(this));
0202 
0203     QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
0204     img.fill(Qt::green);
0205     QString image1Path = QCoreApplication::applicationDirPath() + QLatin1StringView("/image.png");
0206     img.save(image1Path);
0207 
0208     QImage image1;
0209     QImage image2;
0210     QVERIFY(image1.load(image1Path));
0211     QVERIFY(image2.load(image1Path));
0212     QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/emailidentities/unittest/");
0213     QDir().mkpath(path);
0214     QString configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/signaturetest");
0215     QDir().mkpath(configPath);
0216     KConfig config(configPath);
0217     KConfigGroup group1 = config.group(QStringLiteral("Signature1"));
0218 
0219     MySignature sig;
0220     sig.setEnabledSignature(true);
0221     sig.setImageLocation(path);
0222     sig.setInlinedHtml(true);
0223     sig.setText(QStringLiteral("Bla<img src=\"folder-new.png\">Bla"));
0224     sig.addImage(image1, QStringLiteral("folder-new.png"));
0225     sig.writeConfig(group1);
0226 
0227     // OK, signature saved, the image should be saved as well
0228     QDir dir(path);
0229     QStringList entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
0230     QCOMPARE(entryList.count(), 1);
0231     QCOMPARE(entryList.first(), QStringLiteral("folder-new.png"));
0232 
0233     // Now, set the text of the signature to something without images, then save it.
0234     // The signature class should have removed the images.
0235     sig.setText(QStringLiteral("ascii ribbon campaign - against html mail"));
0236     sig.writeConfig(group1);
0237     entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
0238     QCOMPARE(entryList.count(), 0);
0239 
0240     // Enable images again, this time with two of the buggers
0241     sig.setText(QStringLiteral("Bla<img src=\"folder-new.png\">Bla<img src=\"arrow-up.png\">Bla"));
0242     sig.addImage(image1, QStringLiteral("folder-new.png"));
0243     sig.addImage(image2, QStringLiteral("arrow-up.png"));
0244     sig.writeConfig(group1);
0245     entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
0246     QCOMPARE(entryList.count(), 2);
0247     QCOMPARE(entryList.first(), QStringLiteral("arrow-up.png"));
0248     QCOMPARE(entryList.last(), QStringLiteral("folder-new.png"));
0249 
0250     // Now, create a second signature instance from the same config, and make sure it can still
0251     // read the images, and it does not mess up
0252     MySignature sig2;
0253     sig2.readConfig(group1);
0254     SignatureRichTextEditor::insertIntoTextEdit(sig2, Signature::End, Signature::AddSeparator | Signature::AddNewLines, &edit);
0255     QCOMPARE(edit.composerControler()->composerImages()->embeddedImages().count(), 2);
0256     QCOMPARE(sig2.text(), QStringLiteral("Bla<img src=\"folder-new.png\">Bla<img src=\"arrow-up.png\">Bla"));
0257     sig2.writeConfig(group1);
0258     entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
0259     QCOMPARE(entryList.count(), 2);
0260     QCOMPARE(entryList.first(), QStringLiteral("arrow-up.png"));
0261     QCOMPARE(entryList.last(), QStringLiteral("folder-new.png"));
0262 
0263     // Remove one image from the signature, and make sure only 1 file is left one file system.
0264     sig2.setText(QStringLiteral("<img src=\"folder-new.png\">"));
0265     sig2.writeConfig(group1);
0266     edit.clear();
0267     SignatureRichTextEditor::insertIntoTextEdit(sig2, Signature::End, Signature::AddSeparator | Signature::AddNewLines, &edit);
0268     QCOMPARE(edit.composerControler()->composerImages()->embeddedImages().size(), 1);
0269     entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
0270     QCOMPARE(entryList.count(), 1);
0271 }
0272 
0273 void SignatureTester::testLinebreaks()
0274 {
0275     Signature sig;
0276     sig.setEnabledSignature(true);
0277     sig.setType(Signature::Inlined);
0278     sig.setInlinedHtml(true);
0279     sig.setText(QStringLiteral("Hans Mustermann<br>Musterstr. 42"));
0280 
0281     KPIMTextEdit::RichTextComposer edit;
0282     edit.createActions(new KActionCollection(this));
0283     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::Start, Signature::AddNothing, &edit);
0284     QCOMPARE(edit.toPlainText(), QStringLiteral("Hans Mustermann\nMusterstr. 42"));
0285 
0286     edit.clear();
0287     sig.setText(QStringLiteral("<p>Hans Mustermann</p><br>Musterstr. 42"));
0288     SignatureRichTextEditor::insertIntoTextEdit(sig, Signature::Start, Signature::AddSeparator, &edit);
0289     QEXPECT_FAIL("", "This test is probably bogus, since Qt doesn't seem to produce HTML like this anymore.", Continue);
0290     QCOMPARE(edit.toPlainText(), QStringLiteral("-- \nHans Mustermann\nMusterstr. 42"));
0291 }
0292 
0293 #include "moc_signaturetest.cpp"