1 /* 2 Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18 */ 19 20 21 #include <QtTest/QtTest> 22 #include <qwebpage.h> 23 #include <qwidget.h> 24 #include <qwebview.h> 25 #include <qwebframe.h> 26 #include <qwebelement.h> 27 #include <util.h> 28 //TESTED_CLASS= 29 //TESTED_FILES= 30 31 class tst_QWebElement : public QObject 32 { 33 Q_OBJECT 34 35 public: 36 tst_QWebElement(); 37 virtual ~tst_QWebElement(); 38 39 public slots: 40 void init(); 41 void cleanup(); 42 43 private slots: 44 void textHtml(); 45 void simpleCollection(); 46 void attributes(); 47 void attributesNS(); 48 void listAttributes(); 49 void classes(); 50 void namespaceURI(); 51 void iteration(); 52 void nonConstIterator(); 53 void constIterator(); 54 void foreachManipulation(); 55 void emptyCollection(); 56 void appendCollection(); 57 void evaluateJavaScript(); 58 void documentElement(); 59 void frame(); 60 void style(); 61 void computedStyle(); 62 void appendAndPrepend(); 63 void insertBeforeAndAfter(); 64 void remove(); 65 void clear(); 66 void replaceWith(); 67 void encloseWith(); 68 void encloseContentsWith(); 69 void nullSelect(); 70 void firstChildNextSibling(); 71 void lastChildPreviousSibling(); 72 void hasSetFocus(); 73 void render(); 74 75 private: 76 QWebView* m_view; 77 QWebPage* m_page; 78 QWebFrame* m_mainFrame; 79 }; 80 81 tst_QWebElement::tst_QWebElement() 82 { 83 } 84 85 tst_QWebElement::~tst_QWebElement() 86 { 87 } 88 89 void tst_QWebElement::init() 90 { 91 m_view = new QWebView(); 92 m_page = m_view->page(); 93 m_mainFrame = m_page->mainFrame(); 94 } 95 96 void tst_QWebElement::cleanup() 97 { 98 delete m_view; 99 } 100 101 void tst_QWebElement::textHtml() 102 { 103 QString html = "<head></head><body><p>test</p></body>"; 104 m_mainFrame->setHtml(html); 105 QWebElement body = m_mainFrame->documentElement(); 106 QVERIFY(!body.isNull()); 107 108 QCOMPARE(body.toPlainText(), QString("test")); 109 QCOMPARE(body.toPlainText(), m_mainFrame->toPlainText()); 110 111 QCOMPARE(body.toInnerXml(), html); 112 } 113 114 void tst_QWebElement::simpleCollection() 115 { 116 QString html = "<body><p>first para</p><p>second para</p></body>"; 117 m_mainFrame->setHtml(html); 118 QWebElement body = m_mainFrame->documentElement(); 119 120 QWebElementCollection list = body.findAll("p"); 121 QCOMPARE(list.count(), 2); 122 QCOMPARE(list.at(0).toPlainText(), QString("first para")); 123 QCOMPARE(list.at(1).toPlainText(), QString("second para")); 124 } 125 126 void tst_QWebElement::attributes() 127 { 128 m_mainFrame->setHtml("<body><p>Test"); 129 QWebElement body = m_mainFrame->documentElement(); 130 131 QVERIFY(!body.hasAttribute("title")); 132 QVERIFY(!body.hasAttributes()); 133 134 body.setAttribute("title", "test title"); 135 136 QVERIFY(body.hasAttributes()); 137 QVERIFY(body.hasAttribute("title")); 138 139 QCOMPARE(body.attribute("title"), QString("test title")); 140 141 body.removeAttribute("title"); 142 143 QVERIFY(!body.hasAttribute("title")); 144 QVERIFY(!body.hasAttributes()); 145 146 QCOMPARE(body.attribute("does-not-exist", "testvalue"), QString("testvalue")); 147 } 148 149 void tst_QWebElement::attributesNS() 150 { 151 QString content = "<html xmlns=\"http://www.w3.org/1999/xhtml\" " 152 "xmlns:svg=\"http://www.w3.org/2000/svg\">" 153 "<body><svg:svg id=\"foobar\" width=\"400px\" height=\"300px\">" 154 "</svg:svg></body></html>"; 155 156 m_mainFrame->setContent(content.toUtf8(), "application/xhtml+xml"); 157 158 QWebElement svg = m_mainFrame->findFirstElement("svg"); 159 QVERIFY(!svg.isNull()); 160 161 QVERIFY(!svg.hasAttributeNS("http://www.w3.org/2000/svg", "foobar")); 162 QCOMPARE(svg.attributeNS("http://www.w3.org/2000/svg", "foobar", "defaultblah"), QString("defaultblah")); 163 svg.setAttributeNS("http://www.w3.org/2000/svg", "svg:foobar", "true"); 164 QVERIFY(svg.hasAttributeNS("http://www.w3.org/2000/svg", "foobar")); 165 QCOMPARE(svg.attributeNS("http://www.w3.org/2000/svg", "foobar", "defaultblah"), QString("true")); 166 } 167 168 void tst_QWebElement::listAttributes() 169 { 170 QString content = "<html xmlns=\"http://www.w3.org/1999/xhtml\" " 171 "xmlns:svg=\"http://www.w3.org/2000/svg\">" 172 "<body><svg:svg foo=\"\" svg:bar=\"\">" 173 "</svg:svg></body></html>"; 174 175 m_mainFrame->setContent(content.toUtf8(), "application/xhtml+xml"); 176 177 QWebElement svg = m_mainFrame->findFirstElement("svg"); 178 QVERIFY(!svg.isNull()); 179 180 QVERIFY(svg.attributeNames().contains("foo")); 181 QVERIFY(svg.attributeNames("http://www.w3.org/2000/svg").contains("bar")); 182 183 svg.setAttributeNS("http://www.w3.org/2000/svg", "svg:foobar", "true"); 184 QVERIFY(svg.attributeNames().contains("foo")); 185 QStringList attributes = svg.attributeNames("http://www.w3.org/2000/svg"); 186 QCOMPARE(attributes.size(), 2); 187 QVERIFY(attributes.contains("bar")); 188 QVERIFY(attributes.contains("foobar")); 189 } 190 191 void tst_QWebElement::classes() 192 { 193 m_mainFrame->setHtml("<body><p class=\"a b c d a c\">Test"); 194 195 QWebElement body = m_mainFrame->documentElement(); 196 QCOMPARE(body.classes().count(), 0); 197 198 QWebElement p = m_mainFrame->documentElement().findAll("p").at(0); 199 QStringList classes = p.classes(); 200 QCOMPARE(classes.count(), 4); 201 QCOMPARE(classes[0], QLatin1String("a")); 202 QCOMPARE(classes[1], QLatin1String("b")); 203 QCOMPARE(classes[2], QLatin1String("c")); 204 QCOMPARE(classes[3], QLatin1String("d")); 205 QVERIFY(p.hasClass("a")); 206 QVERIFY(p.hasClass("b")); 207 QVERIFY(p.hasClass("c")); 208 QVERIFY(p.hasClass("d")); 209 QVERIFY(!p.hasClass("e")); 210 211 p.addClass("f"); 212 QVERIFY(p.hasClass("f")); 213 p.addClass("a"); 214 QCOMPARE(p.classes().count(), 5); 215 QVERIFY(p.hasClass("a")); 216 QVERIFY(p.hasClass("b")); 217 QVERIFY(p.hasClass("c")); 218 QVERIFY(p.hasClass("d")); 219 220 p.toggleClass("a"); 221 QVERIFY(!p.hasClass("a")); 222 QVERIFY(p.hasClass("b")); 223 QVERIFY(p.hasClass("c")); 224 QVERIFY(p.hasClass("d")); 225 QVERIFY(p.hasClass("f")); 226 QCOMPARE(p.classes().count(), 4); 227 p.toggleClass("f"); 228 QVERIFY(!p.hasClass("f")); 229 QCOMPARE(p.classes().count(), 3); 230 p.toggleClass("a"); 231 p.toggleClass("f"); 232 QVERIFY(p.hasClass("a")); 233 QVERIFY(p.hasClass("f")); 234 QCOMPARE(p.classes().count(), 5); 235 236 p.removeClass("f"); 237 QVERIFY(!p.hasClass("f")); 238 QCOMPARE(p.classes().count(), 4); 239 p.removeClass("d"); 240 QVERIFY(!p.hasClass("d")); 241 QCOMPARE(p.classes().count(), 3); 242 p.removeClass("not-exist"); 243 QCOMPARE(p.classes().count(), 3); 244 p.removeClass("c"); 245 QVERIFY(!p.hasClass("c")); 246 QCOMPARE(p.classes().count(), 2); 247 p.removeClass("b"); 248 QVERIFY(!p.hasClass("b")); 249 QCOMPARE(p.classes().count(), 1); 250 p.removeClass("a"); 251 QVERIFY(!p.hasClass("a")); 252 QCOMPARE(p.classes().count(), 0); 253 p.removeClass("foobar"); 254 QCOMPARE(p.classes().count(), 0); 255 } 256 257 void tst_QWebElement::namespaceURI() 258 { 259 QString content = "<html xmlns=\"http://www.w3.org/1999/xhtml\" " 260 "xmlns:svg=\"http://www.w3.org/2000/svg\">" 261 "<body><svg:svg id=\"foobar\" width=\"400px\" height=\"300px\">" 262 "</svg:svg></body></html>"; 263 264 m_mainFrame->setContent(content.toUtf8(), "application/xhtml+xml"); 265 QWebElement body = m_mainFrame->documentElement(); 266 QCOMPARE(body.namespaceUri(), QLatin1String("http://www.w3.org/1999/xhtml")); 267 268 QWebElement svg = body.findAll("*#foobar").at(0); 269 QCOMPARE(svg.prefix(), QLatin1String("svg")); 270 QCOMPARE(svg.localName(), QLatin1String("svg")); 271 QCOMPARE(svg.tagName(), QLatin1String("svg:svg")); 272 QCOMPARE(svg.namespaceUri(), QLatin1String("http://www.w3.org/2000/svg")); 273 274 } 275 276 void tst_QWebElement::iteration() 277 { 278 QString html = "<body><p>first para</p><p>second para</p></body>"; 279 m_mainFrame->setHtml(html); 280 QWebElement body = m_mainFrame->documentElement(); 281 282 QWebElementCollection paras = body.findAll("p"); 283 QList<QWebElement> referenceList = paras.toList(); 284 285 QList<QWebElement> foreachList; 286 foreach(QWebElement p, paras) { 287 foreachList.append(p); 288 } 289 QVERIFY(foreachList.count() == 2); 290 QCOMPARE(foreachList.count(), referenceList.count()); 291 QCOMPARE(foreachList.at(0), referenceList.at(0)); 292 QCOMPARE(foreachList.at(1), referenceList.at(1)); 293 294 QList<QWebElement> forLoopList; 295 for (int i = 0; i < paras.count(); ++i) { 296 forLoopList.append(paras.at(i)); 297 } 298 QVERIFY(foreachList.count() == 2); 299 QCOMPARE(foreachList.count(), referenceList.count()); 300 QCOMPARE(foreachList.at(0), referenceList.at(0)); 301 QCOMPARE(foreachList.at(1), referenceList.at(1)); 302 303 for (int i = 0; i < paras.count(); ++i) { 304 QCOMPARE(paras.at(i), paras[i]); 305 } 306 307 QCOMPARE(paras.at(0), paras.first()); 308 QCOMPARE(paras.at(1), paras.last()); 309 } 310 311 void tst_QWebElement::nonConstIterator() 312 { 313 QString html = "<body><p>first para</p><p>second para</p></body>"; 314 m_mainFrame->setHtml(html); 315 QWebElement body = m_mainFrame->documentElement(); 316 QWebElementCollection paras = body.findAll("p"); 317 318 QWebElementCollection::iterator it = paras.begin(); 319 QCOMPARE(*it, paras.at(0)); 320 ++it; 321 (*it).encloseWith("<div>"); 322 QCOMPARE(*it, paras.at(1)); 323 ++it; 324 QCOMPARE(it, paras.end()); 325 } 326 327 void tst_QWebElement::constIterator() 328 { 329 QString html = "<body><p>first para</p><p>second para</p></body>"; 330 m_mainFrame->setHtml(html); 331 QWebElement body = m_mainFrame->documentElement(); 332 const QWebElementCollection paras = body.findAll("p"); 333 334 QWebElementCollection::const_iterator it = paras.begin(); 335 QCOMPARE(*it, paras.at(0)); 336 ++it; 337 QCOMPARE(*it, paras.at(1)); 338 ++it; 339 QCOMPARE(it, paras.end()); 340 } 341 342 void tst_QWebElement::foreachManipulation() 343 { 344 QString html = "<body><p>first para</p><p>second para</p></body>"; 345 m_mainFrame->setHtml(html); 346 QWebElement body = m_mainFrame->documentElement(); 347 348 foreach(QWebElement p, body.findAll("p")) { 349 p.setInnerXml("<div>foo</div><div>bar</div>"); 350 } 351 352 QCOMPARE(body.findAll("div").count(), 4); 353 } 354 355 void tst_QWebElement::emptyCollection() 356 { 357 QWebElementCollection emptyCollection; 358 QCOMPARE(emptyCollection.count(), 0); 359 } 360 361 void tst_QWebElement::appendCollection() 362 { 363 QString html = "<body><span class='a'>aaa</span><p>first para</p><div>foo</div>" 364 "<span class='b'>bbb</span><p>second para</p><div>bar</div></body>"; 365 m_mainFrame->setHtml(html); 366 QWebElement body = m_mainFrame->documentElement(); 367 368 QWebElementCollection collection = body.findAll("p"); 369 QCOMPARE(collection.count(), 2); 370 371 collection.append(body.findAll("div")); 372 QCOMPARE(collection.count(), 4); 373 374 collection += body.findAll("span.a"); 375 QCOMPARE(collection.count(), 5); 376 377 QWebElementCollection all = collection + body.findAll("span.b"); 378 QCOMPARE(all.count(), 6); 379 QCOMPARE(collection.count(), 5); 380 381 all += collection; 382 QCOMPARE(all.count(), 11); 383 384 QCOMPARE(collection.count(), 5); 385 QWebElementCollection test; 386 test.append(collection); 387 QCOMPARE(test.count(), 5); 388 test.append(QWebElementCollection()); 389 QCOMPARE(test.count(), 5); 390 } 391 392 void tst_QWebElement::evaluateJavaScript() 393 { 394 QVariant result; 395 m_mainFrame->setHtml("<body><p>test"); 396 QWebElement para = m_mainFrame->findFirstElement("p"); 397 398 result = para.evaluateJavaScript("this.tagName"); 399 QVERIFY(result.isValid()); 400 QVERIFY(result.type() == QVariant::String); 401 QCOMPARE(result.toString(), QLatin1String("P")); 402 403 result = para.evaluateJavaScript("this.hasAttributes()"); 404 QVERIFY(result.isValid()); 405 QVERIFY(result.type() == QVariant::Bool); 406 QVERIFY(!result.toBool()); 407 408 para.evaluateJavaScript("this.setAttribute('align', 'left');"); 409 QCOMPARE(para.attribute("align"), QLatin1String("left")); 410 411 result = para.evaluateJavaScript("this.hasAttributes()"); 412 QVERIFY(result.isValid()); 413 QVERIFY(result.type() == QVariant::Bool); 414 QVERIFY(result.toBool()); 415 } 416 417 void tst_QWebElement::documentElement() 418 { 419 m_mainFrame->setHtml("<body><p>Test"); 420 421 QWebElement para = m_mainFrame->documentElement().findAll("p").at(0); 422 QVERIFY(para.parent().parent() == m_mainFrame->documentElement()); 423 QVERIFY(para.document() == m_mainFrame->documentElement()); 424 } 425 426 void tst_QWebElement::frame() 427 { 428 m_mainFrame->setHtml("<body><p>test"); 429 430 QWebElement doc = m_mainFrame->documentElement(); 431 QVERIFY(doc.webFrame() == m_mainFrame); 432 433 m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," 434 "<p>frame1\">" 435 "<frame src=\"data:text/html,<p>frame2\"></frameset>"), QUrl()); 436 437 waitForSignal(m_page, SIGNAL(loadFinished(bool))); 438 439 QCOMPARE(m_mainFrame->childFrames().count(), 2); 440 441 QWebFrame* firstFrame = m_mainFrame->childFrames().at(0); 442 QWebFrame* secondFrame = m_mainFrame->childFrames().at(1); 443 444 QCOMPARE(firstFrame->toPlainText(), QString("frame1")); 445 QCOMPARE(secondFrame->toPlainText(), QString("frame2")); 446 447 QWebElement firstPara = firstFrame->documentElement().findAll("p").at(0); 448 QWebElement secondPara = secondFrame->documentElement().findAll("p").at(0); 449 450 QVERIFY(firstPara.webFrame() == firstFrame); 451 QVERIFY(secondPara.webFrame() == secondFrame); 452 } 453 454 void tst_QWebElement::style() 455 { 456 QString html = "<head>" 457 "<style type='text/css'>" 458 "p { color: green !important }" 459 "#idP { color: red }" 460 ".classP { color : yellow ! important }" 461 "</style>" 462 "</head>" 463 "<body>" 464 "<p id='idP' class='classP' style='color: blue;'>some text</p>" 465 "</body>"; 466 467 m_mainFrame->setHtml(html); 468 469 QWebElement p = m_mainFrame->documentElement().findAll("p").at(0); 470 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("blue")); 471 QVERIFY(p.styleProperty("cursor", QWebElement::InlineStyle).isEmpty()); 472 473 p.setStyleProperty("color", "red"); 474 p.setStyleProperty("cursor", "auto"); 475 476 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("red")); 477 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("yellow")); 478 QCOMPARE(p.styleProperty("cursor", QWebElement::InlineStyle), QLatin1String("auto")); 479 480 p.setStyleProperty("color", "green !important"); 481 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("green")); 482 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("green")); 483 484 p.setStyleProperty("color", "blue"); 485 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("green")); 486 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("green")); 487 488 p.setStyleProperty("color", "blue !important"); 489 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("blue")); 490 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("blue")); 491 492 QString html2 = "<head>" 493 "<style type='text/css'>" 494 "p { color: green }" 495 "#idP { color: red }" 496 ".classP { color: yellow }" 497 "</style>" 498 "</head>" 499 "<body>" 500 "<p id='idP' class='classP' style='color: blue;'>some text</p>" 501 "</body>"; 502 503 m_mainFrame->setHtml(html2); 504 p = m_mainFrame->documentElement().findAll("p").at(0); 505 506 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("blue")); 507 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("blue")); 508 509 QString html3 = "<head>" 510 "<style type='text/css'>" 511 "p { color: green !important }" 512 "#idP { color: red !important}" 513 ".classP { color: yellow !important}" 514 "</style>" 515 "</head>" 516 "<body>" 517 "<p id='idP' class='classP' style='color: blue !important;'>some text</p>" 518 "</body>"; 519 520 m_mainFrame->setHtml(html3); 521 p = m_mainFrame->documentElement().findAll("p").at(0); 522 523 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("blue")); 524 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("blue")); 525 526 QString html5 = "<head>" 527 "<style type='text/css'>" 528 "p { color: green }" 529 "#idP { color: red }" 530 ".classP { color: yellow }" 531 "</style>" 532 "</head>" 533 "<body>" 534 "<p id='idP' class='classP'>some text</p>" 535 "</body>"; 536 537 m_mainFrame->setHtml(html5); 538 p = m_mainFrame->documentElement().findAll("p").at(0); 539 540 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("")); 541 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("red")); 542 543 QString html6 = "<head>" 544 "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />" 545 "<style type='text/css'>" 546 "p { color: green }" 547 "#idP { color: red }" 548 ".classP { color: yellow ! important}" 549 "</style>" 550 "</head>" 551 "<body>" 552 "<p id='idP' class='classP' style='color: blue;'>some text</p>" 553 "</body>"; 554 555 // in few seconds, the CSS should be completey loaded 556 m_mainFrame->setHtml(html6); 557 waitForSignal(m_page, SIGNAL(loadFinished(bool)), 200); 558 559 p = m_mainFrame->documentElement().findAll("p").at(0); 560 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("blue")); 561 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("black")); 562 563 QString html7 = "<head>" 564 "<style type='text/css'>" 565 "@import url(qrc:/style2.css);" 566 "</style>" 567 "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />" 568 "</head>" 569 "<body>" 570 "<p id='idP' style='color: blue;'>some text</p>" 571 "</body>"; 572 573 // in few seconds, the style should be completey loaded 574 m_mainFrame->setHtml(html7); 575 waitForSignal(m_page, SIGNAL(loadFinished(bool)), 200); 576 577 p = m_mainFrame->documentElement().findAll("p").at(0); 578 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("black")); 579 580 QString html8 = "<body><p>some text</p></body>"; 581 582 m_mainFrame->setHtml(html8); 583 p = m_mainFrame->documentElement().findAll("p").at(0); 584 585 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("")); 586 QCOMPARE(p.styleProperty("color", QWebElement::CascadedStyle), QLatin1String("")); 587 } 588 589 void tst_QWebElement::computedStyle() 590 { 591 QString html = "<body><p>some text</p></body>"; 592 m_mainFrame->setHtml(html); 593 594 QWebElement p = m_mainFrame->documentElement().findAll("p").at(0); 595 QCOMPARE(p.styleProperty("cursor", QWebElement::ComputedStyle), QLatin1String("auto")); 596 QVERIFY(!p.styleProperty("cursor", QWebElement::ComputedStyle).isEmpty()); 597 QVERIFY(p.styleProperty("cursor", QWebElement::InlineStyle).isEmpty()); 598 599 p.setStyleProperty("cursor", "text"); 600 p.setStyleProperty("color", "red"); 601 602 QCOMPARE(p.styleProperty("cursor", QWebElement::ComputedStyle), QLatin1String("text")); 603 QCOMPARE(p.styleProperty("color", QWebElement::ComputedStyle), QLatin1String("rgb(255, 0, 0)")); 604 QCOMPARE(p.styleProperty("color", QWebElement::InlineStyle), QLatin1String("red")); 605 } 606 607 void tst_QWebElement::appendAndPrepend() 608 { 609 QString html = "<body>" 610 "<p>" 611 "foo" 612 "</p>" 613 "<p>" 614 "bar" 615 "</p>" 616 "</body>"; 617 618 m_mainFrame->setHtml(html); 619 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 620 621 QCOMPARE(body.findAll("p").count(), 2); 622 body.appendInside(body.findFirst("p")); 623 QCOMPARE(body.findAll("p").count(), 2); 624 QCOMPARE(body.findFirst("p").toPlainText(), QString("bar")); 625 QCOMPARE(body.findAll("p").last().toPlainText(), QString("foo")); 626 627 body.appendInside(body.findFirst("p").clone()); 628 QCOMPARE(body.findAll("p").count(), 3); 629 QCOMPARE(body.findFirst("p").toPlainText(), QString("bar")); 630 QCOMPARE(body.findAll("p").last().toPlainText(), QString("bar")); 631 632 body.prependInside(body.findAll("p").at(1).clone()); 633 QCOMPARE(body.findAll("p").count(), 4); 634 QCOMPARE(body.findFirst("p").toPlainText(), QString("foo")); 635 636 body.findFirst("p").appendInside("<div>booyakasha</div>"); 637 QCOMPARE(body.findAll("p div").count(), 1); 638 QCOMPARE(body.findFirst("p div").toPlainText(), QString("booyakasha")); 639 640 body.findFirst("div").prependInside("<code>yepp</code>"); 641 QCOMPARE(body.findAll("p div code").count(), 1); 642 QCOMPARE(body.findFirst("p div code").toPlainText(), QString("yepp")); 643 } 644 645 void tst_QWebElement::insertBeforeAndAfter() 646 { 647 QString html = "<body>" 648 "<p>" 649 "foo" 650 "</p>" 651 "<div>" 652 "yeah" 653 "</div>" 654 "<p>" 655 "bar" 656 "</p>" 657 "</body>"; 658 659 m_mainFrame->setHtml(html); 660 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 661 QWebElement div = body.findFirst("div"); 662 663 QCOMPARE(body.findAll("p").count(), 2); 664 QCOMPARE(body.findAll("div").count(), 1); 665 666 div.prependOutside(body.findAll("p").last().clone()); 667 QCOMPARE(body.findAll("p").count(), 3); 668 QCOMPARE(body.findAll("p").at(0).toPlainText(), QString("foo")); 669 QCOMPARE(body.findAll("p").at(1).toPlainText(), QString("bar")); 670 QCOMPARE(body.findAll("p").at(2).toPlainText(), QString("bar")); 671 672 div.appendOutside(body.findFirst("p").clone()); 673 QCOMPARE(body.findAll("p").count(), 4); 674 QCOMPARE(body.findAll("p").at(0).toPlainText(), QString("foo")); 675 QCOMPARE(body.findAll("p").at(1).toPlainText(), QString("bar")); 676 QCOMPARE(body.findAll("p").at(2).toPlainText(), QString("foo")); 677 QCOMPARE(body.findAll("p").at(3).toPlainText(), QString("bar")); 678 679 div.prependOutside("<span>hey</span>"); 680 QCOMPARE(body.findAll("span").count(), 1); 681 682 div.appendOutside("<span>there</span>"); 683 QCOMPARE(body.findAll("span").count(), 2); 684 QCOMPARE(body.findAll("span").at(0).toPlainText(), QString("hey")); 685 QCOMPARE(body.findAll("span").at(1).toPlainText(), QString("there")); 686 } 687 688 void tst_QWebElement::remove() 689 { 690 QString html = "<body>" 691 "<p>" 692 "foo" 693 "</p>" 694 "<div>" 695 "<p>yeah</p>" 696 "</div>" 697 "<p>" 698 "bar" 699 "</p>" 700 "</body>"; 701 702 m_mainFrame->setHtml(html); 703 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 704 705 QCOMPARE(body.findAll("div").count(), 1); 706 QCOMPARE(body.findAll("p").count(), 3); 707 708 QWebElement div = body.findFirst("div"); 709 div.takeFromDocument(); 710 711 QCOMPARE(div.isNull(), false); 712 QCOMPARE(body.findAll("div").count(), 0); 713 QCOMPARE(body.findAll("p").count(), 2); 714 715 body.appendInside(div); 716 717 QCOMPARE(body.findAll("div").count(), 1); 718 QCOMPARE(body.findAll("p").count(), 3); 719 } 720 721 void tst_QWebElement::clear() 722 { 723 QString html = "<body>" 724 "<p>" 725 "foo" 726 "</p>" 727 "<div>" 728 "<p>yeah</p>" 729 "</div>" 730 "<p>" 731 "bar" 732 "</p>" 733 "</body>"; 734 735 m_mainFrame->setHtml(html); 736 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 737 738 QCOMPARE(body.findAll("div").count(), 1); 739 QCOMPARE(body.findAll("p").count(), 3); 740 body.findFirst("div").removeAllChildren(); 741 QCOMPARE(body.findAll("div").count(), 1); 742 QCOMPARE(body.findAll("p").count(), 2); 743 } 744 745 746 void tst_QWebElement::replaceWith() 747 { 748 QString html = "<body>" 749 "<p>" 750 "foo" 751 "</p>" 752 "<div>" 753 "yeah" 754 "</div>" 755 "<p>" 756 "<span>haba</span>" 757 "</p>" 758 "</body>"; 759 760 m_mainFrame->setHtml(html); 761 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 762 763 QCOMPARE(body.findAll("div").count(), 1); 764 QCOMPARE(body.findAll("span").count(), 1); 765 body.findFirst("div").replace(body.findFirst("span").clone()); 766 QCOMPARE(body.findAll("div").count(), 0); 767 QCOMPARE(body.findAll("span").count(), 2); 768 QCOMPARE(body.findAll("p").count(), 2); 769 770 body.findFirst("span").replace("<p><code>wow</code></p>"); 771 QCOMPARE(body.findAll("p").count(), 3); 772 QCOMPARE(body.findAll("p code").count(), 1); 773 QCOMPARE(body.findFirst("p code").toPlainText(), QString("wow")); 774 } 775 776 void tst_QWebElement::encloseContentsWith() 777 { 778 QString html = "<body>" 779 "<div>" 780 "<i>" 781 "yeah" 782 "</i>" 783 "<i>" 784 "hello" 785 "</i>" 786 "</div>" 787 "<p>" 788 "<span>foo</span>" 789 "<span>bar</span>" 790 "</p>" 791 "<u></u>" 792 "<b></b>" 793 "<em>hey</em>" 794 "</body>"; 795 796 m_mainFrame->setHtml(html); 797 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 798 799 body.findFirst("p").encloseContentsWith(body.findFirst("b")); 800 QCOMPARE(body.findAll("p b span").count(), 2); 801 QCOMPARE(body.findFirst("p b span").toPlainText(), QString("foo")); 802 803 body.findFirst("u").encloseContentsWith("<i></i>"); 804 QCOMPARE(body.findAll("u i").count(), 1); 805 QCOMPARE(body.findFirst("u i").toPlainText(), QString()); 806 807 body.findFirst("div").encloseContentsWith("<span></span>"); 808 QCOMPARE(body.findAll("div span i").count(), 2); 809 QCOMPARE(body.findFirst("div span i").toPlainText(), QString("yeah")); 810 811 QString snippet = "" 812 "<table>" 813 "<tbody>" 814 "<tr>" 815 "<td></td>" 816 "<td></td>" 817 "</tr>" 818 "<tr>" 819 "<td></td>" 820 "<td></td>" 821 "<tr>" 822 "</tbody>" 823 "</table>"; 824 825 body.findFirst("em").encloseContentsWith(snippet); 826 QCOMPARE(body.findFirst("em table tbody tr td").toPlainText(), QString("hey")); 827 } 828 829 void tst_QWebElement::encloseWith() 830 { 831 QString html = "<body>" 832 "<p>" 833 "foo" 834 "</p>" 835 "<div>" 836 "yeah" 837 "</div>" 838 "<p>" 839 "<span>bar</span>" 840 "</p>" 841 "<em>hey</em>" 842 "<h1>hello</h1>" 843 "</body>"; 844 845 m_mainFrame->setHtml(html); 846 QWebElement body = m_mainFrame->documentElement().findFirst("body"); 847 848 body.findFirst("p").encloseWith("<br>"); 849 QCOMPARE(body.findAll("br").count(), 0); 850 851 QCOMPARE(body.findAll("div").count(), 1); 852 body.findFirst("div").encloseWith(body.findFirst("span").clone()); 853 QCOMPARE(body.findAll("div").count(), 1); 854 QCOMPARE(body.findAll("span").count(), 2); 855 QCOMPARE(body.findAll("p").count(), 2); 856 857 body.findFirst("div").encloseWith("<code></code>"); 858 QCOMPARE(body.findAll("code").count(), 1); 859 QCOMPARE(body.findAll("code div").count(), 1); 860 QCOMPARE(body.findFirst("code div").toPlainText(), QString("yeah")); 861 862 QString snippet = "" 863 "<table>" 864 "<tbody>" 865 "<tr>" 866 "<td></td>" 867 "<td></td>" 868 "</tr>" 869 "<tr>" 870 "<td></td>" 871 "<td></td>" 872 "<tr>" 873 "</tbody>" 874 "</table>"; 875 876 body.findFirst("em").encloseWith(snippet); 877 QCOMPARE(body.findFirst("table tbody tr td em").toPlainText(), QString("hey")); 878 } 879 880 void tst_QWebElement::nullSelect() 881 { 882 m_mainFrame->setHtml("<body><p>Test"); 883 884 QWebElementCollection collection = m_mainFrame->findAllElements("invalid{syn(tax;;%#$f223e>>"); 885 QVERIFY(collection.count() == 0); 886 } 887 888 void tst_QWebElement::firstChildNextSibling() 889 { 890 m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another commend><table>"); 891 892 QWebElement body = m_mainFrame->findFirstElement("body"); 893 QVERIFY(!body.isNull()); 894 QWebElement p = body.firstChild(); 895 QVERIFY(!p.isNull()); 896 QCOMPARE(p.tagName(), QString("P")); 897 QWebElement table = p.nextSibling(); 898 QVERIFY(!table.isNull()); 899 QCOMPARE(table.tagName(), QString("TABLE")); 900 QVERIFY(table.nextSibling().isNull()); 901 } 902 903 void tst_QWebElement::lastChildPreviousSibling() 904 { 905 m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another commend><table>"); 906 907 QWebElement body = m_mainFrame->findFirstElement("body"); 908 QVERIFY(!body.isNull()); 909 QWebElement table = body.lastChild(); 910 QVERIFY(!table.isNull()); 911 QCOMPARE(table.tagName(), QString("TABLE")); 912 QWebElement p = table.previousSibling(); 913 QVERIFY(!p.isNull()); 914 QCOMPARE(p.tagName(), QString("P")); 915 QVERIFY(p.previousSibling().isNull()); 916 } 917 918 void tst_QWebElement::hasSetFocus() 919 { 920 m_mainFrame->setHtml("<html><body>" \ 921 "<input type='text' id='input1'/>" \ 922 "<br>"\ 923 "<input type='text' id='input2'/>" \ 924 "</body></html>"); 925 926 QWebElementCollection inputs = m_mainFrame->documentElement().findAll("input"); 927 QWebElement input1 = inputs.at(0); 928 input1.setFocus(); 929 QVERIFY(input1.hasFocus()); 930 931 QWebElement input2 = inputs.at(1); 932 input2.setFocus(); 933 QVERIFY(!input1.hasFocus()); 934 QVERIFY(input2.hasFocus()); 935 } 936 937 void tst_QWebElement::render() 938 { 939 QString html( "<html>" 940 "<head><style>" 941 "body, iframe { margin: 0px; border: none; }" 942 "</style></head>" 943 "<body><table width='300px' height='300px' border='1'>" 944 "<tr>" 945 "<td>test" 946 "</td>" 947 "<td><img src='qrc:///image.png'>" 948 "</td>" 949 "</tr>" 950 "</table>" 951 "</body>" 952 "</html>" 953 ); 954 955 QWebPage page; 956 QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); 957 page.mainFrame()->setHtml(html); 958 959 waitForSignal(&page, SIGNAL(loadFinished(bool))); 960 QCOMPARE(loadSpy.count(), 1); 961 962 QSize size = page.mainFrame()->contentsSize(); 963 page.setViewportSize(size); 964 965 QWebElementCollection imgs = page.mainFrame()->findAllElements("img"); 966 QCOMPARE(imgs.count(), 1); 967 968 QImage resource(":/image.png"); 969 QRect imageRect(0, 0, resource.width(), resource.height()); 970 971 QImage testImage(resource.width(), resource.height(), QImage::Format_ARGB32); 972 QPainter painter0(&testImage); 973 painter0.fillRect(imageRect, Qt::white); 974 // render() uses pixmaps internally, and pixmaps might have bit depths 975 // other than 32, giving different pixel values due to rounding. 976 QPixmap pix = QPixmap::fromImage(resource); 977 painter0.drawPixmap(0, 0, pix); 978 painter0.end(); 979 980 QImage image1(resource.width(), resource.height(), QImage::Format_ARGB32); 981 QPainter painter1(&image1); 982 painter1.fillRect(imageRect, Qt::white); 983 imgs[0].render(&painter1); 984 painter1.end(); 985 986 QVERIFY(image1 == testImage); 987 988 // render image 2nd time to make sure that cached rendering works fine 989 QImage image2(resource.width(), resource.height(), QImage::Format_ARGB32); 990 QPainter painter2(&image2); 991 painter2.fillRect(imageRect, Qt::white); 992 imgs[0].render(&painter2); 993 painter2.end(); 994 995 QVERIFY(image2 == testImage); 996 997 // compare table rendered through QWebElement::render to whole page table rendering 998 QRect tableRect(0, 0, 300, 300); 999 QWebElementCollection tables = page.mainFrame()->findAllElements("table"); 1000 QCOMPARE(tables.count(), 1); 1001 1002 QImage image3(300, 300, QImage::Format_ARGB32); 1003 QPainter painter3(&image3); 1004 painter3.fillRect(tableRect, Qt::white); 1005 tables[0].render(&painter3); 1006 painter3.end(); 1007 1008 QImage image4(300, 300, QImage::Format_ARGB32); 1009 QPainter painter4(&image4); 1010 page.mainFrame()->render(&painter4, tableRect); 1011 painter4.end(); 1012 1013 QVERIFY(image3 == image4); 1014 } 1015 1016 QTEST_MAIN(tst_QWebElement) 1017 #include "tst_qwebelement.moc" 1018