File indexing completed on 2025-03-09 04:54:32

0001 /*
0002    SPDX-FileCopyrightText: 2018 Sandro Knauß <sknauss@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 #include "grantleeheaderstyletest.h"
0007 
0008 #include <MessageViewer/GrantleeHeaderStyle>
0009 #include <MimeTreeParser/NodeHelper>
0010 
0011 #include <GrantleeTheme/GrantleeThemeManager>
0012 
0013 #include <QFile>
0014 #include <QProcess>
0015 #include <QRegularExpression>
0016 #include <QStandardPaths>
0017 #include <QStringList>
0018 #include <QTest>
0019 
0020 using namespace MessageViewer;
0021 
0022 QTEST_MAIN(GrantleeHeaderStyleTest)
0023 
0024 void testHeaderFile(const HeaderStyle &style, KMime::Message *msg, const QString &name)
0025 {
0026     QString header = QStringLiteral(
0027         "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
0028         "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
0029         "<body>\n");
0030     header += style.format(msg) + QStringLiteral("</div>");
0031     header += QStringLiteral("\n</body>\n</html>\n");
0032 
0033     header.replace(QStringLiteral("file://") + style.theme().absolutePath(), QStringLiteral("file://PATHTOSTYLE"));
0034     header.replace(QRegularExpression(QStringLiteral("[\t ]+")), QStringLiteral(" "));
0035     header.replace(QRegularExpression(QStringLiteral("[\t ]*\n+[\t ]*")), QStringLiteral("\n"));
0036     header.replace(QRegularExpression(QStringLiteral("([\n\t ])\\1+")), QStringLiteral("\\1"));
0037     header.replace(QRegularExpression(QStringLiteral(">\n+[\t ]*")), QStringLiteral(">"));
0038     header.replace(QRegularExpression(QStringLiteral("[\t ]*\n+[\t ]*<")), QStringLiteral("<"));
0039     header.replace(QLatin1StringView("&nbsp;"), QLatin1StringView("NBSP_ENTITY_PLACEHOLDER")); // xmlling chokes on &nbsp;
0040 
0041     QString outName = name + QStringLiteral(".out.html");
0042     QString fName = name + QStringLiteral(".html");
0043 
0044     QVERIFY(QFile(QStringLiteral(HEADER_DATA_DIR "/") + fName).exists());
0045 
0046     {
0047         QFile f(outName);
0048         f.open(QIODevice::WriteOnly);
0049         f.write(header.toUtf8());
0050         f.close();
0051     }
0052     // TODO add proper cmake check for xmllint and diff
0053     {
0054         const QStringList args = QStringList() << QStringLiteral("--format") << QStringLiteral("--encode") << QStringLiteral("UTF8")
0055                                                << QStringLiteral("--output") << fName << outName;
0056         QCOMPARE(QProcess::execute(QStringLiteral("xmllint"), args), 0);
0057     }
0058 
0059     {
0060         // compare to reference file
0061         const QStringList args = QStringList() << QStringLiteral("-u") << fName << QStringLiteral(HEADER_DATA_DIR "/") + fName;
0062         QProcess proc;
0063         proc.setProcessChannelMode(QProcess::ForwardedChannels);
0064         proc.start(QStringLiteral("diff"), args);
0065         QVERIFY(proc.waitForFinished());
0066 
0067         QCOMPARE(proc.exitCode(), 0);
0068     }
0069 }
0070 
0071 KMime::Message::Ptr readAndParseMail(const QString &mailFile)
0072 {
0073     QFile file(QStringLiteral(HEADER_DATA_DIR) + QLatin1Char('/') + mailFile);
0074     bool openFile = file.open(QIODevice::ReadOnly);
0075     Q_ASSERT(openFile);
0076     const QByteArray data = KMime::CRLFtoLF(file.readAll());
0077     Q_ASSERT(!data.isEmpty());
0078     KMime::Message::Ptr msg(new KMime::Message);
0079     msg->setContent(data);
0080     msg->parse();
0081     return msg;
0082 }
0083 
0084 void GrantleeHeaderStyleTest::initTestCase()
0085 {
0086     qputenv("LC_ALL", "en_US.UTF-8");
0087     QStandardPaths::setTestModeEnabled(true);
0088     expectedDataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0089     expectedDataLocation += QStringLiteral("/messageviewer/defaultthemes");
0090     QDir targetDir(expectedDataLocation);
0091     QDir sourceDir(QStringLiteral(GRANTLEETHEME_DATA_DIR));
0092     const auto themeDirs = sourceDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
0093 
0094     if (targetDir.exists()) {
0095         QVERIFY(targetDir.removeRecursively()); // Start with a fresh copy
0096     }
0097 
0098     for (const auto &themeDir : themeDirs) {
0099         const QString &dirName = targetDir.filePath(themeDir.fileName());
0100         QVERIFY(targetDir.mkpath(themeDir.fileName()));
0101         const auto files = QDir(themeDir.absoluteFilePath()).entryInfoList(QDir::Files | QDir::Readable | QDir::NoSymLinks);
0102         for (const auto &file : files) {
0103             const QString &newPath = dirName + QLatin1Char('/') + file.fileName();
0104             QVERIFY(QFile(file.absoluteFilePath()).copy(newPath));
0105         }
0106     }
0107     const auto configDir = QDir(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation));
0108     if (!configDir.exists()) {
0109         QVERIFY(configDir.mkpath(QStringLiteral(".")));
0110     }
0111     QFile antispamFile(QStringLiteral(HEADER_DATA_DIR "/kmail.antispamrc"));
0112     const QString &newPath = configDir.filePath(QStringLiteral("kmail.antispamrc"));
0113     antispamFile.copy(newPath);
0114 }
0115 
0116 void GrantleeHeaderStyleTest::cleanupTestCase()
0117 {
0118     QDir targetDir(expectedDataLocation);
0119 
0120     if (targetDir.exists()) {
0121         QVERIFY(targetDir.removeRecursively()); // Start with a fresh copy
0122     }
0123 }
0124 
0125 const GrantleeTheme::Theme defaultTheme(const QString &name = QStringLiteral("5.2"))
0126 {
0127     const QStringList defaultThemePath =
0128         QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("messageviewer/defaultthemes/"), QStandardPaths::LocateDirectory);
0129     return GrantleeTheme::ThemeManager::loadTheme(defaultThemePath.at(0) + QStringLiteral("/") + name, name, QStringLiteral("kmail_default.desktop"));
0130 }
0131 
0132 void GrantleeHeaderStyleTest::testName()
0133 {
0134     auto style = GrantleeHeaderStyle();
0135     QCOMPARE(style.name(), "grantlee");
0136 }
0137 
0138 void GrantleeHeaderStyleTest::testRenderHeaderNoMessage()
0139 {
0140     auto style = GrantleeHeaderStyle();
0141     QCOMPARE(style.format(nullptr), QString());
0142 }
0143 
0144 void GrantleeHeaderStyleTest::testRenderHeaderInvalidTheme()
0145 {
0146     auto style = GrantleeHeaderStyle();
0147     auto aMsg = new KMime::Message();
0148     QCOMPARE(style.theme().isValid(), false);
0149     QCOMPARE(style.format(aMsg), QStringLiteral("Grantlee theme \"\" is not valid."));
0150     delete aMsg;
0151 }
0152 
0153 void GrantleeHeaderStyleTest::testRenderHeaderEmpty()
0154 {
0155     auto style = GrantleeHeaderStyle();
0156     auto aMsg = new KMime::Message();
0157     MimeTreeParser::NodeHelper nodeHelper;
0158     style.setTheme(defaultTheme());
0159     style.setNodeHelper(&nodeHelper);
0160 
0161     testHeaderFile(style, aMsg, QStringLiteral("empty"));
0162     delete aMsg;
0163 }
0164 
0165 void GrantleeHeaderStyleTest::testRenderHeaderVCard()
0166 {
0167     auto style = GrantleeHeaderStyle();
0168     auto aMsg = new KMime::Message();
0169     MimeTreeParser::NodeHelper nodeHelper;
0170     style.setTheme(defaultTheme());
0171     style.setNodeHelper(&nodeHelper);
0172     style.setVCardName(QStringLiteral("nofile.vcd"));
0173 
0174     testHeaderFile(style, aMsg, QStringLiteral("vcard"));
0175     delete aMsg;
0176 }
0177 
0178 void GrantleeHeaderStyleTest::testRenderHeader_data()
0179 {
0180     QTest::addColumn<QString>("mailFileName");
0181 
0182     QDir dir(QStringLiteral(HEADER_DATA_DIR));
0183     const auto l = dir.entryList(QStringList(QStringLiteral("*.mbox")), QDir::Files | QDir::Readable | QDir::NoSymLinks);
0184     for (const QString &file : l) {
0185         if (!QFile::exists(dir.path() + QLatin1Char('/') + file + QStringLiteral(".html"))) {
0186             continue;
0187         }
0188         QTest::newRow(file.toLatin1().constData()) << file;
0189     }
0190 }
0191 
0192 void GrantleeHeaderStyleTest::testRenderHeader()
0193 {
0194     QFETCH(QString, mailFileName);
0195 
0196     auto style = GrantleeHeaderStyle();
0197     MimeTreeParser::NodeHelper nodeHelper;
0198     style.setNodeHelper(&nodeHelper);
0199     auto aMsg = readAndParseMail(mailFileName);
0200     style.setTheme(defaultTheme());
0201 
0202     testHeaderFile(style, aMsg.data(), mailFileName);
0203     aMsg.clear();
0204 }
0205 
0206 #include "moc_grantleeheaderstyletest.cpp"