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