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 
     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