File indexing completed on 2024-05-26 04:59:41

0001 /*
0002     SPDX-FileCopyrightText: 2020-2022 Mladen Milinkovic <max@smoothware.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "richdocumenttest.h"
0008 
0009 #include "helpers/common.h"
0010 
0011 #include <QDebug>
0012 #include <QRegularExpression>
0013 #include <QTest>
0014 #include <QTextDocumentFragment>
0015 
0016 using namespace SubtitleComposer;
0017 
0018 enum Format {
0019     Plain = 1,
0020     Html = 2,
0021     Both = Plain | Html
0022 };
0023 Q_DECLARE_METATYPE(Format)
0024 
0025 void
0026 RichDocumentTest::testCursor()
0027 {
0028     const QString backslashes = $("oXXo");
0029     doc.setHtml(backslashes);
0030     QTextCursor c(&doc);
0031     QEXPECT_FAIL("", "Already at doc Start", Continue);
0032     QVERIFY(c.movePosition(QTextCursor::Start));
0033     QVERIFY(c.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1));
0034     QCOMPARE(c.selectedText(), $("o"));
0035     QEXPECT_FAIL("", "Dunno why... some internal anchor == position?", Continue);
0036     QVERIFY(c.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2));
0037     c.clearSelection();
0038     QVERIFY(c.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2));
0039     QVERIFY(c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor));
0040     QCOMPARE(c.selectedText(), $("o"));
0041 }
0042 
0043 void
0044 RichDocumentTest::testHtml_data()
0045 {
0046     QTest::addColumn<QString>("html");
0047     QTest::addColumn<QString>("htmlOut");
0048     QTest::addColumn<QString>("textOut");
0049 
0050     QTest::newRow("bold styles")
0051             << "<p>It has <b>bold</b> and <strong>strong</strong> styles.</p>"
0052             << "It has <b>bold</b> and <b>strong</b> styles."
0053             << "It has bold and strong styles.";
0054     QTest::newRow("italic styles")
0055             << "<div>It has <i>italic</i> and <em>em</em> styles.</div>"
0056             << "It has <i>italic</i> and <i>em</i> styles."
0057             << "It has italic and em styles.";
0058     QTest::newRow("underline/strikethrough styles")
0059             << "<span>It has <u>underline</u> and <s>strike</s> styles.</span>"
0060             << "It has <u>underline</u> and <s>strike</s> styles."
0061             << "It has underline and strike styles.";
0062     QTest::newRow("color styles")
0063             << "<p>Try <font color=\"red\">red</font> and <font color=\"black\">black</font> and <span style=\"color:blue\">blue</span> color.</p>"
0064             << "Try <font color=#ff0000>red</font> and <font color=#000000>black</font> and <font color=#0000ff>blue</font> color."
0065             << "Try red and black and blue color.";
0066     QTest::newRow("nested color styles")
0067             << "<p><span style=\"color:blue\">Try <font color=\"red\">red</font> and <font color=\"black\">black</font> and blue</span> color.</p>"
0068             << "<font color=#0000ff>Try </font><font color=#ff0000>red</font><font color=#0000ff> and </font><font color=#000000>black</font><font color=#0000ff> and blue</font> color."
0069             << "Try red and black and blue color.";
0070     QTest::newRow("unicode literal")
0071             << "An unicode ♪ char."
0072             << "An unicode \u266A char."
0073             << "An unicode \u266A char.";
0074     QTest::newRow("misc tags, breaks etc")
0075             << "<p>A non&nbsp;breakable space. "
0076                "A newline.\n"
0077                "A line break.<br>"
0078                "And a</p><p>different paragraph</p>"
0079                "and some <p>unclosed and bad</div> <b><i><u><s>tags."
0080             << "A non\u00A0breakable space. "
0081                "A newline.<br>\n"
0082                "A line break.<br>\n"
0083                "And a<br>\ndifferent paragraph<br>\n"
0084                "and some <br>\nunclosed and bad <b><i><u><s>tags.</b></i></u></s>"
0085             << "A non breakable space. "
0086                "A newline.\n"
0087                "A line break.\n"
0088                "And a\ndifferent paragraph\n"
0089                "and some \nunclosed and bad tags.";
0090     QTest::newRow("paragraph break")
0091             << "<p>paragraph text</p>new line"
0092             << "paragraph text<br>\nnew line"
0093             << "paragraph text\nnew line";
0094 }
0095 
0096 void
0097 RichDocumentTest::testHtml()
0098 {
0099     QFETCH(QString, html);
0100     QFETCH(QString, htmlOut);
0101     QFETCH(QString, textOut);
0102 
0103     doc.setHtml(html);
0104     QCOMPARE(doc.toHtml(), htmlOut);
0105     QCOMPARE(doc.toPlainText(), textOut);
0106 
0107     doc.setHtml(htmlOut);
0108     QCOMPARE(doc.toHtml(), htmlOut);
0109     QCOMPARE(doc.toPlainText(), textOut);
0110 }
0111 
0112 void
0113 RichDocumentTest::testRegExpReplace_data()
0114 {
0115     QTest::addColumn<Format>("inType");
0116     QTest::addColumn<QString>("input");
0117     QTest::addColumn<QRegularExpression>("re");
0118     QTest::addColumn<Format>("repType");
0119     QTest::addColumn<QString>("replacement");
0120     QTest::addColumn<QString>("expected");
0121 
0122     QTest::newRow("t1")
0123             << Plain << $("xx12xx345xx6xx7xx")
0124             << RE$("x+")
0125             << Plain << QString()
0126             << QString();
0127     QTest::newRow("t2")
0128             << Plain << $("xx12xx345xx6xx7xx")
0129             << RE$("x+")
0130             << Plain << $("y")
0131             << QString();
0132     QTest::newRow("t3")
0133             << Plain << $("xx12xx345xx6xx7xx")
0134             << RE$("((6x)|x+)")
0135             << Plain << $("\\2")
0136             << QString();
0137     QTest::newRow("t4")
0138             << Plain << $("xx12xx345xx6xx7xx")
0139             << RE$("((6x)|x+)")
0140             << Plain << $("o\\2o")
0141             << QString();
0142     QTest::newRow("t5")
0143             << Plain << $("xx12xx345xx6xx7xx")
0144             << RE$("((\\d)x+)+")
0145             << Plain << $("o\\2o")
0146             << QString();
0147     QTest::newRow("swaps")
0148             << Plain << $("aa12bb345cc6xx7yy")
0149             << RE$("([a-z]+)\\d+([a-z]+)")
0150             << Plain << $("\\2 swapped \\1")
0151             << QString();
0152     // these are failing cause replacer is not very good with replacing tags yet
0153 //  QTest::newRow("styles1")
0154 //          << Html << $("am<b>az</b>ing su<i>per</i> <u>stuff</u>")
0155 //          << RE$("\\b(\\w+)\\b")
0156 //          << Plain << $("X\\1X")
0157 //          << $("Xam<b>az</b>ingX Xsu<i>perX</i> <u>XstuffX</u>");
0158 //  QTest::newRow("styles2")
0159 //          << Html << $("am<b>az</b>ing su<i>per</i> <u>stuff</u>")
0160 //          << RE$("\\b\\w+\\b")
0161 //          << Plain << $("word")
0162 //          << $("word word <u>word</u>");
0163 }
0164 
0165 void
0166 RichDocumentTest::testRegExpReplace()
0167 {
0168     QFETCH(Format, inType);
0169     QFETCH(QString, input);
0170     QFETCH(QRegularExpression, re);
0171     QFETCH(Format, repType);
0172     QFETCH(QString, replacement);
0173     QFETCH(QString, expected);
0174 
0175     if(inType == Plain)
0176         doc.setPlainText(input, true);
0177     else
0178         doc.setHtml(input, true);
0179 
0180     if(expected.isEmpty())
0181         expected = QString(input).replace(re, replacement);
0182 
0183     if(inType == Plain && repType == Plain) {
0184         doc.replace(re, replacement, false);
0185         QCOMPARE(doc.toPlainText(), expected);
0186     }
0187 
0188     doc.undo();
0189     doc.replace(re, replacement, true);
0190     QString docOut = inType == Plain && repType == Plain ? doc.toPlainText() : doc.toHtml();
0191     QCOMPARE(docOut, expected);
0192 }
0193 
0194 void
0195 RichDocumentTest::testIndexReplace_data()
0196 {
0197     QTest::addColumn<Format>("inType");
0198     QTest::addColumn<QString>("input");
0199     QTest::addColumn<int>("index");
0200     QTest::addColumn<int>("length");
0201     QTest::addColumn<Format>("repType");
0202     QTest::addColumn<QString>("replacement");
0203     QTest::addColumn<QString>("expected");
0204 
0205     QTest::newRow("start")
0206             << Plain << $("xx12xx345xx6xx7xx")
0207             << 0 << 4
0208             << Plain << $("YYY")
0209             << $("YYYxx345xx6xx7xx");
0210     QTest::newRow("middle")
0211             << Plain << $("xx12xx345xx6xx7xx")
0212             << 6 << 3
0213             << Plain << $("YYY")
0214             << $("xx12xxYYYxx6xx7xx");
0215     QTest::newRow("end")
0216             << Plain << $("xx12xx345xx6xx7xx")
0217             << 12 << 5
0218             << Plain << $("YYY")
0219             << $("xx12xx345xx6YYY");
0220 }
0221 
0222 void
0223 RichDocumentTest::testIndexReplace()
0224 {
0225     QFETCH(Format, inType);
0226     QFETCH(QString, input);
0227     QFETCH(int, index);
0228     QFETCH(int, length);
0229     QFETCH(Format, repType);
0230     QFETCH(QString, replacement);
0231     QFETCH(QString, expected);
0232 
0233     if(inType == Plain)
0234         doc.setPlainText(input, true);
0235     else
0236         doc.setHtml(input, true);
0237 
0238     if(expected.isEmpty())
0239         expected = QString(input).replace(index, length, replacement);
0240 
0241     if(inType == Plain && repType == Plain) {
0242         doc.replace(index, length, replacement);
0243         QCOMPARE(doc.toPlainText(), expected);
0244     }
0245 
0246     doc.undo();
0247     doc.replace(index, length, replacement);
0248     QString docOut = inType == Plain && repType == Plain ? doc.toPlainText() : doc.toHtml();
0249     QCOMPARE(docOut, expected);
0250 }
0251 
0252 void
0253 RichDocumentTest::testCleanupSpaces_data()
0254 {
0255     QTest::addColumn<Format>("inType");
0256     QTest::addColumn<QString>("input");
0257     QTest::addColumn<QString>("expected");
0258 
0259     QTest::newRow("t1") << Html
0260         << $("♪ It  <b>\t  \t  seems </b><i>\t  today<br>that</i> all <i>     \t you</i> see ♪")
0261         << $("\u266A It seems today\nthat all you see \u266A");
0262     QTest::newRow("t2") << Plain
0263         << $("\n\n \t This  \t  is\tsome \t \n \t \n\t \t\n\n \t good subtitle\t\n\ttext. \t")
0264         << $("This is some\ngood subtitle\ntext.");
0265     QTest::newRow("t3") << Plain
0266         << $(" \t \nline text\n \t ")
0267         << $("line text");
0268     QTest::newRow("t4") << Html
0269         << $(" \t &nbsp; <br> &nbsp; <p>line text</p><p>\n \t </p><div><br>&nbsp;<br></div>")
0270         << $("line text");
0271 }
0272 
0273 void
0274 RichDocumentTest::testCleanupSpaces()
0275 {
0276     QFETCH(Format, inType);
0277     QFETCH(QString, input);
0278     QFETCH(QString, expected);
0279 
0280     if(inType == Plain)
0281         doc.setPlainText(input);
0282     else
0283         doc.setHtml(input);
0284     doc.cleanupSpaces();
0285     QCOMPARE(doc.toPlainText(), expected);
0286 }
0287 
0288 void
0289 RichDocumentTest::testUpperLower()
0290 {
0291     doc.setPlainText($("some čćžšđ òàùèì lowercase \u266A♪\\!! text"));
0292     doc.toUpper();
0293     QCOMPARE(doc.toPlainText(), $("SOME ČĆŽŠĐ ÒÀÙÈÌ LOWERCASE \u266A♪\\!! TEXT"));
0294     doc.toLower();
0295     QCOMPARE(doc.toPlainText(), $("some čćžšđ òàùèì lowercase \u266A♪\\!! text"));
0296 }
0297 
0298 void
0299 RichDocumentTest::testSentence_data()
0300 {
0301     QTest::addColumn<bool>("sentenceStart");
0302     QTest::addColumn<QString>("input");
0303     QTest::addColumn<QString>("expected");
0304 
0305     QTest::newRow("t1") << true
0306         << $("begINNING of ♪ some \t \u266A SENTENCE,")
0307         << $("Beginning of ♪ some \t \u266A sentence,");
0308     QTest::newRow("t2") << false
0309         << $("Which CONTINUES? to finish¿\nthe SENTENCE")
0310         << $("which continues? To finish¿\nThe sentence");
0311     QTest::newRow("t3") << false
0312         << $("BREAKS: LINE. AND PUP'S ENDS HERE!")
0313         << $("breaks: line. And pup's ends here!");
0314 }
0315 
0316 void
0317 RichDocumentTest::testSentence()
0318 {
0319     QFETCH(bool, sentenceStart);
0320     QFETCH(QString, input);
0321     QFETCH(QString, expected);
0322 
0323     doc.setPlainText(input);
0324     doc.toSentenceCase(&sentenceStart);
0325     QCOMPARE(doc.toPlainText(), expected);
0326 }
0327 
0328 void
0329 RichDocumentTest::testTitle_data()
0330 {
0331     QTest::addColumn<bool>("sentenceStart");
0332     QTest::addColumn<QString>("input");
0333     QTest::addColumn<QString>("expected");
0334 
0335     QTest::newRow("t1") << true
0336         << $("begINNING of ♪ s-o-m-e \t \u266A SENTENCE,")
0337         << $("Beginning Of ♪ S-o-m-e \t \u266A Sentence,");
0338     QTest::newRow("t2") << false
0339         << $("Whi_ch CONT:INUES? to finish¿\nthe SENTENCE")
0340         << $("Whi_ch Cont:Inues? To Finish¿\nThe Sentence");
0341     QTest::newRow("t3") << false
0342         << $("BRE+AKS: LINE. AND PUP'S ENDS HERE!")
0343         << $("Bre+aks: Line. And Pup's Ends Here!");
0344 }
0345 
0346 void
0347 RichDocumentTest::testTitle()
0348 {
0349     QFETCH(bool, sentenceStart);
0350     QFETCH(QString, input);
0351     QFETCH(QString, expected);
0352 
0353     doc.setPlainText(input);
0354     doc.toSentenceCase(&sentenceStart, true, true);
0355     QCOMPARE(doc.toPlainText(), expected);
0356 }
0357 
0358 void
0359 RichDocumentTest::testClass()
0360 {
0361     QTextCursor *c = doc.undoableCursor();
0362     doc.setPlainText($("The quick brown fox jumps over the lazy dog"));
0363     QVERIFY(c->movePosition(QTextCursor::Start));
0364 
0365     {
0366         QVERIFY(c->movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 4));
0367         QVERIFY(c->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 11));
0368         QCOMPARE(c->selectedText(), $("quick brown"));
0369         QTextCharFormat fmt;
0370         fmt.setFontWeight(QFont::Bold);
0371         c->mergeCharFormat(fmt);
0372         QCOMPARE(c->selectedText(), $("quick brown"));
0373         c->clearSelection();
0374     }
0375     {
0376         QVERIFY(c->movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 5));
0377         QVERIFY(c->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 9));
0378         QCOMPARE(c->selectedText(), $("brown fox"));
0379         QTextCharFormat fmt;
0380         QSet<QString> classList;
0381         classList.insert($("test-class"));
0382         fmt.setProperty(RichDocument::Class, QVariant::fromValue(classList));
0383         c->mergeCharFormat(fmt);
0384         QCOMPARE(c->selectedText(), $("brown fox"));
0385         c->clearSelection();
0386     }
0387     qDebug() << doc.toHtml();
0388 }
0389 
0390 QTEST_MAIN(RichDocumentTest)