File indexing completed on 2024-05-12 16:46:19
0001 /*************************************************************************** 0002 Copyright (C) 2015 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #undef QT_NO_CAST_FROM_ASCII 0026 0027 #include "htmlexportertest.h" 0028 0029 #include "../translators/htmlexporter.h" 0030 #include "../translators/tellicoimporter.h" 0031 #include "../collections/bookcollection.h" 0032 #include "../collections/videocollection.h" 0033 #include "../collections/musiccollection.h" 0034 #include "../collectionfactory.h" 0035 #include "../entry.h" 0036 #include "../document.h" 0037 #include "../images/imagefactory.h" 0038 #include "../utils/datafileregistry.h" 0039 #include "../config/tellico_config.h" 0040 0041 #include <QTest> 0042 #include <QRegularExpression> 0043 #include <QTemporaryDir> 0044 #include <QFile> 0045 #include <QStandardPaths> 0046 #include <QProcess> 0047 0048 QTEST_GUILESS_MAIN( HtmlExporterTest ) 0049 0050 void HtmlExporterTest::initTestCase() { 0051 QStandardPaths::setTestModeEnabled(true); 0052 Tellico::ImageFactory::init(); 0053 Tellico::RegisterCollection<Tellico::Data::BookCollection> registerBook(Tellico::Data::Collection::Book, "book"); 0054 Tellico::RegisterCollection<Tellico::Data::VideoCollection> registerVideo(Tellico::Data::Collection::Video, "video"); 0055 Tellico::RegisterCollection<Tellico::Data::VideoCollection> registerMusic(Tellico::Data::Collection::Album, "album"); 0056 Tellico::DataFileRegistry::self()->addDataLocation(QFINDTESTDATA("../../xslt/tellico2html.xsl")); 0057 Tellico::DataFileRegistry::self()->addDataLocation(QFINDTESTDATA("../../xslt/entry-templates/Fancy.xsl")); 0058 Tellico::DataFileRegistry::self()->addDataLocation(QFINDTESTDATA("../../xslt/report-templates/Column_View.xsl")); 0059 } 0060 0061 void HtmlExporterTest::cleanupTestCase() { 0062 Tellico::ImageFactory::clean(true); 0063 } 0064 0065 void HtmlExporterTest::testHtml() { 0066 Tellico::Config::setImageLocation(Tellico::Config::ImagesInLocalDir); 0067 // the default collection will use a temporary directory as a local image dir 0068 QVERIFY(!Tellico::ImageFactory::localDir().isEmpty()); 0069 0070 QString tempDirName; 0071 QTemporaryDir tempDir; 0072 QVERIFY(tempDir.isValid()); 0073 tempDir.setAutoRemove(true); 0074 tempDirName = tempDir.path(); 0075 QString fileName = tempDirName + "/with-image.tc"; 0076 QString imageDirName = tempDirName + "/with-image_files/"; 0077 0078 // copy a collection file that includes an image into the temporary directory 0079 QVERIFY(QFile::copy(QFINDTESTDATA("data/with-image.tc"), fileName)); 0080 0081 Tellico::Data::Document* doc = Tellico::Data::Document::self(); 0082 QVERIFY(doc->openDocument(QUrl::fromLocalFile(fileName))); 0083 QCOMPARE(Tellico::ImageFactory::localDir(), imageDirName); 0084 // save the document, so the images get copied out of the .tc file into the local image directory 0085 QVERIFY(doc->saveDocument(QUrl::fromLocalFile(fileName))); 0086 0087 Tellico::Data::CollPtr coll = doc->collection(); 0088 QVERIFY(coll); 0089 0090 Tellico::Export::HTMLExporter exp(coll); 0091 exp.setEntries(coll->entries()); 0092 exp.setExportEntryFiles(true); 0093 exp.setEntryXSLTFile(QStringLiteral("Fancy")); 0094 exp.setColumns(QStringList() << QStringLiteral("Title") << QStringLiteral("Gift") 0095 << QStringLiteral("Rating") << QStringLiteral("Front Cover")); 0096 exp.setURL(QUrl::fromLocalFile(tempDirName + "/testHtml.html")); 0097 0098 QString output = exp.text(); 0099 QVERIFY(!output.isEmpty()); 0100 0101 // verify the relative location of the tellico2html.js file 0102 QVERIFY(output.contains(QStringLiteral("src=\"testHtml_files/tellico2html.js"))); 0103 // verify relative location of image pics 0104 QVERIFY(output.contains(QStringLiteral("src=\"testHtml_files/pics/checkmark.png"))); 0105 // verify relative location of entry link 0106 QVERIFY(output.contains(QStringLiteral("href=\"testHtml_files/Catching_Fire__The_Second_Book_of_the_Hunger_Games_-1.html"))); 0107 // verify relative location of image file 0108 QVERIFY(output.contains(QStringLiteral("src=\"testHtml_files/17b54b2a742c6d342a75f122d615a793.jpeg"))); 0109 0110 QVERIFY(exp.exec()); 0111 QFile f(tempDirName + "/testHtml.html"); 0112 QVERIFY(f.exists()); 0113 QVERIFY(f.open(QIODevice::ReadOnly | QIODevice::Text)); 0114 0115 QTextStream in(&f); 0116 QString fileText = in.readAll(); 0117 QVERIFY(fileText.contains(QStringLiteral("src=\"testHtml_files/tellico2html.js"))); 0118 QVERIFY(fileText.contains(QStringLiteral("src=\"testHtml_files/pics/checkmark.png"))); 0119 QVERIFY(fileText.contains(QStringLiteral("href=\"testHtml_files/Catching_Fire__The_Second_Book_of_the_Hunger_Games_-1.html"))); 0120 QVERIFY(fileText.contains(QStringLiteral("src=\"testHtml_files/17b54b2a742c6d342a75f122d615a793.jpeg"))); 0121 0122 QVERIFY(QFile::exists(tempDirName + "/testHtml_files/tellico2html.js")); 0123 QVERIFY(QFile::exists(tempDirName + "/testHtml_files/pics/checkmark.png")); 0124 QVERIFY(QFile::exists(tempDirName + "/testHtml_files/17b54b2a742c6d342a75f122d615a793.jpeg")); 0125 0126 // check entry html output 0127 QFile f2(tempDirName + "/testHtml_files/Catching_Fire__The_Second_Book_of_the_Hunger_Games_-1.html"); 0128 QVERIFY(f2.exists()); 0129 QVERIFY(f2.open(QIODevice::ReadOnly | QIODevice::Text)); 0130 0131 QTextStream in2(&f2); 0132 QString entryText = in2.readAll(); 0133 // verify relative location of image file 0134 QVERIFY(entryText.contains(QStringLiteral("src=\"./17b54b2a742c6d342a75f122d615a793.jpeg"))); 0135 // verify relative location of image pics 0136 QVERIFY(entryText.contains(QStringLiteral("src=\"pics/checkmark.png"))); 0137 // verify link to parent html file 0138 QVERIFY(entryText.contains(QStringLiteral("href=\"../testHtml.html"))); 0139 0140 // sanity check, the directory should not exists after QTemporaryDir destruction 0141 tempDir.remove(); 0142 QVERIFY(!QDir(tempDirName).exists()); 0143 } 0144 0145 void HtmlExporterTest::testHtmlTitle() { 0146 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true)); 0147 coll->setTitle(QStringLiteral("Robby's Books")); 0148 0149 Tellico::Data::EntryPtr e(new Tellico::Data::Entry(coll)); 0150 coll->addEntries(e); 0151 0152 Tellico::Export::HTMLExporter exporter(coll); 0153 exporter.setEntries(coll->entries()); 0154 0155 QString output = exporter.text(); 0156 // qDebug() << output; 0157 QVERIFY(!output.isEmpty()); 0158 0159 // check https://bugs.kde.org/show_bug.cgi?id=348381 0160 QRegularExpression rx("<title>.*</title>"); 0161 QRegularExpressionMatch match = rx.match(output); 0162 QVERIFY(match.hasMatch()); 0163 QCOMPARE(match.captured(), QStringLiteral("<title>Robby's Books</title>")); 0164 } 0165 0166 void HtmlExporterTest::testReportHtml() { 0167 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true)); 0168 coll->setTitle(QStringLiteral("Robby's Books")); 0169 0170 Tellico::Data::EntryPtr e(new Tellico::Data::Entry(coll)); 0171 e->setField(QStringLiteral("title"), QStringLiteral("My Title")); 0172 e->setField(QStringLiteral("rating"), QStringLiteral("3")); 0173 coll->addEntries(e); 0174 0175 Tellico::Export::HTMLExporter exporter(coll); 0176 exporter.setXSLTFile(QFINDTESTDATA("../../xslt/report-templates/Column_View.xsl")); 0177 exporter.setEntries(coll->entries()); 0178 0179 QString output = exporter.text(); 0180 QVERIFY(!output.isEmpty()); 0181 0182 // check that cdate is passed correctly 0183 QRegularExpression rx("<p id=\"header-right\">(.*)</p>"); 0184 QRegularExpressionMatch match = rx.match(output); 0185 QVERIFY(match.hasMatch()); 0186 QCOMPARE(match.captured(1), QLocale().toString(QDate::currentDate())); 0187 0188 // test image location in tmp directory 0189 Tellico::Export::HTMLExporter exporter2(coll); 0190 exporter2.setXSLTFile(QFINDTESTDATA("../../xslt/report-templates/Image_List.xsl")); 0191 exporter2.setEntries(coll->entries()); 0192 exporter2.setColumns(QStringList() << QStringLiteral("Title") << QStringLiteral("Rating")); 0193 0194 QString output2 = exporter2.text(); 0195 QVERIFY(!output2.isEmpty()); 0196 // the rating pic image needs to be an absolute local path 0197 QRegularExpression starsPathRx(QStringLiteral("src=\"(.+stars3.png)\"")); 0198 auto starsMatch = starsPathRx.match(output2); 0199 QVERIFY(starsMatch.hasMatch()); 0200 QFileInfo starsInfo(starsMatch.captured(1)); 0201 qDebug() << "Looking for absolute path:" << starsInfo.filePath(); 0202 QVERIFY(starsInfo.isAbsolute()); 0203 } 0204 0205 void HtmlExporterTest::testDirectoryNames() { 0206 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true)); 0207 Tellico::Export::HTMLExporter exp(coll); 0208 0209 exp.setURL(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/test.html"))); 0210 QCOMPARE(exp.fileDir(), QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/test_files/"))); 0211 QCOMPARE(exp.fileDirName(), QStringLiteral("test_files/")); 0212 0213 // setCollectionUrl used when exporting entry files only 0214 exp.setCollectionURL(QUrl::fromLocalFile(QDir::homePath())); 0215 QCOMPARE(exp.fileDirName(), QStringLiteral("/")); 0216 } 0217 0218 void HtmlExporterTest::testTemplates() { 0219 const QString tidy = QStandardPaths::findExecutable(QStringLiteral("tidy")); 0220 if(tidy.isEmpty()) { 0221 QSKIP("This test requires tidy", SkipAll); 0222 } 0223 0224 QFETCH(QString, xsltFile); 0225 QFETCH(QString, tellicoFile); 0226 Tellico::ImageFactory::clean(true); 0227 0228 QStringList tidyArgs = { QStringLiteral("-errors"), 0229 QStringLiteral("-quiet"), 0230 QStringLiteral("--show-warnings"), 0231 QStringLiteral("no"), 0232 QStringLiteral("--strict-tags-attributes"), 0233 QStringLiteral("yes") }; 0234 QProcessEnvironment tidyEnv; 0235 // suppress warning about no tidyrc file 0236 tidyEnv.insert("HTML_TIDY", "/dev/null"); 0237 0238 QUrl url = QUrl::fromLocalFile(tellicoFile); 0239 Tellico::Import::TellicoImporter importer(url); 0240 Tellico::Data::CollPtr coll = importer.collection(); 0241 QVERIFY(coll); 0242 0243 Tellico::Export::HTMLExporter exporter(coll); 0244 exporter.setParseDOM(false); // shows error for <wbr> tags and is not necessary for check 0245 exporter.setEntries(coll->entries()); 0246 exporter.setXSLTFile(xsltFile); 0247 exporter.setPrintGrouped(true); 0248 0249 const QString output = exporter.text(); 0250 QVERIFY(!output.contains(QStringLiteral("<p><p>"))); 0251 QProcess tidyProc; 0252 tidyProc.setProcessEnvironment(tidyEnv); 0253 tidyProc.setProcessChannelMode(QProcess::SeparateChannels); 0254 tidyProc.setReadChannel(QProcess::StandardError); 0255 tidyProc.start(tidy, tidyArgs); 0256 QVERIFY(tidyProc.waitForStarted()); 0257 0258 tidyProc.write(output.toUtf8() + '\n'); 0259 QVERIFY(tidyProc.waitForBytesWritten()); 0260 tidyProc.closeWriteChannel(); 0261 QVERIFY(tidyProc.waitForFinished()); 0262 0263 QTextStream ts(&tidyProc); 0264 QString errorOutput = ts.readLine(); 0265 while(!errorOutput.isEmpty()) { 0266 qDebug() << errorOutput; 0267 errorOutput = ts.readLine(); 0268 } 0269 0270 tidyProc.close(); 0271 QCOMPARE(tidyProc.exitStatus(), QProcess::NormalExit); 0272 // tidy exit codes are 0 for none, 1 for warnings only, 2 for errors 0273 QVERIFY(tidyProc.exitCode() < 2); 0274 } 0275 0276 void HtmlExporterTest::testTemplates_data() { 0277 QTest::addColumn<QString>("xsltFile"); 0278 QTest::addColumn<QString>("tellicoFile"); 0279 0280 QString ted = QFINDTESTDATA(QStringLiteral("data/ted_lasso.xml")); 0281 QString moody = QFINDTESTDATA(QStringLiteral("data/moody_blue.xml")); 0282 0283 QDir entryDir(QFINDTESTDATA(QStringLiteral("../../xslt/entry-templates/Default.xsl"))); 0284 entryDir.cdUp(); 0285 foreach(const QString& file, entryDir.entryList({"*.xsl"}, QDir::Files)) { 0286 QTest::newRow(file.toUtf8().constData()) << file << ted; 0287 QTest::newRow(file.toUtf8().constData()) << file << moody; 0288 } 0289 QDir reportDir(QFINDTESTDATA(QStringLiteral("../../xslt/report-templates/Column_View.xsl"))); 0290 reportDir.cdUp(); 0291 foreach(const QString& file, reportDir.entryList({"*.xsl"}, QDir::Files)) { 0292 QTest::newRow(file.toUtf8().constData()) << file << ted; 0293 QTest::newRow(file.toUtf8().constData()) << file << moody; 0294 } 0295 }