1 /*
2     SPDX-FileCopyrightText: 2020 Mladen Milinkovic <max@smoothware.net>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "richdocumenttest.h"
8 
9 #include "helpers/common.h"
10 
11 #include <QRegularExpression>
12 #include <QTest>
13 #include <QDebug>
14 
15 using namespace SubtitleComposer;
16 
17 enum Format {
18 	Plain = 1,
19 	Html = 2,
20 	Both = Plain | Html
21 };
Q_DECLARE_METATYPE(Format)22 Q_DECLARE_METATYPE(Format)
23 
24 void
25 RichDocumentTest::testCursor()
26 {
27 	const QString backslashes = $("oXXo");
28 	doc.setHtml(backslashes);
29 	QTextCursor c(&doc);
30 	QEXPECT_FAIL("", "Already at doc Start", Continue);
31 	QVERIFY(c.movePosition(QTextCursor::Start));
32 	QVERIFY(c.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1));
33 	QCOMPARE(c.selectedText(), $("o"));
34 	QEXPECT_FAIL("", "Dunno why... some internal anchor == position?", Continue);
35 	QVERIFY(c.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2));
36 	c.clearSelection();
37 	QVERIFY(c.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2));
38 	QVERIFY(c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor));
39 	QCOMPARE(c.selectedText(), $("o"));
40 }
41 
42 void
testHtml_data()43 RichDocumentTest::testHtml_data()
44 {
45 	QTest::addColumn<QString>("html");
46 	QTest::addColumn<QString>("htmlOut");
47 	QTest::addColumn<QString>("textOut");
48 
49 	QTest::newRow("bold styles")
50 			<< "<p>It has <b>bold</b> and <strong>strong</strong> styles.</p>"
51 			<< "It has <b>bold</b> and <b>strong</b> styles."
52 			<< "It has bold and strong styles.";
53 	QTest::newRow("italic styles")
54 			<< "<div>It has <i>italic</i> and <em>em</em> styles.</div>"
55 			<< "It has <i>italic</i> and <i>em</i> styles."
56 			<< "It has italic and em styles.";
57 	QTest::newRow("underline/strikethrough styles")
58 			<< "<span>It has <u>underline</u> and <s>strike</s> styles.</span>"
59 			<< "It has <u>underline</u> and <s>strike</s> styles."
60 			<< "It has underline and strike styles.";
61 	QTest::newRow("color styles")
62 			<< "<p>Try <font color=\"red\">red</font> and <font color=\"black\">black</font> and <span style=\"color:blue\">blue</span> color.</p>"
63 			<< "Try <font color=#ff0000>red</font> and <font color=#000000>black</font> and <font color=#0000ff>blue</font> color."
64 			<< "Try red and black and blue color.";
65 	QTest::newRow("unicode literal")
66 			<< "An unicode ♪ char."
67 			<< "An unicode \u266A char."
68 			<< "An unicode \u266A char.";
69 	QTest::newRow("misc tags, breaks etc")
70 			<< "<p>A non&nbsp;breakable space. "
71 			   "A newline.\n"
72 			   "A line break.<br>"
73 			   "And a</p><p>different paragraph</p>"
74 			   "and some <p>unclosed and bad</div> <b><i><u><s>tags."
75 			<< "A non\u00A0breakable space. "
76 			   "A newline.<br>\n"
77 			   "A line break.<br>\n"
78 			   "And a<br>\ndifferent paragraph<br>\n"
79 			   "and some <br>\nunclosed and bad <b><i><u><s>tags.</b></i></u></s>"
80 			<< "A non breakable space. "
81 			   "A newline.\n"
82 			   "A line break.\n"
83 			   "And a\ndifferent paragraph\n"
84 			   "and some \nunclosed and bad tags.";
85 }
86 
87 void
testHtml()88 RichDocumentTest::testHtml()
89 {
90 	QFETCH(QString, html);
91 	QFETCH(QString, htmlOut);
92 	QFETCH(QString, textOut);
93 
94 	doc.setHtml(html);
95 	QCOMPARE(doc.toHtml(), htmlOut);
96 	QCOMPARE(doc.toPlainText(), textOut);
97 
98 	doc.setHtml(htmlOut);
99 	QCOMPARE(doc.toHtml(), htmlOut);
100 	QCOMPARE(doc.toPlainText(), textOut);
101 }
102 
103 void
testRegExpReplace_data()104 RichDocumentTest::testRegExpReplace_data()
105 {
106 	QTest::addColumn<Format>("inType");
107 	QTest::addColumn<QString>("input");
108 	QTest::addColumn<QRegularExpression>("re");
109 	QTest::addColumn<Format>("repType");
110 	QTest::addColumn<QString>("replacement");
111 	QTest::addColumn<QString>("expected");
112 
113 	QTest::newRow("t1")
114 			<< Plain << $("xx12xx345xx6xx7xx")
115 			<< RE$("x+")
116 			<< Plain << QString()
117 			<< QString();
118 	QTest::newRow("t2")
119 			<< Plain << $("xx12xx345xx6xx7xx")
120 			<< RE$("x+")
121 			<< Plain << $("y")
122 			<< QString();
123 	QTest::newRow("t3")
124 			<< Plain << $("xx12xx345xx6xx7xx")
125 			<< RE$("((6x)|x+)")
126 			<< Plain << $("\\2")
127 			<< QString();
128 	QTest::newRow("t4")
129 			<< Plain << $("xx12xx345xx6xx7xx")
130 			<< RE$("((6x)|x+)")
131 			<< Plain << $("o\\2o")
132 			<< QString();
133 	QTest::newRow("t5")
134 			<< Plain << $("xx12xx345xx6xx7xx")
135 			<< RE$("((\\d)x+)+")
136 			<< Plain << $("o\\2o")
137 			<< QString();
138 	QTest::newRow("swaps")
139 			<< Plain << $("aa12bb345cc6xx7yy")
140 			<< RE$("([a-z]+)\\d+([a-z]+)")
141 			<< Plain << $("\\2 swapped \\1")
142 			<< QString();
143 	// these are failing cause replacer is not very good with replacing tags yet
144 //	QTest::newRow("styles1")
145 //			<< Html << $("am<b>az</b>ing su<i>per</i> <u>stuff</u>")
146 //			<< RE$("\\b(\\w+)\\b")
147 //			<< Plain << $("X\\1X")
148 //			<< $("Xam<b>az</b>ingX Xsu<i>perX</i> <u>XstuffX</u>");
149 //	QTest::newRow("styles2")
150 //			<< Html << $("am<b>az</b>ing su<i>per</i> <u>stuff</u>")
151 //			<< RE$("\\b\\w+\\b")
152 //			<< Plain << $("word")
153 //			<< $("word word <u>word</u>");
154 }
155 
156 void
testRegExpReplace()157 RichDocumentTest::testRegExpReplace()
158 {
159 	QFETCH(Format, inType);
160 	QFETCH(QString, input);
161 	QFETCH(QRegularExpression, re);
162 	QFETCH(Format, repType);
163 	QFETCH(QString, replacement);
164 	QFETCH(QString, expected);
165 
166 	if(inType == Plain)
167 		doc.setPlainText(input, true);
168 	else
169 		doc.setHtml(input, true);
170 
171 	if(expected.isEmpty())
172 		expected = QString(input).replace(re, replacement);
173 
174 	if(inType == Plain && repType == Plain) {
175 		doc.replace(re, replacement, false);
176 		QCOMPARE(doc.toPlainText(), expected);
177 	}
178 
179 	doc.undo();
180 	doc.replace(re, replacement, true);
181 	QString docOut = inType == Plain && repType == Plain ? doc.toPlainText() : doc.toHtml();
182 	QCOMPARE(docOut, expected);
183 }
184 
185 void
testIndexReplace_data()186 RichDocumentTest::testIndexReplace_data()
187 {
188 	QTest::addColumn<Format>("inType");
189 	QTest::addColumn<QString>("input");
190 	QTest::addColumn<int>("index");
191 	QTest::addColumn<int>("length");
192 	QTest::addColumn<Format>("repType");
193 	QTest::addColumn<QString>("replacement");
194 	QTest::addColumn<QString>("expected");
195 
196 	QTest::newRow("start")
197 			<< Plain << $("xx12xx345xx6xx7xx")
198 			<< 0 << 4
199 			<< Plain << $("YYY")
200 			<< $("YYYxx345xx6xx7xx");
201 	QTest::newRow("middle")
202 			<< Plain << $("xx12xx345xx6xx7xx")
203 			<< 6 << 3
204 			<< Plain << $("YYY")
205 			<< $("xx12xxYYYxx6xx7xx");
206 	QTest::newRow("end")
207 			<< Plain << $("xx12xx345xx6xx7xx")
208 			<< 12 << 5
209 			<< Plain << $("YYY")
210 			<< $("xx12xx345xx6YYY");
211 }
212 
213 void
testIndexReplace()214 RichDocumentTest::testIndexReplace()
215 {
216 	QFETCH(Format, inType);
217 	QFETCH(QString, input);
218 	QFETCH(int, index);
219 	QFETCH(int, length);
220 	QFETCH(Format, repType);
221 	QFETCH(QString, replacement);
222 	QFETCH(QString, expected);
223 
224 	if(inType == Plain)
225 		doc.setPlainText(input, true);
226 	else
227 		doc.setHtml(input, true);
228 
229 	if(expected.isEmpty())
230 		expected = QString(input).replace(index, length, replacement);
231 
232 	if(inType == Plain && repType == Plain) {
233 		doc.replace(index, length, replacement);
234 		QCOMPARE(doc.toPlainText(), expected);
235 	}
236 
237 	doc.undo();
238 	doc.replace(index, length, replacement);
239 	QString docOut = inType == Plain && repType == Plain ? doc.toPlainText() : doc.toHtml();
240 	QCOMPARE(docOut, expected);
241 }
242 
243 void
testCleanupSpaces_data()244 RichDocumentTest::testCleanupSpaces_data()
245 {
246 	QTest::addColumn<Format>("inType");
247 	QTest::addColumn<QString>("input");
248 	QTest::addColumn<QString>("expected");
249 
250 	QTest::newRow("t1") << Html
251 		<< $("♪ It  <b>\t  \t  seems </b><i>\t  today<br>that</i> all <i>  	\t you</i> see ♪")
252 		<< $("\u266A It seems today\nthat all you see \u266A");
253 	QTest::newRow("t2") << Plain
254 		<< $("\n\n \t This  \t  is\tsome \t \n \t \n\t \t\n\n \t good subtitle\t\n\ttext. \t")
255 		<< $("This is some\ngood subtitle\ntext.");
256 	QTest::newRow("t3") << Plain
257 		<< $(" \t \nline text\n \t ")
258 		<< $("line text");
259 	QTest::newRow("t4") << Html
260 		<< $(" \t &nbsp; <br> &nbsp; <p>line text</p><p>\n \t </p><div><br>&nbsp;<br></div>")
261 		<< $("line text");
262 }
263 
264 void
testCleanupSpaces()265 RichDocumentTest::testCleanupSpaces()
266 {
267 	QFETCH(Format, inType);
268 	QFETCH(QString, input);
269 	QFETCH(QString, expected);
270 
271 	if(inType == Plain)
272 		doc.setPlainText(input);
273 	else
274 		doc.setHtml(input);
275 	doc.cleanupSpaces();
276 	QCOMPARE(doc.toPlainText(), expected);
277 }
278 
279 void
testUpperLower()280 RichDocumentTest::testUpperLower()
281 {
282 	doc.setPlainText($("some čćžšđ òàùèì lowercase \u266A♪\\!! text"));
283 	doc.toUpper();
284 	QCOMPARE(doc.toPlainText(), $("SOME ČĆŽŠĐ ÒÀÙÈÌ LOWERCASE \u266A♪\\!! TEXT"));
285 	doc.toLower();
286 	QCOMPARE(doc.toPlainText(), $("some čćžšđ òàùèì lowercase \u266A♪\\!! text"));
287 }
288 
289 void
testSentence_data()290 RichDocumentTest::testSentence_data()
291 {
292 	QTest::addColumn<bool>("sentenceStart");
293 	QTest::addColumn<QString>("input");
294 	QTest::addColumn<QString>("expected");
295 
296 	QTest::newRow("t1") << true
297 		<< $("begINNING of ♪ some \t \u266A SENTENCE,")
298 		<< $("Beginning of ♪ some \t \u266A sentence,");
299 	QTest::newRow("t2") << false
300 		<< $("Which CONTINUES? to finish¿\nthe SENTENCE")
301 		<< $("which continues? To finish¿\nThe sentence");
302 	QTest::newRow("t3") << false
303 		<< $("BREAKS: LINE. AND PUP'S ENDS HERE!")
304 		<< $("breaks: line. And pup's ends here!");
305 }
306 
307 void
testSentence()308 RichDocumentTest::testSentence()
309 {
310 	QFETCH(bool, sentenceStart);
311 	QFETCH(QString, input);
312 	QFETCH(QString, expected);
313 
314 	doc.setPlainText(input);
315 	doc.toSentenceCase(&sentenceStart);
316 	QCOMPARE(doc.toPlainText(), expected);
317 }
318 
319 void
testTitle_data()320 RichDocumentTest::testTitle_data()
321 {
322 	QTest::addColumn<bool>("sentenceStart");
323 	QTest::addColumn<QString>("input");
324 	QTest::addColumn<QString>("expected");
325 
326 	QTest::newRow("t1") << true
327 		<< $("begINNING of ♪ s-o-m-e \t \u266A SENTENCE,")
328 		<< $("Beginning Of ♪ S-o-m-e \t \u266A Sentence,");
329 	QTest::newRow("t2") << false
330 		<< $("Whi_ch CONT:INUES? to finish¿\nthe SENTENCE")
331 		<< $("Whi_ch Cont:Inues? To Finish¿\nThe Sentence");
332 	QTest::newRow("t3") << false
333 		<< $("BRE+AKS: LINE. AND PUP'S ENDS HERE!")
334 		<< $("Bre+aks: Line. And Pup's Ends Here!");
335 }
336 
337 void
testTitle()338 RichDocumentTest::testTitle()
339 {
340 	QFETCH(bool, sentenceStart);
341 	QFETCH(QString, input);
342 	QFETCH(QString, expected);
343 
344 	doc.setPlainText(input);
345 	doc.toSentenceCase(&sentenceStart, true, true);
346 	QCOMPARE(doc.toPlainText(), expected);
347 }
348 
349 QTEST_GUILESS_MAIN(RichDocumentTest)
350