Home | History | Annotate | Download | only in qwebelement
      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