1 /* 2 This file is part of the Grantlee template system. 3 4 Copyright (c) 2008 Stephen Kelly <steveire@gmail.com> 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either version 9 2.1 of the Licence, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 19 */ 20 21 #include <QtCore/QRegularExpression> 22 #include <QtCore> 23 #include <QtGui/QTextCursor> 24 #include <QtGui/QTextDocument> 25 #include <QtTest/QtTest> 26 #include <QtTest/qtestevent.h> 27 28 #include "coverageobject.h" 29 #include "markupdirector.h" 30 #include "texthtmlbuilder.h" 31 32 using namespace Grantlee; 33 34 class TestHtmlOutput : public CoverageObject 35 { 36 Q_OBJECT 37 private Q_SLOTS: 38 39 // Test paragraph contents: 40 void testSingleFormat(); 41 void testDoubleFormat(); 42 void testDoubleStartDifferentFinish(); 43 void testDoubleStartDifferentFinishReverseOrder(); 44 void testDifferentStartDoubleFinish(); 45 void testDifferentStartDoubleFinishReverseOrder(); 46 void testOverlap(); 47 void testAnchor(); 48 void testAnchorWithFormattedContent(); 49 void testAdjacentAnchors(); 50 void testNestedFormatting(); 51 void testSpan(); 52 void testDoubleSpan(); 53 void testSpanNesting(); 54 void testEdgeCaseLeft(); 55 void testEdgeCaseRight(); 56 void testImage(); 57 void testImageResized(); 58 void testEachFormatTagSingly(); 59 void testHorizontalRule(); 60 void testNewlines(); 61 void testNewlinesThroughQTextCursor(); 62 }; 63 testSingleFormat()64void TestHtmlOutput::testSingleFormat() 65 { 66 auto doc = new QTextDocument(); 67 68 // One format 69 doc->setHtml(QStringLiteral("This <b>text</b> is bold.")); 70 71 auto hb = new TextHTMLBuilder(); 72 auto md = new MarkupDirector(hb); 73 md->processDocument(doc); 74 auto result = hb->getResult(); 75 QRegularExpression regex( 76 QStringLiteral("^<p>This <strong>text</strong> is bold.</p>\\n$")); 77 78 QVERIFY(regex.match(result).hasMatch()); 79 } 80 testDoubleFormat()81void TestHtmlOutput::testDoubleFormat() 82 { 83 auto doc = new QTextDocument(); 84 85 // One format 86 doc->setHtml(QStringLiteral("Some <b><i>formatted</i></b> text.")); 87 88 auto hb = new TextHTMLBuilder(); 89 auto md = new MarkupDirector(hb); 90 md->processDocument(doc); 91 auto result = hb->getResult(); 92 QRegularExpression regex( 93 QStringLiteral("^<p>Some " 94 "(<strong><em>|<em><strong>)formatted(</em></strong>|</" 95 "strong></em>) text.</p>\\n$")); 96 97 QVERIFY(regex.match(result).hasMatch()); 98 } 99 testAnchor()100void TestHtmlOutput::testAnchor() 101 { 102 auto doc = new QTextDocument(); 103 doc->setHtml( 104 QStringLiteral("A <a href=\"http://www.kde.org\">link</a> to KDE.")); 105 106 auto hb = new TextHTMLBuilder(); 107 auto md = new MarkupDirector(hb); 108 md->processDocument(doc); 109 auto result = hb->getResult(); 110 111 QRegularExpression regex(QStringLiteral( 112 "^<p>A <a href=\"http://www.kde.org\">link</a> to KDE.</p>\\n$")); 113 114 QVERIFY(regex.match(result).hasMatch()); 115 } 116 testAnchorWithFormattedContent()117void TestHtmlOutput::testAnchorWithFormattedContent() 118 { 119 auto doc = new QTextDocument(); 120 doc->setHtml(QStringLiteral( 121 "A <a href=\"http://www.kde.org\"><b>formatted</b> link</a> to KDE.")); 122 123 auto hb = new TextHTMLBuilder(); 124 auto md = new MarkupDirector(hb); 125 md->processDocument(doc); 126 auto result = hb->getResult(); 127 128 QRegularExpression regex(QStringLiteral( 129 "^<p>A <a href=\"http://www.kde.org\"><strong>formatted</strong> " 130 "link</a> to KDE.</p>\\n$")); 131 132 QVERIFY(regex.match(result).hasMatch()); 133 } 134 testAdjacentAnchors()135void TestHtmlOutput::testAdjacentAnchors() 136 { 137 auto doc = new QTextDocument(); 138 doc->setHtml( 139 QStringLiteral("Two <a href=\"http://www.kde.org\">links</a><a " 140 "href=\"http://www.google.com\">next</a> to eachother.")); 141 142 auto hb = new TextHTMLBuilder(); 143 auto md = new MarkupDirector(hb); 144 md->processDocument(doc); 145 auto result = hb->getResult(); 146 147 QRegularExpression regex(QStringLiteral( 148 "^<p>Two <a href=\"http://www.kde.org\">links</a><a " 149 "href=\"http://www.google.com\">next</a> to eachother.</p>\\n$")); 150 151 QVERIFY(regex.match(result).hasMatch()); 152 } 153 testNestedFormatting()154void TestHtmlOutput::testNestedFormatting() 155 { 156 auto doc = new QTextDocument(); 157 doc->setHtml(QStringLiteral("This <b>text is <i>italic</i> and</b> bold.")); 158 159 auto hb = new TextHTMLBuilder(); 160 auto md = new MarkupDirector(hb); 161 md->processDocument(doc); 162 auto result = hb->getResult(); 163 164 QRegularExpression regex(QStringLiteral( 165 "^<p>This <strong>text is <em>italic</em> and</strong> bold.</p>\\n$")); 166 167 QVERIFY(regex.match(result).hasMatch()); 168 } 169 testSpan()170void TestHtmlOutput::testSpan() 171 { 172 auto doc = new QTextDocument(); 173 doc->setHtml(QStringLiteral( 174 "Some <span style=\"color:#ff0000;\">formatted</span> text.")); 175 176 auto hb = new TextHTMLBuilder(); 177 auto md = new MarkupDirector(hb); 178 md->processDocument(doc); 179 auto result = hb->getResult(); 180 181 auto regex = QRegularExpression( 182 QStringLiteral("^<p>Some <span style=\"color:#ff0000;\">formatted</span> " 183 "text.</p>\\n$")); 184 185 QVERIFY(regex.match(result).hasMatch()); 186 } 187 testDoubleSpan()188void TestHtmlOutput::testDoubleSpan() 189 { 190 auto doc = new QTextDocument(); 191 doc->setHtml(QStringLiteral("Some <span " 192 "style=\"color:#ff0000;background-color:#00ff00;" 193 "\">formatted</span> text.")); 194 195 auto hb = new TextHTMLBuilder(); 196 auto md = new MarkupDirector(hb); 197 md->processDocument(doc); 198 auto result = hb->getResult(); 199 200 auto regex = QRegularExpression(QStringLiteral( 201 "^<p>Some <span " 202 "style=\"(color:#ff0000|background-color:#00ff00);\"><span " 203 "style=\"(color:#ff0000|background-color:#00ff00);\">formatted</span></" 204 "span> text.</p>\\n$")); 205 206 QVERIFY(regex.match(result).hasMatch()); 207 } 208 testSpanNesting()209void TestHtmlOutput::testSpanNesting() 210 { 211 auto doc = new QTextDocument(); 212 doc->setHtml(QStringLiteral( 213 "Paragraph <span style=\"background-color:#00ff00;\">with some <span " 214 "style=\"color:#ff0000;\">formatted</span> nested</span> text.")); 215 216 auto hb = new TextHTMLBuilder(); 217 auto md = new MarkupDirector(hb); 218 md->processDocument(doc); 219 auto result = hb->getResult(); 220 221 auto regex = QRegularExpression(QStringLiteral( 222 "^<p>Paragraph <span style=\"background-color:#00ff00;\">with some <span " 223 "style=\"color:#ff0000;\">formatted</span> nested</span> text.</p>\\n$")); 224 225 QVERIFY(regex.match(result).hasMatch()); 226 } 227 testDoubleStartDifferentFinish()228void TestHtmlOutput::testDoubleStartDifferentFinish() 229 { 230 auto doc = new QTextDocument(); 231 doc->setHtml( 232 QStringLiteral("Paragraph <i><b>with</b> some formatted</i> text.")); 233 234 auto hb = new TextHTMLBuilder(); 235 auto md = new MarkupDirector(hb); 236 md->processDocument(doc); 237 auto result = hb->getResult(); 238 239 auto regex = QRegularExpression( 240 QStringLiteral("^<p>Paragraph <em><strong>with</strong> some " 241 "formatted</em> text.</p>\\n$")); 242 243 QVERIFY(regex.match(result).hasMatch()); 244 } 245 testDoubleStartDifferentFinishReverseOrder()246void TestHtmlOutput::testDoubleStartDifferentFinishReverseOrder() 247 { 248 auto doc = new QTextDocument(); 249 doc->setHtml( 250 QStringLiteral("Paragraph <b><i>with</i> some formatted</b> text.")); 251 252 auto hb = new TextHTMLBuilder(); 253 auto md = new MarkupDirector(hb); 254 md->processDocument(doc); 255 auto result = hb->getResult(); 256 257 auto regex = QRegularExpression( 258 QStringLiteral("^<p>Paragraph <strong><em>with</em> some " 259 "formatted</strong> text.</p>\\n$")); 260 261 QVERIFY(regex.match(result).hasMatch()); 262 } 263 testDifferentStartDoubleFinish()264void TestHtmlOutput::testDifferentStartDoubleFinish() 265 { 266 auto doc = new QTextDocument(); 267 doc->setHtml( 268 QStringLiteral("Paragraph <i>with some <b>formatted<b></i> text.")); 269 270 auto hb = new TextHTMLBuilder(); 271 auto md = new MarkupDirector(hb); 272 md->processDocument(doc); 273 auto result = hb->getResult(); 274 275 auto regex = QRegularExpression( 276 QStringLiteral("^<p>Paragraph <em>with some " 277 "<strong>formatted</strong></em> text.</p>\\n$")); 278 279 QVERIFY(regex.match(result).hasMatch()); 280 } 281 testDifferentStartDoubleFinishReverseOrder()282void TestHtmlOutput::testDifferentStartDoubleFinishReverseOrder() 283 { 284 auto doc = new QTextDocument(); 285 doc->setHtml( 286 QStringLiteral("Paragraph <b>with some <i>formatted</i></b> text.")); 287 288 auto hb = new TextHTMLBuilder(); 289 auto md = new MarkupDirector(hb); 290 md->processDocument(doc); 291 auto result = hb->getResult(); 292 293 auto regex = QRegularExpression( 294 QStringLiteral("^<p>Paragraph <strong>with some " 295 "<em>formatted</em></strong> text.</p>\\n$")); 296 297 QVERIFY(regex.match(result).hasMatch()); 298 } 299 testOverlap()300void TestHtmlOutput::testOverlap() 301 { 302 auto doc = new QTextDocument(); 303 doc->setHtml(QStringLiteral( 304 "Paragraph <b>with <i>some</i></b><i> formatted</i> text.")); 305 306 auto hb = new TextHTMLBuilder(); 307 auto md = new MarkupDirector(hb); 308 md->processDocument(doc); 309 auto result = hb->getResult(); 310 311 auto regex = QRegularExpression( 312 QStringLiteral("^<p>Paragraph <strong>with <em>some</em></strong><em> " 313 "formatted</em> text.</p>\\n$")); 314 315 QVERIFY(regex.match(result).hasMatch()); 316 } 317 testEdgeCaseLeft()318void TestHtmlOutput::testEdgeCaseLeft() 319 { 320 auto doc = new QTextDocument(); 321 doc->setHtml(QStringLiteral("Paragraph <b>with some formatted text.</b>")); 322 323 auto hb = new TextHTMLBuilder(); 324 auto md = new MarkupDirector(hb); 325 md->processDocument(doc); 326 auto result = hb->getResult(); 327 328 auto regex = QRegularExpression(QStringLiteral( 329 "^<p>Paragraph <strong>with some formatted text.</strong></p>\\n$")); 330 331 QVERIFY(regex.match(result).hasMatch()); 332 } 333 testEdgeCaseRight()334void TestHtmlOutput::testEdgeCaseRight() 335 { 336 auto doc = new QTextDocument(); 337 doc->setHtml(QStringLiteral("<b>Paragraph with some formatted</b> text.")); 338 339 auto hb = new TextHTMLBuilder(); 340 auto md = new MarkupDirector(hb); 341 md->processDocument(doc); 342 auto result = hb->getResult(); 343 344 auto regex = QRegularExpression(QStringLiteral( 345 "^<p><strong>Paragraph with some formatted</strong> text.</p>\\n$")); 346 347 QVERIFY(regex.match(result).hasMatch()); 348 } 349 testImage()350void TestHtmlOutput::testImage() 351 { 352 auto doc = new QTextDocument(); 353 doc->setHtml( 354 QStringLiteral("Paragraph with an inline <img " 355 "src=\"http://kde.org/img/kde41.png\" /> image.")); 356 357 auto hb = new TextHTMLBuilder(); 358 auto md = new MarkupDirector(hb); 359 md->processDocument(doc); 360 auto result = hb->getResult(); 361 362 auto regex = QRegularExpression( 363 QStringLiteral("^<p>Paragraph with an inline <img " 364 "src=\"http://kde.org/img/kde41.png\" /> image.</p>\\n$")); 365 366 QVERIFY(regex.match(result).hasMatch()); 367 } 368 testImageResized()369void TestHtmlOutput::testImageResized() 370 { 371 QString result; 372 QRegularExpression regex; 373 TextHTMLBuilder *hb; 374 MarkupDirector *md; 375 auto doc = new QTextDocument(); 376 377 // width 378 doc->setHtml(QStringLiteral( 379 "Paragraph with an inline <img src=\"http://kde.org/img/kde41.png\" " 380 "width=\"10\" /> image.")); 381 382 hb = new TextHTMLBuilder(); 383 md = new MarkupDirector(hb); 384 md->processDocument(doc); 385 result = hb->getResult(); 386 387 regex = QRegularExpression(QStringLiteral( 388 "^<p>Paragraph with an inline <img src=\"http://kde.org/img/kde41.png\" " 389 "width=\"10\" /> image.</p>\\n$")); 390 QVERIFY(regex.match(result).hasMatch()); 391 392 // height 393 doc->setHtml(QStringLiteral( 394 "Paragraph with an inline <img src=\"http://kde.org/img/kde41.png\" " 395 "height=\"10\" /> image.")); 396 397 hb = new TextHTMLBuilder(); 398 md = new MarkupDirector(hb); 399 md->processDocument(doc); 400 result = hb->getResult(); 401 402 regex = QRegularExpression(QStringLiteral( 403 "^<p>Paragraph with an inline <img src=\"http://kde.org/img/kde41.png\" " 404 "height=\"10\" /> image.</p>\\n$")); 405 QVERIFY(regex.match(result).hasMatch()); 406 407 // height and width 408 doc->setHtml(QStringLiteral( 409 "Paragraph with an inline <img src=\"http://kde.org/img/kde41.png\" " 410 "height=\"10\" width=\"10\" /> image.")); 411 412 hb = new TextHTMLBuilder(); 413 md = new MarkupDirector(hb); 414 md->processDocument(doc); 415 result = hb->getResult(); 416 417 regex = QRegularExpression(QStringLiteral( 418 "^<p>Paragraph with an inline <img src=\"http://kde.org/img/kde41.png\" " 419 "width=\"10\" height=\"10\" /> image.</p>\\n$")); 420 421 QVERIFY(regex.match(result).hasMatch()); 422 } 423 testEachFormatTagSingly()424void TestHtmlOutput::testEachFormatTagSingly() 425 { 426 QString result; 427 QRegularExpression regex; 428 TextHTMLBuilder *hb; 429 MarkupDirector *md; 430 auto doc = new QTextDocument(); 431 432 // Test bold 433 doc->setHtml(QStringLiteral("Some <b>formatted</b> text.")); 434 hb = new TextHTMLBuilder(); 435 md = new MarkupDirector(hb); 436 md->processDocument(doc); 437 result = hb->getResult(); 438 439 regex = QRegularExpression( 440 QStringLiteral("^<p>Some <strong>formatted</strong> text.</p>\\n$")); 441 QVERIFY(regex.match(result).hasMatch()); 442 443 // Test Italic 444 doc->setHtml(QStringLiteral("Some <i>formatted</i> text.")); 445 hb = new TextHTMLBuilder(); 446 md = new MarkupDirector(hb); 447 md->processDocument(doc); 448 result = hb->getResult(); 449 450 regex = QRegularExpression( 451 QStringLiteral("^<p>Some <em>formatted</em> text.</p>\\n$")); 452 QVERIFY(regex.match(result).hasMatch()); 453 454 // Test Underline 455 doc->setHtml(QStringLiteral("Some <u>formatted</u> text.")); 456 hb = new TextHTMLBuilder(); 457 md = new MarkupDirector(hb); 458 md->processDocument(doc); 459 result = hb->getResult(); 460 461 regex = QRegularExpression( 462 QStringLiteral("^<p>Some <u>formatted</u> text.</p>\\n$")); 463 QVERIFY(regex.match(result).hasMatch()); 464 465 // Test Strikeout 466 doc->setHtml(QStringLiteral("Some <s>formatted</s> text.")); 467 hb = new TextHTMLBuilder(); 468 md = new MarkupDirector(hb); 469 md->processDocument(doc); 470 result = hb->getResult(); 471 472 regex = QRegularExpression( 473 QStringLiteral("^<p>Some <s>formatted</s> text.</p>\\n$")); 474 QVERIFY(regex.match(result).hasMatch()); 475 476 // Test Superscript 477 doc->setHtml(QStringLiteral("Some <sup>formatted</sup> text.")); 478 hb = new TextHTMLBuilder(); 479 md = new MarkupDirector(hb); 480 md->processDocument(doc); 481 result = hb->getResult(); 482 483 regex = QRegularExpression( 484 QStringLiteral("^<p>Some <sup>formatted</sup> text.</p>\\n$")); 485 QVERIFY(regex.match(result).hasMatch()); 486 487 // Test Subscript 488 doc->setHtml(QStringLiteral("Some <sub>formatted</sub> text.")); 489 hb = new TextHTMLBuilder(); 490 md = new MarkupDirector(hb); 491 md->processDocument(doc); 492 result = hb->getResult(); 493 494 regex = QRegularExpression( 495 QStringLiteral("^<p>Some <sub>formatted</sub> text.</p>\\n$")); 496 QVERIFY(regex.match(result).hasMatch()); 497 498 // Test Foreground 499 doc->setHtml(QStringLiteral( 500 "Some <span style=\"color:#ff0000;\">formatted</span> text.")); 501 hb = new TextHTMLBuilder(); 502 md = new MarkupDirector(hb); 503 md->processDocument(doc); 504 result = hb->getResult(); 505 506 regex = QRegularExpression( 507 QStringLiteral("^<p>Some <span style=\"color:#ff0000;\">formatted</span> " 508 "text.</p>\\n$")); 509 QVERIFY(regex.match(result).hasMatch()); 510 511 // Test Background 512 doc->setHtml(QStringLiteral( 513 "Some <span style=\"background-color:#ff0000;\">formatted</span> text.")); 514 hb = new TextHTMLBuilder(); 515 md = new MarkupDirector(hb); 516 md->processDocument(doc); 517 result = hb->getResult(); 518 519 regex = QRegularExpression(QStringLiteral( 520 "^<p>Some <span style=\"background-color:#ff0000;\">formatted</span> " 521 "text.</p>\\n$")); 522 QVERIFY(regex.match(result).hasMatch()); 523 524 // Test Font Family 525 doc->setHtml(QStringLiteral( 526 "Some <span style=\"font-family:courier;\">formatted</span> text.")); 527 hb = new TextHTMLBuilder(); 528 md = new MarkupDirector(hb); 529 md->processDocument(doc); 530 result = hb->getResult(); 531 532 regex = QRegularExpression(QStringLiteral( 533 "^<p>Some <span style=\"font-family:courier;\">formatted</span> " 534 "text.</p>\\n$")); 535 QVERIFY(regex.match(result).hasMatch()); 536 537 // Test Font Size 538 doc->setHtml(QStringLiteral( 539 "Some <span style=\"font-size:20pt;\">formatted</span> text.")); 540 hb = new TextHTMLBuilder(); 541 md = new MarkupDirector(hb); 542 md->processDocument(doc); 543 result = hb->getResult(); 544 545 regex = QRegularExpression(QStringLiteral( 546 "^<p>Some <span style=\"font-size:20pt;\">formatted</span> " 547 "text.</p>\\n$")); 548 QVERIFY(regex.match(result).hasMatch()); 549 } 550 testHorizontalRule()551void TestHtmlOutput::testHorizontalRule() 552 { 553 auto doc = new QTextDocument(); 554 doc->setHtml( 555 QStringLiteral("<p style=\"margin-top:0;margin-bottom:0;\">Foo</p><hr " 556 "/><p style=\"margin-top:0;margin-bottom:0;\">Bar</p>")); 557 558 auto hb = new TextHTMLBuilder(); 559 auto md = new MarkupDirector(hb); 560 md->processDocument(doc); 561 auto result = hb->getResult(); 562 563 auto regex = QRegularExpression( 564 QStringLiteral("^<p>Foo</p>\\n<hr />\\n<p>Bar</p>\\n$")); 565 566 QVERIFY(regex.match(result).hasMatch()); 567 } 568 testNewlines()569void TestHtmlOutput::testNewlines() 570 { 571 auto doc = new QTextDocument(); 572 doc->setHtml(QStringLiteral("<p>Foo<br /><br />\n<p>Bar</p>")); 573 574 auto hb = new TextHTMLBuilder(); 575 auto md = new MarkupDirector(hb); 576 md->processDocument(doc); 577 auto result = hb->getResult(); 578 579 auto regex = QRegularExpression( 580 QStringLiteral("^<p>Foo</p>\\n<p> <p> </p>\\n<p>Bar</p>\\n$")); 581 582 QVERIFY(regex.match(result).hasMatch()); 583 } 584 testNewlinesThroughQTextCursor()585void TestHtmlOutput::testNewlinesThroughQTextCursor() 586 { 587 auto doc = new QTextDocument(this); 588 QTextCursor cursor(doc); 589 cursor.movePosition(QTextCursor::Start); 590 cursor.insertText(QStringLiteral("Foo")); 591 cursor.insertText(QStringLiteral("\n")); 592 cursor.insertText(QStringLiteral("\n")); 593 cursor.insertText(QStringLiteral("\n")); 594 cursor.insertText(QStringLiteral("Bar")); 595 596 auto hb = new TextHTMLBuilder(); 597 auto md = new MarkupDirector(hb); 598 md->processDocument(doc); 599 auto result = hb->getResult(); 600 601 auto regex = QRegularExpression( 602 QStringLiteral("^<p>Foo</p>\\n<p> <p> <p>Bar</p>\\n$")); 603 604 QVERIFY(regex.match(result).hasMatch()); 605 } 606 607 QTEST_MAIN(TestHtmlOutput) 608 #include "htmlbuildertest.moc" 609