diff options
Diffstat (limited to 'WebKit/qt/tests')
39 files changed, 2727 insertions, 22 deletions
diff --git a/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp b/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp new file mode 100644 index 0000000..0bc87f7 --- /dev/null +++ b/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009 Holger Hans Peter Freyther + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <QtTest/QtTest> + +#include <qwebframe.h> +#include <qwebview.h> +#include <qpainter.h> + +/** + * Starts an event loop that runs until the given signal is received. + Optionally the event loop + * can return earlier on a timeout. + * + * \return \p true if the requested signal was received + * \p false on timeout + */ +static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) +{ + QEventLoop loop; + QObject::connect(obj, signal, &loop, SLOT(quit())); + QTimer timer; + QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); + if (timeout > 0) { + QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.setSingleShot(true); + timer.start(timeout); + } + loop.exec(); + return timeoutSpy.isEmpty(); +} + +class tst_Loading : public QObject +{ + Q_OBJECT + +public: + +public Q_SLOTS: + void init(); + void cleanup(); + +private Q_SLOTS: + void load_data(); + void load(); + +private: + QWebView* m_view; + QWebPage* m_page; +}; + +void tst_Loading::init() +{ + m_view = new QWebView; + m_page = m_view->page(); + + QSize viewportSize(1024, 768); + m_view->setFixedSize(viewportSize); + m_page->setViewportSize(viewportSize); +} + +void tst_Loading::cleanup() +{ + delete m_view; +} + +void tst_Loading::load_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::newRow("amazon") << QUrl("http://www.amazon.com"); + QTest::newRow("kde") << QUrl("http://www.kde.org"); + QTest::newRow("apple") << QUrl("http://www.apple.com"); +} + +void tst_Loading::load() +{ + QFETCH(QUrl, url); + + + QBENCHMARK { + m_view->load(url); + + // really wait for loading, painting is in another test + ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); + } +} + +QTEST_MAIN(tst_Loading) +#include "tst_loading.moc" diff --git a/WebKit/qt/tests/benchmarks/loading/tst_loading.pro b/WebKit/qt/tests/benchmarks/loading/tst_loading.pro new file mode 100644 index 0000000..af0387e --- /dev/null +++ b/WebKit/qt/tests/benchmarks/loading/tst_loading.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = tst_loading +include(../../../../../WebKit.pri) +SOURCES += tst_loading.cpp +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp b/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp new file mode 100644 index 0000000..f4531fd --- /dev/null +++ b/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2009 Holger Hans Peter Freyther + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <QtTest/QtTest> + +#include <qwebframe.h> +#include <qwebview.h> +#include <qpainter.h> + +/** + * Starts an event loop that runs until the given signal is received. + Optionally the event loop + * can return earlier on a timeout. + * + * \return \p true if the requested signal was received + * \p false on timeout + */ +static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) +{ + QEventLoop loop; + QObject::connect(obj, signal, &loop, SLOT(quit())); + QTimer timer; + QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); + if (timeout > 0) { + QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.setSingleShot(true); + timer.start(timeout); + } + loop.exec(); + return timeoutSpy.isEmpty(); +} + +class tst_Painting : public QObject +{ + Q_OBJECT + +public: + +public Q_SLOTS: + void init(); + void cleanup(); + +private Q_SLOTS: + void paint_data(); + void paint(); + +private: + QWebView* m_view; + QWebPage* m_page; +}; + +void tst_Painting::init() +{ + m_view = new QWebView; + m_page = m_view->page(); + + QSize viewportSize(1024, 768); + m_view->setFixedSize(viewportSize); + m_page->setViewportSize(viewportSize); +} + +void tst_Painting::cleanup() +{ + delete m_view; +} + +void tst_Painting::paint_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::newRow("amazon") << QUrl("http://www.amazon.com"); +} + +void tst_Painting::paint() +{ + QFETCH(QUrl, url); + + m_view->load(url); + ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); + + /* force a layout */ + QWebFrame* mainFrame = m_page->mainFrame(); + mainFrame->toPlainText(); + + QPixmap pixmap(m_page->viewportSize()); + QBENCHMARK { + QPainter painter(&pixmap); + mainFrame->render(&painter, QRect(QPoint(0, 0), m_page->viewportSize())); + painter.end(); + } +} + +QTEST_MAIN(tst_Painting) +#include "tst_painting.moc" diff --git a/WebKit/qt/tests/benchmarks/painting/tst_painting.pro b/WebKit/qt/tests/benchmarks/painting/tst_painting.pro new file mode 100644 index 0000000..496210e --- /dev/null +++ b/WebKit/qt/tests/benchmarks/painting/tst_painting.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = tst_painting +include(../../../../../WebKit.pri) +SOURCES += tst_painting.cpp +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebelement/qwebelement.pro b/WebKit/qt/tests/qwebelement/qwebelement.pro new file mode 100644 index 0000000..dd0b88a --- /dev/null +++ b/WebKit/qt/tests/qwebelement/qwebelement.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = tst_qwebelement +include(../../../../WebKit.pri) +SOURCES += tst_qwebelement.cpp +RESOURCES += qwebelement.qrc +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebelement/qwebelement.qrc b/WebKit/qt/tests/qwebelement/qwebelement.qrc new file mode 100644 index 0000000..ed01440 --- /dev/null +++ b/WebKit/qt/tests/qwebelement/qwebelement.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/"> +<file>style.css</file> +<file>style2.css</file> +</qresource> +</RCC> diff --git a/WebKit/qt/tests/qwebelement/style.css b/WebKit/qt/tests/qwebelement/style.css new file mode 100644 index 0000000..2713dfd --- /dev/null +++ b/WebKit/qt/tests/qwebelement/style.css @@ -0,0 +1 @@ +#idP {color: black !important} diff --git a/WebKit/qt/tests/qwebelement/style2.css b/WebKit/qt/tests/qwebelement/style2.css new file mode 100644 index 0000000..6575dcb --- /dev/null +++ b/WebKit/qt/tests/qwebelement/style2.css @@ -0,0 +1 @@ +#idP {color: green ! important} diff --git a/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp b/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp new file mode 100644 index 0000000..0819a3a --- /dev/null +++ b/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp @@ -0,0 +1,882 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include <QtTest/QtTest> + +#include <qwebpage.h> +#include <qwidget.h> +#include <qwebview.h> +#include <qwebframe.h> +#include <qwebelement.h> +//TESTED_CLASS= +//TESTED_FILES= + +/** + * Starts an event loop that runs until the given signal is received. + Optionally the event loop + * can return earlier on a timeout. + * + * \return \p true if the requested signal was received + * \p false on timeout + */ +static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) +{ + QEventLoop loop; + QObject::connect(obj, signal, &loop, SLOT(quit())); + QTimer timer; + QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); + if (timeout > 0) { + QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.setSingleShot(true); + timer.start(timeout); + } + loop.exec(); + return timeoutSpy.isEmpty(); +} + +class tst_QWebElement : public QObject +{ + Q_OBJECT + +public: + tst_QWebElement(); + virtual ~tst_QWebElement(); + +public slots: + void init(); + void cleanup(); + +private slots: + void textHtml(); + void simpleCollection(); + void attributes(); + void attributesNS(); + void classes(); + void namespaceURI(); + void foreachManipulation(); + void evaluateScript(); + void callFunction(); + void callFunctionSubmitForm(); + void functionNames(); + void documentElement(); + void frame(); + void style(); + void computedStyle(); + void properties(); + void appendAndPrepend(); + void insertBeforeAndAfter(); + void remove(); + void clear(); + void replaceWith(); + void encloseWith(); + void encloseContentsWith(); + void nullSelect(); + void firstChildNextSibling(); + void lastChildPreviousSibling(); + +private: + QWebView* m_view; + QWebPage* m_page; + QWebFrame* m_mainFrame; +}; + +tst_QWebElement::tst_QWebElement() +{ +} + +tst_QWebElement::~tst_QWebElement() +{ +} + +void tst_QWebElement::init() +{ + m_view = new QWebView(); + m_page = m_view->page(); + m_mainFrame = m_page->mainFrame(); +} + +void tst_QWebElement::cleanup() +{ + delete m_view; +} + +void tst_QWebElement::textHtml() +{ + QString html = "<head></head><body><p>test</p></body>"; + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement(); + QVERIFY(!body.isNull()); + + QCOMPARE(body.toPlainText(), QString("test")); + QCOMPARE(body.toPlainText(), m_mainFrame->toPlainText()); + + QCOMPARE(body.toInnerXml(), html); +} + +void tst_QWebElement::simpleCollection() +{ + QString html = "<body><p>first para</p><p>second para</p></body>"; + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement(); + + QList<QWebElement> list = body.findAll("p"); + QCOMPARE(list.count(), 2); + QCOMPARE(list.at(0).toPlainText(), QString("first para")); + QCOMPARE(list.at(1).toPlainText(), QString("second para")); +} + +void tst_QWebElement::attributes() +{ + m_mainFrame->setHtml("<body><p>Test"); + QWebElement body = m_mainFrame->documentElement(); + + QVERIFY(!body.hasAttribute("title")); + QVERIFY(!body.hasAttributes()); + + body.setAttribute("title", "test title"); + + QVERIFY(body.hasAttributes()); + QVERIFY(body.hasAttribute("title")); + + QCOMPARE(body.attribute("title"), QString("test title")); + + body.removeAttribute("title"); + + QVERIFY(!body.hasAttribute("title")); + QVERIFY(!body.hasAttributes()); + + QCOMPARE(body.attribute("does-not-exist", "testvalue"), QString("testvalue")); +} + +void tst_QWebElement::attributesNS() +{ + QString content = "<html xmlns=\"http://www.w3.org/1999/xhtml\" " + "xmlns:svg=\"http://www.w3.org/2000/svg\">" + "<body><svg:svg id=\"foobar\" width=\"400px\" height=\"300px\">" + "</svg:svg></body></html>"; + + m_mainFrame->setContent(content.toUtf8(), "application/xhtml+xml"); + + QWebElement svg = m_mainFrame->findFirstElement("svg"); + QVERIFY(!svg.isNull()); + + QVERIFY(!svg.hasAttributeNS("http://www.w3.org/2000/svg", "foobar")); + QCOMPARE(svg.attributeNS("http://www.w3.org/2000/svg", "foobar", "defaultblah"), QString("defaultblah")); + svg.setAttributeNS("http://www.w3.org/2000/svg", "svg:foobar", "true"); + QVERIFY(svg.hasAttributeNS("http://www.w3.org/2000/svg", "foobar")); + QCOMPARE(svg.attributeNS("http://www.w3.org/2000/svg", "foobar", "defaultblah"), QString("true")); +} + +void tst_QWebElement::classes() +{ + m_mainFrame->setHtml("<body><p class=\"a b c d a c\">Test"); + + QWebElement body = m_mainFrame->documentElement(); + QCOMPARE(body.classes().count(), 0); + + QWebElement p = m_mainFrame->documentElement().findAll("p").at(0); + QStringList classes = p.classes(); + QCOMPARE(classes.count(), 4); + QCOMPARE(classes[0], QLatin1String("a")); + QCOMPARE(classes[1], QLatin1String("b")); + QCOMPARE(classes[2], QLatin1String("c")); + QCOMPARE(classes[3], QLatin1String("d")); + QVERIFY(p.hasClass("a")); + QVERIFY(p.hasClass("b")); + QVERIFY(p.hasClass("c")); + QVERIFY(p.hasClass("d")); + QVERIFY(!p.hasClass("e")); + + p.addClass("f"); + QVERIFY(p.hasClass("f")); + p.addClass("a"); + QCOMPARE(p.classes().count(), 5); + QVERIFY(p.hasClass("a")); + QVERIFY(p.hasClass("b")); + QVERIFY(p.hasClass("c")); + QVERIFY(p.hasClass("d")); + + p.toggleClass("a"); + QVERIFY(!p.hasClass("a")); + QVERIFY(p.hasClass("b")); + QVERIFY(p.hasClass("c")); + QVERIFY(p.hasClass("d")); + QVERIFY(p.hasClass("f")); + QCOMPARE(p.classes().count(), 4); + p.toggleClass("f"); + QVERIFY(!p.hasClass("f")); + QCOMPARE(p.classes().count(), 3); + p.toggleClass("a"); + p.toggleClass("f"); + QVERIFY(p.hasClass("a")); + QVERIFY(p.hasClass("f")); + QCOMPARE(p.classes().count(), 5); + + p.removeClass("f"); + QVERIFY(!p.hasClass("f")); + QCOMPARE(p.classes().count(), 4); + p.removeClass("d"); + QVERIFY(!p.hasClass("d")); + QCOMPARE(p.classes().count(), 3); + p.removeClass("not-exist"); + QCOMPARE(p.classes().count(), 3); + p.removeClass("c"); + QVERIFY(!p.hasClass("c")); + QCOMPARE(p.classes().count(), 2); + p.removeClass("b"); + QVERIFY(!p.hasClass("b")); + QCOMPARE(p.classes().count(), 1); + p.removeClass("a"); + QVERIFY(!p.hasClass("a")); + QCOMPARE(p.classes().count(), 0); + p.removeClass("foobar"); + QCOMPARE(p.classes().count(), 0); +} + +void tst_QWebElement::namespaceURI() +{ + QString content = "<html xmlns=\"http://www.w3.org/1999/xhtml\" " + "xmlns:svg=\"http://www.w3.org/2000/svg\">" + "<body><svg:svg id=\"foobar\" width=\"400px\" height=\"300px\">" + "</svg:svg></body></html>"; + + m_mainFrame->setContent(content.toUtf8(), "application/xhtml+xml"); + QWebElement body = m_mainFrame->documentElement(); + QCOMPARE(body.namespaceUri(), QLatin1String("http://www.w3.org/1999/xhtml")); + + QWebElement svg = body.findAll("*#foobar").at(0); + QCOMPARE(svg.prefix(), QLatin1String("svg")); + QCOMPARE(svg.localName(), QLatin1String("svg")); + QCOMPARE(svg.tagName(), QLatin1String("svg:svg")); + QCOMPARE(svg.namespaceUri(), QLatin1String("http://www.w3.org/2000/svg")); + +} + +void tst_QWebElement::foreachManipulation() +{ + QString html = "<body><p>first para</p><p>second para</p></body>"; + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement(); + + foreach(QWebElement p, body.findAll("p")) { + p.setInnerXml("<div>foo</div><div>bar</div>"); + } + + QCOMPARE(body.findAll("div").count(), 4); +} + +void tst_QWebElement::evaluateScript() +{ + QVariant result; + m_mainFrame->setHtml("<body><p>test"); + QWebElement para = m_mainFrame->findFirstElement("p"); + + result = para.evaluateScript("this.tagName"); + QVERIFY(result.isValid()); + QVERIFY(result.type() == QVariant::String); + QCOMPARE(result.toString(), QLatin1String("P")); + + QVERIFY(para.functions().contains("hasAttributes")); + result = para.evaluateScript("this.hasAttributes()"); + QVERIFY(result.isValid()); + QVERIFY(result.type() == QVariant::Bool); + QVERIFY(!result.toBool()); + + para.evaluateScript("this.setAttribute('align', 'left');"); + QCOMPARE(para.attribute("align"), QLatin1String("left")); + + result = para.evaluateScript("this.hasAttributes()"); + QVERIFY(result.isValid()); + QVERIFY(result.type() == QVariant::Bool); + QVERIFY(result.toBool()); +} + +void tst_QWebElement::callFunction() +{ + m_mainFrame->setHtml("<body><p>test"); + QWebElement body = m_mainFrame->documentElement(); + QVERIFY(body.functions().contains("hasChildNodes")); + QVariant result = body.callFunction("hasChildNodes"); + QVERIFY(result.isValid()); + QVERIFY(result.type() == QVariant::Bool); + QVERIFY(result.toBool()); + + body.callFunction("setAttribute", QVariantList() << "foo" << "bar"); + QCOMPARE(body.attribute("foo"), QString("bar")); +} + +void tst_QWebElement::callFunctionSubmitForm() +{ + m_mainFrame->setHtml(QString("<html><body><form name='tstform' action='data:text/html,foo'method='get'>" + "<input type='text'><input type='submit'></form></body></html>"), QUrl()); + + QWebElement form = m_mainFrame->documentElement().findAll("form").at(0); + QVERIFY(form.functions().contains("submit")); + QVERIFY(!form.isNull()); + form.callFunction("submit"); + + waitForSignal(m_page, SIGNAL(loadFinished(bool))); + QCOMPARE(m_mainFrame->url().toString(), QString("data:text/html,foo?")); +} + +void tst_QWebElement::functionNames() +{ + m_mainFrame->setHtml("<body><p>Test"); + + QWebElement body = m_mainFrame->documentElement(); + + QVERIFY(body.functions().contains("setAttribute")); +} + +void tst_QWebElement::documentElement() +{ + m_mainFrame->setHtml("<body><p>Test"); + + QWebElement para = m_mainFrame->documentElement().findAll("p").at(0); + QVERIFY(para.parent().parent() == m_mainFrame->documentElement()); + QVERIFY(para.document() == m_mainFrame->documentElement()); +} + +void tst_QWebElement::frame() +{ + m_mainFrame->setHtml("<body><p>test"); + + QWebElement doc = m_mainFrame->documentElement(); + QVERIFY(doc.webFrame() == m_mainFrame); + + m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," + "<p>frame1\">" + "<frame src=\"data:text/html,<p>frame2\"></frameset>"), QUrl()); + + waitForSignal(m_page, SIGNAL(loadFinished(bool))); + + QCOMPARE(m_mainFrame->childFrames().count(), 2); + + QWebFrame* firstFrame = m_mainFrame->childFrames().at(0); + QWebFrame* secondFrame = m_mainFrame->childFrames().at(1); + + QCOMPARE(firstFrame->toPlainText(), QString("frame1")); + QCOMPARE(secondFrame->toPlainText(), QString("frame2")); + + QWebElement firstPara = firstFrame->documentElement().findAll("p").at(0); + QWebElement secondPara = secondFrame->documentElement().findAll("p").at(0); + + QVERIFY(firstPara.webFrame() == firstFrame); + QVERIFY(secondPara.webFrame() == secondFrame); +} + +void tst_QWebElement::style() +{ + QString html = "<head>" + "<style type='text/css'>" + "p { color: green !important }" + "#idP { color: red }" + ".classP { color : yellow ! important }" + "</style>" + "</head>" + "<body>" + "<p id='idP' class='classP' style='color: blue;'>some text</p>" + "</body>"; + + m_mainFrame->setHtml(html); + + QWebElement p = m_mainFrame->documentElement().findAll("p").at(0); + QCOMPARE(p.styleProperty("color"), QLatin1String("blue")); + QVERIFY(p.styleProperty("cursor").isEmpty()); + + p.setStyleProperty("color", "red"); + p.setStyleProperty("cursor", "auto"); + + QCOMPARE(p.styleProperty("color"), QLatin1String("red")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("yellow")); + QCOMPARE(p.styleProperty("cursor"), QLatin1String("auto")); + + p.setStyleProperty("color", "green !important"); + QCOMPARE(p.styleProperty("color"), QLatin1String("green")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("green")); + + p.setStyleProperty("color", "blue"); + QCOMPARE(p.styleProperty("color"), QLatin1String("green")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("green")); + + p.setStyleProperty("color", "blue", QWebElement::ImportantStylePriority); + QCOMPARE(p.styleProperty("color"), QLatin1String("blue")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("blue")); + + QString html2 = "<head>" + "<style type='text/css'>" + "p { color: green }" + "#idP { color: red }" + ".classP { color: yellow }" + "</style>" + "</head>" + "<body>" + "<p id='idP' class='classP' style='color: blue;'>some text</p>" + "</body>"; + + m_mainFrame->setHtml(html2); + p = m_mainFrame->documentElement().findAll("p").at(0); + + QCOMPARE(p.styleProperty("color"), QLatin1String("blue")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("blue")); + + QString html3 = "<head>" + "<style type='text/css'>" + "p { color: green !important }" + "#idP { color: red !important}" + ".classP { color: yellow !important}" + "</style>" + "</head>" + "<body>" + "<p id='idP' class='classP' style='color: blue !important;'>some text</p>" + "</body>"; + + m_mainFrame->setHtml(html3); + p = m_mainFrame->documentElement().findAll("p").at(0); + + QCOMPARE(p.styleProperty("color"), QLatin1String("blue")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("blue")); + + QString html5 = "<head>" + "<style type='text/css'>" + "p { color: green }" + "#idP { color: red }" + ".classP { color: yellow }" + "</style>" + "</head>" + "<body>" + "<p id='idP' class='classP'>some text</p>" + "</body>"; + + m_mainFrame->setHtml(html5); + p = m_mainFrame->documentElement().findAll("p").at(0); + + QCOMPARE(p.styleProperty("color"), QLatin1String("")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("red")); + + QString html6 = "<head>" + "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />" + "<style type='text/css'>" + "p { color: green }" + "#idP { color: red }" + ".classP { color: yellow ! important}" + "</style>" + "</head>" + "<body>" + "<p id='idP' class='classP' style='color: blue;'>some text</p>" + "</body>"; + + // in few seconds, the CSS should be completey loaded + QSignalSpy spy(m_page, SIGNAL(loadFinished(bool))); + m_mainFrame->setHtml(html6); + QTest::qWait(200); + + p = m_mainFrame->documentElement().findAll("p").at(0); + QCOMPARE(p.styleProperty("color"), QLatin1String("blue")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("black")); + + QString html7 = "<head>" + "<style type='text/css'>" + "@import url(qrc:/style2.css);" + "</style>" + "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />" + "</head>" + "<body>" + "<p id='idP' style='color: blue;'>some text</p>" + "</body>"; + + // in few seconds, the style should be completey loaded + m_mainFrame->setHtml(html7); + QTest::qWait(200); + + p = m_mainFrame->documentElement().findAll("p").at(0); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("black")); + + QString html8 = "<body><p>some text</p></body>"; + + m_mainFrame->setHtml(html8); + p = m_mainFrame->documentElement().findAll("p").at(0); + + QCOMPARE(p.styleProperty("color"), QLatin1String("")); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("")); +} + +void tst_QWebElement::computedStyle() +{ + QString html = "<body><p>some text</p></body>"; + m_mainFrame->setHtml(html); + + QWebElement p = m_mainFrame->documentElement().findAll("p").at(0); + QCOMPARE(p.computedStyleProperty("cursor"), QLatin1String("auto")); + QVERIFY(!p.computedStyleProperty("cursor").isEmpty()); + QVERIFY(p.styleProperty("cursor").isEmpty()); + + p.setStyleProperty("cursor", "text"); + p.setStyleProperty("color", "red"); + + QCOMPARE(p.computedStyleProperty("cursor"), QLatin1String("text")); + QCOMPARE(p.computedStyleProperty("color"), QLatin1String("rgb(255, 0, 0)")); + QCOMPARE(p.styleProperty("color"), QLatin1String("red")); +} + +void tst_QWebElement::properties() +{ + m_mainFrame->setHtml("<body><form><input type=checkbox id=ourcheckbox checked=true>"); + + QWebElement checkBox = m_mainFrame->findFirstElement("#ourcheckbox"); + QVERIFY(!checkBox.isNull()); + + QVERIFY(checkBox.scriptableProperties().contains("checked")); + + QCOMPARE(checkBox.scriptableProperty("checked"), QVariant(true)); + checkBox.setScriptableProperty("checked", false); + QCOMPARE(checkBox.scriptableProperty("checked"), QVariant(false)); + + QVERIFY(!checkBox.scriptableProperties().contains("non_existant")); + QCOMPARE(checkBox.scriptableProperty("non_existant"), QVariant()); + + checkBox.setScriptableProperty("non_existant", "test"); + + QCOMPARE(checkBox.scriptableProperty("non_existant"), QVariant("test")); + QVERIFY(checkBox.scriptableProperties().contains("non_existant")); + + // removing scriptableProperties is currently not supported. We should look into this + // and consider the option of just allowing through the QtScript API only. +#if 0 + checkBox.setScriptableProperty("non_existant", QVariant()); + + QCOMPARE(checkBox.scriptableProperty("non_existant"), QVariant()); + QVERIFY(!checkBox.scriptableProperties().contains("non_existant")); +#endif +} + +void tst_QWebElement::appendAndPrepend() +{ + QString html = "<body>" + "<p>" + "foo" + "</p>" + "<p>" + "bar" + "</p>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + + QCOMPARE(body.findAll("p").count(), 2); + body.appendInside(body.findFirst("p")); + QCOMPARE(body.findAll("p").count(), 2); + QCOMPARE(body.findFirst("p").toPlainText(), QString("bar")); + QCOMPARE(body.findAll("p").last().toPlainText(), QString("foo")); + + body.appendInside(body.findFirst("p").clone()); + QCOMPARE(body.findAll("p").count(), 3); + QCOMPARE(body.findFirst("p").toPlainText(), QString("bar")); + QCOMPARE(body.findAll("p").last().toPlainText(), QString("bar")); + + body.prependInside(body.findAll("p").at(1).clone()); + QCOMPARE(body.findAll("p").count(), 4); + QCOMPARE(body.findFirst("p").toPlainText(), QString("foo")); + + body.findFirst("p").appendInside("<div>booyakasha</div>"); + QCOMPARE(body.findAll("p div").count(), 1); + QCOMPARE(body.findFirst("p div").toPlainText(), QString("booyakasha")); + + body.findFirst("div").prependInside("<code>yepp</code>"); + QCOMPARE(body.findAll("p div code").count(), 1); + QCOMPARE(body.findFirst("p div code").toPlainText(), QString("yepp")); +} + +void tst_QWebElement::insertBeforeAndAfter() +{ + QString html = "<body>" + "<p>" + "foo" + "</p>" + "<div>" + "yeah" + "</div>" + "<p>" + "bar" + "</p>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + QWebElement div = body.findFirst("div"); + + QCOMPARE(body.findAll("p").count(), 2); + QCOMPARE(body.findAll("div").count(), 1); + + div.prependOutside(body.findAll("p").last().clone()); + QCOMPARE(body.findAll("p").count(), 3); + QCOMPARE(body.findAll("p").at(0).toPlainText(), QString("foo")); + QCOMPARE(body.findAll("p").at(1).toPlainText(), QString("bar")); + QCOMPARE(body.findAll("p").at(2).toPlainText(), QString("bar")); + + div.appendOutside(body.findFirst("p").clone()); + QCOMPARE(body.findAll("p").count(), 4); + QCOMPARE(body.findAll("p").at(0).toPlainText(), QString("foo")); + QCOMPARE(body.findAll("p").at(1).toPlainText(), QString("bar")); + QCOMPARE(body.findAll("p").at(2).toPlainText(), QString("foo")); + QCOMPARE(body.findAll("p").at(3).toPlainText(), QString("bar")); + + div.prependOutside("<span>hey</span>"); + QCOMPARE(body.findAll("span").count(), 1); + + div.appendOutside("<span>there</span>"); + QCOMPARE(body.findAll("span").count(), 2); + QCOMPARE(body.findAll("span").at(0).toPlainText(), QString("hey")); + QCOMPARE(body.findAll("span").at(1).toPlainText(), QString("there")); +} + +void tst_QWebElement::remove() +{ + QString html = "<body>" + "<p>" + "foo" + "</p>" + "<div>" + "<p>yeah</p>" + "</div>" + "<p>" + "bar" + "</p>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + + QCOMPARE(body.findAll("div").count(), 1); + QCOMPARE(body.findAll("p").count(), 3); + + QWebElement div = body.findFirst("div"); + div.takeFromDocument(); + + QCOMPARE(div.isNull(), false); + QCOMPARE(body.findAll("div").count(), 0); + QCOMPARE(body.findAll("p").count(), 2); + + body.appendInside(div); + + QCOMPARE(body.findAll("div").count(), 1); + QCOMPARE(body.findAll("p").count(), 3); +} + +void tst_QWebElement::clear() +{ + QString html = "<body>" + "<p>" + "foo" + "</p>" + "<div>" + "<p>yeah</p>" + "</div>" + "<p>" + "bar" + "</p>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + + QCOMPARE(body.findAll("div").count(), 1); + QCOMPARE(body.findAll("p").count(), 3); + body.findFirst("div").removeChildren(); + QCOMPARE(body.findAll("div").count(), 1); + QCOMPARE(body.findAll("p").count(), 2); +} + + +void tst_QWebElement::replaceWith() +{ + QString html = "<body>" + "<p>" + "foo" + "</p>" + "<div>" + "yeah" + "</div>" + "<p>" + "<span>haba</span>" + "</p>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + + QCOMPARE(body.findAll("div").count(), 1); + QCOMPARE(body.findAll("span").count(), 1); + body.findFirst("div").replace(body.findFirst("span").clone()); + QCOMPARE(body.findAll("div").count(), 0); + QCOMPARE(body.findAll("span").count(), 2); + QCOMPARE(body.findAll("p").count(), 2); + + body.findFirst("span").replace("<p><code>wow</code></p>"); + QCOMPARE(body.findAll("p").count(), 3); + QCOMPARE(body.findAll("p code").count(), 1); + QCOMPARE(body.findFirst("p code").toPlainText(), QString("wow")); +} + +void tst_QWebElement::encloseContentsWith() +{ + QString html = "<body>" + "<div>" + "<i>" + "yeah" + "</i>" + "<i>" + "hello" + "</i>" + "</div>" + "<p>" + "<span>foo</span>" + "<span>bar</span>" + "</p>" + "<u></u>" + "<b></b>" + "<em>hey</em>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + + body.findFirst("p").encloseContentsWith(body.findFirst("b")); + QCOMPARE(body.findAll("p b span").count(), 2); + QCOMPARE(body.findFirst("p b span").toPlainText(), QString("foo")); + + body.findFirst("u").encloseContentsWith("<i></i>"); + QCOMPARE(body.findAll("u i").count(), 1); + QCOMPARE(body.findFirst("u i").toPlainText(), QString()); + + body.findFirst("div").encloseContentsWith("<span></span>"); + QCOMPARE(body.findAll("div span i").count(), 2); + QCOMPARE(body.findFirst("div span i").toPlainText(), QString("yeah")); + + QString snippet = "" + "<table>" + "<tbody>" + "<tr>" + "<td></td>" + "<td></td>" + "</tr>" + "<tr>" + "<td></td>" + "<td></td>" + "<tr>" + "</tbody>" + "</table>"; + + body.findFirst("em").encloseContentsWith(snippet); + QCOMPARE(body.findFirst("em table tbody tr td").toPlainText(), QString("hey")); +} + +void tst_QWebElement::encloseWith() +{ + QString html = "<body>" + "<p>" + "foo" + "</p>" + "<div>" + "yeah" + "</div>" + "<p>" + "<span>bar</span>" + "</p>" + "<em>hey</em>" + "<h1>hello</h1>" + "</body>"; + + m_mainFrame->setHtml(html); + QWebElement body = m_mainFrame->documentElement().findFirst("body"); + + body.findFirst("p").encloseWith("<br>"); + QCOMPARE(body.findAll("br").count(), 0); + + QCOMPARE(body.findAll("div").count(), 1); + body.findFirst("div").encloseWith(body.findFirst("span").clone()); + QCOMPARE(body.findAll("div").count(), 1); + QCOMPARE(body.findAll("span").count(), 2); + QCOMPARE(body.findAll("p").count(), 2); + + body.findFirst("div").encloseWith("<code></code>"); + QCOMPARE(body.findAll("code").count(), 1); + QCOMPARE(body.findAll("code div").count(), 1); + QCOMPARE(body.findFirst("code div").toPlainText(), QString("yeah")); + + QString snippet = "" + "<table>" + "<tbody>" + "<tr>" + "<td></td>" + "<td></td>" + "</tr>" + "<tr>" + "<td></td>" + "<td></td>" + "<tr>" + "</tbody>" + "</table>"; + + body.findFirst("em").encloseWith(snippet); + QCOMPARE(body.findFirst("table tbody tr td em").toPlainText(), QString("hey")); +} + +void tst_QWebElement::nullSelect() +{ + m_mainFrame->setHtml("<body><p>Test"); + + QList<QWebElement> collection = m_mainFrame->findAllElements("invalid{syn(tax;;%#$f223e>>"); + QVERIFY(collection.count() == 0); +} + +void tst_QWebElement::firstChildNextSibling() +{ + m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another commend><table>"); + + QWebElement body = m_mainFrame->findFirstElement("body"); + QVERIFY(!body.isNull()); + QWebElement p = body.firstChild(); + QVERIFY(!p.isNull()); + QCOMPARE(p.tagName(), QString("P")); + QWebElement table = p.nextSibling(); + QVERIFY(!table.isNull()); + QCOMPARE(table.tagName(), QString("TABLE")); + QVERIFY(table.nextSibling().isNull()); +} + +void tst_QWebElement::lastChildPreviousSibling() +{ + m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another commend><table>"); + + QWebElement body = m_mainFrame->findFirstElement("body"); + QVERIFY(!body.isNull()); + QWebElement table = body.lastChild(); + QVERIFY(!table.isNull()); + QCOMPARE(table.tagName(), QString("TABLE")); + QWebElement p = table.previousSibling(); + QVERIFY(!p.isNull()); + QCOMPARE(p.tagName(), QString("P")); + QVERIFY(p.previousSibling().isNull()); +} + +QTEST_MAIN(tst_QWebElement) +#include "tst_qwebelement.moc" diff --git a/WebKit/qt/tests/qwebframe/qwebframe.qrc b/WebKit/qt/tests/qwebframe/qwebframe.qrc index 69e62d9..9615e27 100644 --- a/WebKit/qt/tests/qwebframe/qwebframe.qrc +++ b/WebKit/qt/tests/qwebframe/qwebframe.qrc @@ -1,5 +1,8 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> <file>image.png</file> +<file>style.css</file> +<file>test1.html</file> +<file>test2.html</file> </qresource> </RCC> diff --git a/WebKit/qt/tests/qwebframe/style.css b/WebKit/qt/tests/qwebframe/style.css new file mode 100644 index 0000000..c05b747 --- /dev/null +++ b/WebKit/qt/tests/qwebframe/style.css @@ -0,0 +1 @@ +#idP {color: red !important} diff --git a/WebKit/qt/tests/qwebframe/test1.html b/WebKit/qt/tests/qwebframe/test1.html new file mode 100644 index 0000000..b323f96 --- /dev/null +++ b/WebKit/qt/tests/qwebframe/test1.html @@ -0,0 +1 @@ +<html><body><p>Some text 1</p></body></html> diff --git a/WebKit/qt/tests/qwebframe/test2.html b/WebKit/qt/tests/qwebframe/test2.html new file mode 100644 index 0000000..63ac1f6 --- /dev/null +++ b/WebKit/qt/tests/qwebframe/test2.html @@ -0,0 +1 @@ +<html><body> <p>Some text 2</p></body></html> diff --git a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index d9c97c8..17dea99 100644 --- a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -21,6 +21,7 @@ #include <QtTest/QtTest> #include <qwebpage.h> +#include <qwebelement.h> #include <qwidget.h> #include <qwebview.h> #include <qwebframe.h> @@ -28,8 +29,12 @@ #include <QAbstractItemView> #include <QApplication> #include <QComboBox> +#include <QPicture> #include <QRegExp> #include <QNetworkRequest> +#include <QNetworkReply> +#include <qsslerror.h> + //TESTED_CLASS= //TESTED_FILES= @@ -570,7 +575,9 @@ private slots: void typeConversion(); void symmetricUrl(); void progressSignal(); + void urlChange(); void domCycles(); + void requestedUrl(); void setHtml(); void setHtmlWithResource(); void ipv6HostEncoding(); @@ -579,6 +586,13 @@ private slots: void hitTestContent(); void jsByteArray(); void ownership(); + void nullValue(); + void baseUrl_data(); + void baseUrl(); + void hasSetFocus(); + void render(); + void scrollPosition(); + private: QString evalJS(const QString&s) { // Convert an undefined return variant to the string "undefined" @@ -2125,6 +2139,26 @@ void tst_QWebFrame::progressSignal() QCOMPARE(progressSpy.last().first().toInt(), 100); } +void tst_QWebFrame::urlChange() +{ + QSignalSpy urlSpy(m_page->mainFrame(), SIGNAL(urlChanged(QUrl))); + + QUrl dataUrl("data:text/html,<h1>Test"); + m_view->setUrl(dataUrl); + + ::waitForSignal(m_page->mainFrame(), SIGNAL(urlChanged(QUrl))); + + QCOMPARE(urlSpy.size(), 1); + + QUrl dataUrl2("data:text/html,<html><head><title>title</title></head><body><h1>Test</body></html>"); + m_view->setUrl(dataUrl2); + + ::waitForSignal(m_page->mainFrame(), SIGNAL(urlChanged(QUrl))); + + QCOMPARE(urlSpy.size(), 2); +} + + void tst_QWebFrame::domCycles() { m_view->setHtml("<html><body>"); @@ -2132,9 +2166,120 @@ void tst_QWebFrame::domCycles() QVERIFY(v.type() == QVariant::Map); } +class FakeReply : public QNetworkReply { + Q_OBJECT + +public: + FakeReply(const QNetworkRequest& request, QObject* parent = 0) + : QNetworkReply(parent) + { + setOperation(QNetworkAccessManager::GetOperation); + setRequest(request); + if (request.url() == QUrl("qrc:/test1.html")) { + setHeader(QNetworkRequest::LocationHeader, QString("qrc:/test2.html")); + setAttribute(QNetworkRequest::RedirectionTargetAttribute, QUrl("qrc:/test2.html")); + } else if (request.url() == QUrl("qrc:/fake-ssl-error.html")) + setError(QNetworkReply::SslHandshakeFailedError, tr("Fake error !")); // force a ssl error + else if (request.url() == QUrl("http://abcdef.abcdef/")) + setError(QNetworkReply::HostNotFoundError, tr("Invalid URL")); + + open(QIODevice::ReadOnly); + QTimer::singleShot(0, this, SLOT(timeout())); + } + ~FakeReply() + { + close(); + } + virtual void abort() {} + virtual void close() {} + +protected: + qint64 readData(char*, qint64) + { + return 0; + } + +private slots: + void timeout() + { + if (request().url() == QUrl("qrc://test1.html")) + emit error(this->error()); + else if (request().url() == QUrl("http://abcdef.abcdef/")) + emit metaDataChanged(); + else if (request().url() == QUrl("qrc:/fake-ssl-error.html")) + return; + + emit readyRead(); + emit finished(); + } +}; + +class FakeNetworkManager : public QNetworkAccessManager { + Q_OBJECT + +public: + FakeNetworkManager(QObject* parent) : QNetworkAccessManager(parent) { } + +protected: + virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData) + { + QString url = request.url().toString(); + if (op == QNetworkAccessManager::GetOperation) + if (url == "qrc:/test1.html" || url == "http://abcdef.abcdef/") + return new FakeReply(request, this); + else if (url == "qrc:/fake-ssl-error.html") { + FakeReply* reply = new FakeReply(request, this); + QList<QSslError> errors; + emit sslErrors(reply, errors << QSslError(QSslError::UnspecifiedError)); + return reply; + } + + return QNetworkAccessManager::createRequest(op, request, outgoingData); + } +}; + +void tst_QWebFrame::requestedUrl() +{ + QWebPage page; + QWebFrame* frame = page.mainFrame(); + + // in few seconds, the image should be completely loaded + QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); + FakeNetworkManager* networkManager = new FakeNetworkManager(&page); + page.setNetworkAccessManager(networkManager); + + frame->setUrl(QUrl("qrc:/test1.html")); + QTest::qWait(200); + QCOMPARE(spy.count(), 1); + QCOMPARE(frame->requestedUrl(), QUrl("qrc:/test1.html")); + QCOMPARE(frame->url(), QUrl("qrc:/test2.html")); + + frame->setUrl(QUrl("qrc:/non-existent.html")); + QTest::qWait(200); + QCOMPARE(spy.count(), 2); + QCOMPARE(frame->requestedUrl(), QUrl("qrc:/non-existent.html")); + QCOMPARE(frame->url(), QUrl("qrc:/non-existent.html")); + + frame->setUrl(QUrl("http://abcdef.abcdef")); + QTest::qWait(200); + QCOMPARE(spy.count(), 3); + QCOMPARE(frame->requestedUrl(), QUrl("http://abcdef.abcdef/")); + QCOMPARE(frame->url(), QUrl("http://abcdef.abcdef/")); + + qRegisterMetaType<QList<QSslError> >("QList<QSslError>"); + qRegisterMetaType<QNetworkReply* >("QNetworkReply*"); + + QSignalSpy spy2(page.networkAccessManager(), SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&))); + frame->setUrl(QUrl("qrc:/fake-ssl-error.html")); + QTest::qWait(200); + QCOMPARE(spy2.count(), 1); + QCOMPARE(frame->requestedUrl(), QUrl("qrc:/fake-ssl-error.html")); + QCOMPARE(frame->url(), QUrl("qrc:/fake-ssl-error.html")); +} + void tst_QWebFrame::setHtml() { - QString html("<html><body><p>hello world</p></body></html>"); + QString html("<html><head></head><body><p>hello world</p></body></html>"); m_view->page()->mainFrame()->setHtml(html); QCOMPARE(m_view->page()->mainFrame()->toHtml(), html); } @@ -2155,6 +2300,24 @@ void tst_QWebFrame::setHtmlWithResource() QCOMPARE(frame->evaluateJavaScript("document.images.length").toInt(), 1); QCOMPARE(frame->evaluateJavaScript("document.images[0].width").toInt(), 128); QCOMPARE(frame->evaluateJavaScript("document.images[0].height").toInt(), 128); + + QString html2 = + "<html>" + "<head>" + "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />" + "</head>" + "<body>" + "<p id='idP'>some text</p>" + "</body>" + "</html>"; + + // in few seconds, the CSS should be completey loaded + frame->setHtml(html2); + QTest::qWait(200); + QCOMPARE(spy.size(), 2); + + QWebElement p = frame->documentElement().findAll("p").at(0); + QCOMPARE(p.styleProperty("color", QWebElement::RespectCascadingStyles), QLatin1String("red")); } class TestNetworkManager : public QNetworkAccessManager @@ -2285,7 +2448,8 @@ void tst_QWebFrame::hitTestContent() page.setViewportSize(QSize(200, 0)); //no height so link is not visible QWebHitTestResult result = frame->hitTestContent(QPoint(10, 100)); QCOMPARE(result.linkText(), QString("link text")); - QCOMPARE(result.linkTarget(), QString("_foo")); + QWebElement link = result.linkElement(); + QCOMPARE(link.attribute("target"), QString("_foo")); } void tst_QWebFrame::jsByteArray() @@ -2365,5 +2529,145 @@ void tst_QWebFrame::ownership() } } +void tst_QWebFrame::nullValue() +{ + QVariant v = m_view->page()->mainFrame()->evaluateJavaScript("null"); + QVERIFY(v.isNull()); +} + +void tst_QWebFrame::baseUrl_data() +{ + QTest::addColumn<QString>("html"); + QTest::addColumn<QUrl>("loadUrl"); + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QUrl>("baseUrl"); + + QTest::newRow("null") << QString() << QUrl() + << QUrl("about:blank") << QUrl("about:blank"); + + QTest::newRow("foo") << QString() << QUrl("http://foobar.baz/") + << QUrl("http://foobar.baz/") << QUrl("http://foobar.baz/"); + + QString html = "<html>" + "<head>" + "<base href=\"http://foobaz.bar/\" />" + "</head>" + "</html>"; + QTest::newRow("customBaseUrl") << html << QUrl("http://foobar.baz/") + << QUrl("http://foobar.baz/") << QUrl("http://foobaz.bar/"); +} + +void tst_QWebFrame::baseUrl() +{ + QFETCH(QString, html); + QFETCH(QUrl, loadUrl); + QFETCH(QUrl, url); + QFETCH(QUrl, baseUrl); + + m_page->mainFrame()->setHtml(html, loadUrl); + QCOMPARE(m_page->mainFrame()->url(), url); + QCOMPARE(m_page->mainFrame()->baseUrl(), baseUrl); +} + +void tst_QWebFrame::hasSetFocus() +{ + QString html("<html><body><p>top</p>" \ + "<iframe width='80%' height='30%'/>" \ + "</body></html>"); + + QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool))); + m_page->mainFrame()->setHtml(html); + + QTest::qWait(200); + QCOMPARE(loadSpy.size(), 1); + + QList<QWebFrame*> children = m_page->mainFrame()->childFrames(); + QWebFrame* frame = children.at(0); + QString innerHtml("<html><body><p>another iframe</p>" \ + "<iframe width='80%' height='30%'/>" \ + "</body></html>"); + frame->setHtml(innerHtml); + + QTest::qWait(200); + QCOMPARE(loadSpy.size(), 2); + + m_page->mainFrame()->setFocus(); + QVERIFY(m_page->mainFrame()->hasFocus()); + + for (int i = 0; i < children.size(); ++i) { + children.at(i)->setFocus(); + QVERIFY(children.at(i)->hasFocus()); + QVERIFY(!m_page->mainFrame()->hasFocus()); + } + + m_page->mainFrame()->setFocus(); + QVERIFY(m_page->mainFrame()->hasFocus()); +} + +void tst_QWebFrame::render() +{ + QString html("<html>" \ + "<head><style>" \ + "body, iframe { margin: 0px; border: none; }" \ + "</style></head>" \ + "<body><iframe width='100px' height='100px'/></body>" \ + "</html>"); + + QWebPage page; + page.mainFrame()->setHtml(html); + + QList<QWebFrame*> frames = page.mainFrame()->childFrames(); + QWebFrame *frame = frames.at(0); + QString innerHtml("<body style='margin: 0px;'><img src='qrc:/image.png'/></body>"); + frame->setHtml(innerHtml); + + QPicture picture; + + // render clipping to Viewport + frame->setClipRenderToViewport(true); + QPainter painter1(&picture); + frame->render(&painter1); + painter1.end(); + + QSize size = page.mainFrame()->contentsSize(); + page.setViewportSize(size); + QCOMPARE(size.width(), picture.boundingRect().width()); // 100px + QCOMPARE(size.height(), picture.boundingRect().height()); // 100px + + // render without clipping to Viewport + frame->setClipRenderToViewport(false); + QPainter painter2(&picture); + frame->render(&painter2); + painter2.end(); + + QImage resource(":/image.png"); + QCOMPARE(resource.width(), picture.boundingRect().width()); // resource width: 128px + QCOMPARE(resource.height(), picture.boundingRect().height()); // resource height: 128px +} + +void tst_QWebFrame::scrollPosition() +{ + // enlarged image in a small viewport, to provoke the scrollbars to appear + QString html("<html><body><img src='qrc:/image.png' height=500 width=500/></body></html>"); + + QWebPage page; + page.setViewportSize(QSize(200, 200)); + + QWebFrame* frame = page.mainFrame(); + frame->setHtml(html); + frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); + frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); + + // try to set the scroll offset programmatically + frame->setScrollPosition(QPoint(23, 29)); + QCOMPARE(frame->scrollPosition().x(), 23); + QCOMPARE(frame->scrollPosition().y(), 29); + + int x = frame->evaluateJavaScript("window.scrollX").toInt(); + int y = frame->evaluateJavaScript("window.scrollY").toInt(); + QCOMPARE(x, 23); + QCOMPARE(y, 29); +} + QTEST_MAIN(tst_QWebFrame) #include "tst_qwebframe.moc" diff --git a/WebKit/qt/tests/qwebhistory/data/page1.html b/WebKit/qt/tests/qwebhistory/data/page1.html new file mode 100644 index 0000000..82fa4af --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/data/page1.html @@ -0,0 +1 @@ +<title>page1</title><body><h1>page1</h1></body> diff --git a/WebKit/qt/tests/qwebhistory/data/page2.html b/WebKit/qt/tests/qwebhistory/data/page2.html new file mode 100644 index 0000000..5307bdc --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/data/page2.html @@ -0,0 +1 @@ +<title>page2</title><body><h1>page2</h1></body> diff --git a/WebKit/qt/tests/qwebhistory/data/page3.html b/WebKit/qt/tests/qwebhistory/data/page3.html new file mode 100644 index 0000000..4e5547c --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/data/page3.html @@ -0,0 +1 @@ +<title>page3</title><body><h1>page3</h1></body> diff --git a/WebKit/qt/tests/qwebhistory/data/page4.html b/WebKit/qt/tests/qwebhistory/data/page4.html new file mode 100644 index 0000000..3c57aed --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/data/page4.html @@ -0,0 +1 @@ +<title>page4</title><body><h1>page4</h1></body> diff --git a/WebKit/qt/tests/qwebhistory/data/page5.html b/WebKit/qt/tests/qwebhistory/data/page5.html new file mode 100644 index 0000000..8593552 --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/data/page5.html @@ -0,0 +1 @@ +<title>page5</title><body><h1>page5</h1></body> diff --git a/WebKit/qt/tests/qwebhistory/data/page6.html b/WebKit/qt/tests/qwebhistory/data/page6.html new file mode 100644 index 0000000..c5bbc6f --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/data/page6.html @@ -0,0 +1 @@ +<title>page6</title><body><h1>page6</h1></body> diff --git a/WebKit/qt/tests/qwebhistory/qwebhistory.pro b/WebKit/qt/tests/qwebhistory/qwebhistory.pro new file mode 100644 index 0000000..fd1074c --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/qwebhistory.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = tst_qwebhistory +include(../../../../WebKit.pri) +SOURCES += tst_qwebhistory.cpp +RESOURCES += tst_qwebhistory.qrc +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp b/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp new file mode 100644 index 0000000..5b55613 --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp @@ -0,0 +1,326 @@ +/* + Copyright (C) 2008 Holger Hans Peter Freyther + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <QtTest/QtTest> + +#include "qwebpage.h" +#include "qwebview.h" +#include "qwebframe.h" +#include "qwebhistory.h" +#include "qdebug.h" + +class tst_QWebHistory : public QObject +{ + Q_OBJECT + +public: + tst_QWebHistory(); + virtual ~tst_QWebHistory(); + +protected : + void loadPage(int nr) + { + frame->load(QUrl("qrc:/data/page" + QString::number(nr) + ".html")); + waitForLoadFinished.exec(); + } + +public slots: + void init(); + void cleanup(); + +private slots: + void title(); + void count(); + void back(); + void forward(); + void itemAt(); + void goToItem(); + void items(); + void serialize_1(); //QWebHistory countity + void serialize_2(); //QWebHistory index + void serialize_3(); //QWebHistoryItem + void saveAndRestore_1(); //simple checks saveState and restoreState + void saveAndRestore_2(); //bad parameters saveState and restoreState + void saveAndRestore_3(); //try use different version + +private: + QWebPage* page; + QWebFrame* frame; + QWebHistory* hist; + QEventLoop waitForLoadFinished; //operation on history are asynchronous! + int histsize; +}; + +tst_QWebHistory::tst_QWebHistory() +{ +} + +tst_QWebHistory::~tst_QWebHistory() +{ +} + +void tst_QWebHistory::init() +{ + page = new QWebPage(this); + frame = page->mainFrame(); + connect(page, SIGNAL(loadFinished(bool)), &waitForLoadFinished, SLOT(quit())); + + for (int i = 1;i < 6;i++) { + loadPage(i); + } + hist = page->history(); + histsize = 5; +} + +void tst_QWebHistory::cleanup() +{ + delete page; +} + +/** + * Check QWebHistoryItem::title() method + */ +void tst_QWebHistory::title() +{ + QCOMPARE(hist->currentItem().title(), QString("page5")); +} + +/** + * Check QWebHistory::count() method + */ +void tst_QWebHistory::count() +{ + QCOMPARE(hist->count(), histsize); +} + +/** + * Check QWebHistory::back() method + */ +void tst_QWebHistory::back() +{ + for (int i = histsize;i > 1;i--) { + QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(i)); + hist->back(); + waitForLoadFinished.exec(); + } +} + +/** + * Check QWebHistory::forward() method + */ +void tst_QWebHistory::forward() +{ + //rewind history :-) + while (hist->canGoBack()) { + hist->back(); + waitForLoadFinished.exec(); + } + + for (int i = 1;i < histsize;i++) { + QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(i)); + hist->forward(); + waitForLoadFinished.exec(); + } +} + +/** + * Check QWebHistory::itemAt() method + */ +void tst_QWebHistory::itemAt() +{ + for (int i = 1;i < histsize;i++) { + QCOMPARE(hist->itemAt(i - 1).title(), QString("page") + QString::number(i)); + QVERIFY(hist->itemAt(i - 1).isValid()); + } + //check out of range values + QVERIFY(!hist->itemAt(-1).isValid()); + QVERIFY(!hist->itemAt(histsize).isValid()); +} + +/** + * Check QWebHistory::goToItem() method + */ +void tst_QWebHistory::goToItem() +{ + QWebHistoryItem current = hist->currentItem(); + hist->back(); + waitForLoadFinished.exec(); + hist->back(); + waitForLoadFinished.exec(); + QVERIFY(hist->currentItem().title() != current.title()); + hist->goToItem(current); + waitForLoadFinished.exec(); + QCOMPARE(hist->currentItem().title(), current.title()); +} + +/** + * Check QWebHistory::items() method + */ +void tst_QWebHistory::items() +{ + QList<QWebHistoryItem> items = hist->items(); + //check count + QCOMPARE(histsize, items.count()); + + //check order + for (int i = 1;i <= histsize;i++) { + QCOMPARE(items.at(i - 1).title(), QString("page") + QString::number(i)); + } +} + +/** + * Check history state after serialization (pickle, persistent..) method + * Checks history size, history order + */ +void tst_QWebHistory::serialize_1() +{ + QByteArray tmp; //buffer + QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved + QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded + + save << *hist; + QVERIFY(save.status() == QDataStream::Ok); + QCOMPARE(hist->count(), histsize); + + //check size of history + //load next page to find differences + loadPage(6); + QCOMPARE(hist->count(), histsize + 1); + load >> *hist; + QVERIFY(load.status() == QDataStream::Ok); + QCOMPARE(hist->count(), histsize); + + //check order of historyItems + QList<QWebHistoryItem> items = hist->items(); + for (int i = 1;i <= histsize;i++) { + QCOMPARE(items.at(i - 1).title(), QString("page") + QString::number(i)); + } +} + +/** + * Check history state after serialization (pickle, persistent..) method + * Checks history currentIndex value + */ +void tst_QWebHistory::serialize_2() +{ + QByteArray tmp; //buffer + QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved + QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded + + int oldCurrentIndex = hist->currentItemIndex(); + + hist->back(); + waitForLoadFinished.exec(); + hist->back(); + waitForLoadFinished.exec(); + //check if current index was changed (make sure that it is not last item) + QVERIFY(hist->currentItemIndex() != oldCurrentIndex); + //save current index + oldCurrentIndex = hist->currentItemIndex(); + + save << *hist; + QVERIFY(save.status() == QDataStream::Ok); + load >> *hist; + QVERIFY(load.status() == QDataStream::Ok); + + //check current index + QCOMPARE(hist->currentItemIndex(), oldCurrentIndex); +} + +/** + * Check history state after serialization (pickle, persistent..) method + * Checks QWebHistoryItem public property after serialization + */ +void tst_QWebHistory::serialize_3() +{ + QByteArray tmp; //buffer + QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved + QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded + + //prepare two different history items + QWebHistoryItem a = hist->currentItem(); + a.setUserData("A - user data"); + + //check properties BEFORE serialization + QString title(a.title()); + QDateTime lastVisited(a.lastVisited()); + QUrl originalUrl(a.originalUrl()); + QUrl url(a.url()); + QVariant userData(a.userData()); + + save << *hist; + QVERIFY(save.status() == QDataStream::Ok); + QVERIFY(!load.atEnd()); + hist->clear(); + QVERIFY(hist->count() == 1); + load >> *hist; + QVERIFY(load.status() == QDataStream::Ok); + QWebHistoryItem b = hist->currentItem(); + + //check properties AFTER serialization + QCOMPARE(b.title(), title); + QCOMPARE(b.lastVisited(), lastVisited); + QCOMPARE(b.originalUrl(), originalUrl); + QCOMPARE(b.url(), url); + QCOMPARE(b.userData(), userData); + + //Check if all data was read + QVERIFY(load.atEnd()); +} + +/** Simple checks should be a bit redundant to streaming operators */ +void tst_QWebHistory::saveAndRestore_1() +{ + hist->back(); + waitForLoadFinished.exec(); + QByteArray buffer(hist->saveState()); + hist->clear(); + QVERIFY(hist->count() == 1); + hist->restoreState(buffer); + + //check only few values, do not make full test + //because most of the code is shared with streaming operators + //and these are checked before + QCOMPARE(hist->count(), histsize); + QCOMPARE(hist->currentItemIndex(), histsize - 2); + QCOMPARE(hist->itemAt(0).title(), QString("page1")); + QCOMPARE(hist->itemAt(histsize - 1).title(), QString("page") + QString::number(histsize)); +} + +/** Check returns value if there are bad parameters. Actually, result + * is no so importent. The test shouldn't crash :-) */ +void tst_QWebHistory::saveAndRestore_2() +{ + QByteArray buffer; + hist->restoreState(buffer); + QVERIFY(hist->count() == 1); + QVERIFY(hist->itemAt(0).isValid()); +} + +/** Try to use bad version value */ +void tst_QWebHistory::saveAndRestore_3() +{ + QByteArray tmp = hist->saveState((QWebHistory::HistoryStateVersion)29999); + QVERIFY(hist->saveState((QWebHistory::HistoryStateVersion)29999).isEmpty()); + QVERIFY(hist->count() == histsize); + QVERIFY(hist->itemAt(3).isValid()); +} + +QTEST_MAIN(tst_QWebHistory) +#include "tst_qwebhistory.moc" diff --git a/WebKit/qt/tests/qwebhistory/tst_qwebhistory.qrc b/WebKit/qt/tests/qwebhistory/tst_qwebhistory.qrc new file mode 100644 index 0000000..7c5ff0e --- /dev/null +++ b/WebKit/qt/tests/qwebhistory/tst_qwebhistory.qrc @@ -0,0 +1,11 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>data/page1.html</file> + <file>data/page2.html</file> + <file>data/page3.html</file> + <file>data/page4.html</file> + <file>data/page5.html</file> + <file>data/page6.html</file> +</qresource> +</RCC> + diff --git a/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro b/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro new file mode 100644 index 0000000..af3b348 --- /dev/null +++ b/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = tst_qwebhistoryinterface +include(../../../../WebKit.pri) +SOURCES += tst_qwebhistoryinterface.cpp +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp b/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp new file mode 100644 index 0000000..435cada --- /dev/null +++ b/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp @@ -0,0 +1,94 @@ +/* + Copyright (C) 2008 Holger Hans Peter Freyther + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include <QtTest/QtTest> + +#include <qwebpage.h> +#include <qwebview.h> +#include <qwebframe.h> +#include <qwebhistoryinterface.h> +#include <QDebug> + +class tst_QWebHistoryInterface : public QObject +{ + Q_OBJECT + +public: + tst_QWebHistoryInterface(); + virtual ~tst_QWebHistoryInterface(); + +public slots: + void init(); + void cleanup(); + +private slots: + void visitedLinks(); + +private: + + +private: + QWebView* m_view; + QWebPage* m_page; +}; + +tst_QWebHistoryInterface::tst_QWebHistoryInterface() +{ +} + +tst_QWebHistoryInterface::~tst_QWebHistoryInterface() +{ +} + +void tst_QWebHistoryInterface::init() +{ + m_view = new QWebView(); + m_page = m_view->page(); +} + +void tst_QWebHistoryInterface::cleanup() +{ + delete m_view; +} + +class FakeHistoryImplementation : public QWebHistoryInterface { +public: + void addHistoryEntry(const QString&) {} + bool historyContains(const QString& url) const { + return url == QLatin1String("http://www.trolltech.com/"); + } +}; + + +/* + * Test that visited links are properly colored. http://www.trolltech.com is marked + * as visited, so the below website should have exactly one element in the a:visited + * state. + */ +void tst_QWebHistoryInterface::visitedLinks() +{ + QWebHistoryInterface::setDefaultInterface(new FakeHistoryImplementation); + m_view->setHtml("<html><body><a href='http://www.trolltech.com'>Trolltech</a></body></html>"); + QCOMPARE(m_page->mainFrame()->evaluateJavaScript("document.querySelectorAll(':visited').length;").toString(), + QString::fromLatin1("1")); +} + +QTEST_MAIN(tst_QWebHistoryInterface) +#include "tst_qwebhistoryinterface.moc" diff --git a/WebKit/qt/tests/qwebpage/frametest/frame_a.html b/WebKit/qt/tests/qwebpage/frametest/frame_a.html new file mode 100644 index 0000000..9ff68f1 --- /dev/null +++ b/WebKit/qt/tests/qwebpage/frametest/frame_a.html @@ -0,0 +1,2 @@ +<a href="http://google.com" target="frame_b"><img src="" width=100 height=100 alt="Google"></a> +<a href="http://yahoo.com" target="frame_b"><img src="" width=100 height=100 alt="Yahoo"></a> diff --git a/WebKit/qt/tests/qwebpage/frametest/iframe.html b/WebKit/qt/tests/qwebpage/frametest/iframe.html new file mode 100644 index 0000000..f17027c --- /dev/null +++ b/WebKit/qt/tests/qwebpage/frametest/iframe.html @@ -0,0 +1,6 @@ +<html> +<body> +<p>top</p> +<iframe src="iframe2.html" width="80%" height="30%"/> +</body> +</html> diff --git a/WebKit/qt/tests/qwebpage/frametest/iframe2.html b/WebKit/qt/tests/qwebpage/frametest/iframe2.html new file mode 100644 index 0000000..5017435 --- /dev/null +++ b/WebKit/qt/tests/qwebpage/frametest/iframe2.html @@ -0,0 +1,7 @@ +<html> +<body> +<p>another iframe</p> +<iframe src="iframe3.html" width="80%" height="30%"></iframe> +</body> +</html> + diff --git a/WebKit/qt/tests/qwebpage/frametest/iframe3.html b/WebKit/qt/tests/qwebpage/frametest/iframe3.html new file mode 100644 index 0000000..ed6ac5b --- /dev/null +++ b/WebKit/qt/tests/qwebpage/frametest/iframe3.html @@ -0,0 +1,5 @@ +<html> +<body> +<p>inner</p> +</body> +</html> diff --git a/WebKit/qt/tests/qwebpage/frametest/index.html b/WebKit/qt/tests/qwebpage/frametest/index.html new file mode 100644 index 0000000..c53ad09 --- /dev/null +++ b/WebKit/qt/tests/qwebpage/frametest/index.html @@ -0,0 +1,4 @@ +<frameset cols="25%,75%"> + <frame src="frame_a.html" name="frame_a"> + <frame src="frame_b.html" name="frame_b"> +</frameset> diff --git a/WebKit/qt/tests/qwebpage/qwebpage.pro b/WebKit/qt/tests/qwebpage/qwebpage.pro index bbd98c6..2f3a108 100644 --- a/WebKit/qt/tests/qwebpage/qwebpage.pro +++ b/WebKit/qt/tests/qwebpage/qwebpage.pro @@ -2,5 +2,6 @@ TEMPLATE = app TARGET = tst_qwebpage include(../../../../WebKit.pri) SOURCES += tst_qwebpage.cpp +RESOURCES += tst_qwebpage.qrc QT += testlib network QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index d85e880..966f049 100644 --- a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -92,6 +92,7 @@ private slots: void cleanupTestCase(); void acceptNavigationRequest(); + void infiniteLoopJS(); void loadFinished(); void acceptNavigationRequestWithNewWindow(); void userStyleSheet(); @@ -105,6 +106,10 @@ private slots: void cursorMovements(); void textSelection(); void textEditing(); + void backActionUpdate(); + void frameAt(); + void requestCache(); + void protectBindingsRuntimeObjectsFromCollector(); private: @@ -189,6 +194,26 @@ void tst_QWebPage::acceptNavigationRequest() m_view->setPage(0); } +class JSTestPage : public QWebPage +{ +Q_OBJECT +public: + JSTestPage(QObject* parent = 0) + : QWebPage(parent) {} + +public slots: + bool shouldInterruptJavaScript() { + return true; + } +}; + +void tst_QWebPage::infiniteLoopJS() +{ + JSTestPage* newPage = new JSTestPage(m_view); + m_view->setPage(newPage); + m_view->setHtml(QString("<html><bodytest</body></html>"), QUrl()); + m_view->page()->mainFrame()->evaluateJavaScript("var run = true;var a = 1;while(run){a++;}"); +} void tst_QWebPage::loadFinished() { @@ -832,7 +857,7 @@ void tst_QWebPage::cursorMovements() // cursor will be before the word "be" page->triggerAction(QWebPage::MoveToStartOfBlock); QVERIFY(page->isSelectionCollapsed()); - QCOMPARE(page->selectionStartOffset(), 2); + QCOMPARE(page->selectionStartOffset(), 0); // cursor will be after the word "you!" page->triggerAction(QWebPage::MoveToEndOfBlock); @@ -870,14 +895,6 @@ void tst_QWebPage::textSelection() "<p>May the source<br/>be with you!</p></body></html>"); page->mainFrame()->setHtml(content); - // this will select the first paragraph - QString script = "var range = document.createRange(); " \ - "var node = document.getElementById(\"one\"); " \ - "range.selectNode(node); " \ - "getSelection().addRange(range);"; - page->mainFrame()->evaluateJavaScript(script); - QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox")); - // these actions must exist QVERIFY(page->action(QWebPage::SelectAll) != 0); QVERIFY(page->action(QWebPage::SelectNextChar) != 0); @@ -893,7 +910,8 @@ void tst_QWebPage::textSelection() QVERIFY(page->action(QWebPage::SelectStartOfDocument) != 0); QVERIFY(page->action(QWebPage::SelectEndOfDocument) != 0); - // right now they are disabled because contentEditable is false + // right now they are disabled because contentEditable is false and + // there isn't an existing selection to modify QCOMPARE(page->action(QWebPage::SelectNextChar)->isEnabled(), false); QCOMPARE(page->action(QWebPage::SelectPreviousChar)->isEnabled(), false); QCOMPARE(page->action(QWebPage::SelectNextWord)->isEnabled(), false); @@ -910,11 +928,37 @@ void tst_QWebPage::textSelection() // ..but SelectAll is awalys enabled QCOMPARE(page->action(QWebPage::SelectAll)->isEnabled(), true); + // this will select the first paragraph + QString selectScript = "var range = document.createRange(); " \ + "var node = document.getElementById(\"one\"); " \ + "range.selectNode(node); " \ + "getSelection().addRange(range);"; + page->mainFrame()->evaluateJavaScript(selectScript); + QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox")); + + // here the actions are enabled after a selection has been created + QCOMPARE(page->action(QWebPage::SelectNextChar)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectPreviousChar)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectNextWord)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectPreviousWord)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectNextLine)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectPreviousLine)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectStartOfLine)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectEndOfLine)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectStartOfBlock)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectEndOfBlock)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectStartOfDocument)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::SelectEndOfDocument)->isEnabled(), true); + // make it editable before navigating the cursor page->setContentEditable(true); + // cursor will be before the word "The", this makes sure there is a charet + page->triggerAction(QWebPage::MoveToStartOfDocument); + QVERIFY(page->isSelectionCollapsed()); + QCOMPARE(page->selectionStartOffset(), 0); + // here the actions are enabled after contentEditable is true - QCOMPARE(page->action(QWebPage::SelectAll)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SelectNextChar)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SelectPreviousChar)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SelectNextWord)->isEnabled(), true); @@ -939,15 +983,10 @@ void tst_QWebPage::textEditing() "<p>May the source<br/>be with you!</p></body></html>"); page->mainFrame()->setHtml(content); - // this will select the first paragraph - QString script = "var range = document.createRange(); " \ - "var node = document.getElementById(\"one\"); " \ - "range.selectNode(node); " \ - "getSelection().addRange(range);"; - page->mainFrame()->evaluateJavaScript(script); - QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox")); - // these actions must exist + QVERIFY(page->action(QWebPage::Cut) != 0); + QVERIFY(page->action(QWebPage::Copy) != 0); + QVERIFY(page->action(QWebPage::Paste) != 0); QVERIFY(page->action(QWebPage::DeleteStartOfWord) != 0); QVERIFY(page->action(QWebPage::DeleteEndOfWord) != 0); QVERIFY(page->action(QWebPage::SetTextDirectionDefault) != 0); @@ -958,8 +997,23 @@ void tst_QWebPage::textEditing() QVERIFY(page->action(QWebPage::ToggleUnderline) != 0); QVERIFY(page->action(QWebPage::InsertParagraphSeparator) != 0); QVERIFY(page->action(QWebPage::InsertLineSeparator) != 0); + QVERIFY(page->action(QWebPage::PasteAndMatchStyle) != 0); + QVERIFY(page->action(QWebPage::RemoveFormat) != 0); + QVERIFY(page->action(QWebPage::ToggleStrikethrough) != 0); + QVERIFY(page->action(QWebPage::ToggleSubscript) != 0); + QVERIFY(page->action(QWebPage::ToggleSuperscript) != 0); + QVERIFY(page->action(QWebPage::InsertUnorderedList) != 0); + QVERIFY(page->action(QWebPage::InsertOrderedList) != 0); + QVERIFY(page->action(QWebPage::Indent) != 0); + QVERIFY(page->action(QWebPage::Outdent) != 0); + QVERIFY(page->action(QWebPage::AlignCenter) != 0); + QVERIFY(page->action(QWebPage::AlignJustified) != 0); + QVERIFY(page->action(QWebPage::AlignLeft) != 0); + QVERIFY(page->action(QWebPage::AlignRight) != 0); // right now they are disabled because contentEditable is false + QCOMPARE(page->action(QWebPage::Cut)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::Paste)->isEnabled(), false); QCOMPARE(page->action(QWebPage::DeleteStartOfWord)->isEnabled(), false); QCOMPARE(page->action(QWebPage::DeleteEndOfWord)->isEnabled(), false); QCOMPARE(page->action(QWebPage::SetTextDirectionDefault)->isEnabled(), false); @@ -970,11 +1024,39 @@ void tst_QWebPage::textEditing() QCOMPARE(page->action(QWebPage::ToggleUnderline)->isEnabled(), false); QCOMPARE(page->action(QWebPage::InsertParagraphSeparator)->isEnabled(), false); QCOMPARE(page->action(QWebPage::InsertLineSeparator)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::PasteAndMatchStyle)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::RemoveFormat)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::ToggleStrikethrough)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::ToggleSubscript)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::ToggleSuperscript)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::InsertUnorderedList)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::InsertOrderedList)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::Indent)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::Outdent)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::AlignCenter)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::AlignJustified)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::AlignLeft)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::AlignRight)->isEnabled(), false); + + // Select everything + page->triggerAction(QWebPage::SelectAll); + + // make sure it is enabled since there is a selection + QCOMPARE(page->action(QWebPage::Copy)->isEnabled(), true); // make it editable before navigating the cursor page->setContentEditable(true); + // clear the selection + page->triggerAction(QWebPage::MoveToStartOfDocument); + QVERIFY(page->isSelectionCollapsed()); + QCOMPARE(page->selectionStartOffset(), 0); + + // make sure it is disabled since there isn't a selection + QCOMPARE(page->action(QWebPage::Copy)->isEnabled(), false); + // here the actions are enabled after contentEditable is true + QCOMPARE(page->action(QWebPage::Paste)->isEnabled(), true); QCOMPARE(page->action(QWebPage::DeleteStartOfWord)->isEnabled(), true); QCOMPARE(page->action(QWebPage::DeleteEndOfWord)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SetTextDirectionDefault)->isEnabled(), true); @@ -985,10 +1067,128 @@ void tst_QWebPage::textEditing() QCOMPARE(page->action(QWebPage::ToggleUnderline)->isEnabled(), true); QCOMPARE(page->action(QWebPage::InsertParagraphSeparator)->isEnabled(), true); QCOMPARE(page->action(QWebPage::InsertLineSeparator)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::PasteAndMatchStyle)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::ToggleStrikethrough)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::ToggleSubscript)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::ToggleSuperscript)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::InsertUnorderedList)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::InsertOrderedList)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::Indent)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::Outdent)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::AlignCenter)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::AlignJustified)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::AlignLeft)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::AlignRight)->isEnabled(), true); + + // make sure these are disabled since there isn't a selection + QCOMPARE(page->action(QWebPage::Cut)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::RemoveFormat)->isEnabled(), false); + + // make sure everything is selected + page->triggerAction(QWebPage::SelectAll); + + // this is only true if there is an editable selection + QCOMPARE(page->action(QWebPage::Cut)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::RemoveFormat)->isEnabled(), true); delete page; } +void tst_QWebPage::requestCache() +{ + TestPage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + + page.mainFrame()->setUrl(QString("data:text/html,<a href=\"data:text/html,Reached\" target=\"_blank\">Click me</a>")); + QTRY_COMPARE(loadSpy.count(), 1); + QTRY_COMPARE(page.navigations.count(), 1); + + page.mainFrame()->setUrl(QString("data:text/html,<a href=\"data:text/html,Reached\" target=\"_blank\">Click me2</a>")); + QTRY_COMPARE(loadSpy.count(), 2); + QTRY_COMPARE(page.navigations.count(), 2); + + page.triggerAction(QWebPage::Stop); + QVERIFY(page.history()->canGoBack()); + page.triggerAction(QWebPage::Back); + + QTRY_COMPARE(loadSpy.count(), 3); + QTRY_COMPARE(page.navigations.count(), 3); + QCOMPARE(page.navigations.at(0).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), + (int)QNetworkRequest::PreferNetwork); + QCOMPARE(page.navigations.at(1).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), + (int)QNetworkRequest::PreferNetwork); + QCOMPARE(page.navigations.at(2).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), + (int)QNetworkRequest::PreferCache); +} + +void tst_QWebPage::backActionUpdate() +{ + QWebView view; + QWebPage *page = view.page(); + QAction *action = page->action(QWebPage::Back); + QVERIFY(!action->isEnabled()); + QSignalSpy loadSpy(page, SIGNAL(loadFinished(bool))); + QUrl url = QUrl("qrc:///frametest/index.html"); + page->mainFrame()->load(url); + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(!action->isEnabled()); + QTest::mouseClick(&view, Qt::LeftButton, 0, QPoint(10, 10)); + QTRY_COMPARE(loadSpy.count(), 2); + + QVERIFY(action->isEnabled()); +} + +void frameAtHelper(QWebPage* webPage, QWebFrame* webFrame, QPoint framePosition) +{ + if (!webFrame) + return; + + framePosition += QPoint(webFrame->pos()); + QList<QWebFrame*> children = webFrame->childFrames(); + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->childFrames().size() > 0) + frameAtHelper(webPage, children.at(i), framePosition); + + QRect frameRect(children.at(i)->pos() + framePosition, children.at(i)->geometry().size()); + QVERIFY(children.at(i) == webPage->frameAt(frameRect.topLeft())); + } +} + +void tst_QWebPage::frameAt() +{ + QWebView webView; + QWebPage* webPage = webView.page(); + QSignalSpy loadSpy(webPage, SIGNAL(loadFinished(bool))); + QUrl url = QUrl("qrc:///frametest/iframe.html"); + webPage->mainFrame()->load(url); + QTRY_COMPARE(loadSpy.count(), 1); + frameAtHelper(webPage, webPage->mainFrame(), webPage->mainFrame()->pos()); +} + +// import a little DRT helper function to trigger the garbage collector +void QWEBKIT_EXPORT qt_drt_garbageCollector_collect(); + +void tst_QWebPage::protectBindingsRuntimeObjectsFromCollector() +{ + QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); + + PluginPage* newPage = new PluginPage(m_view); + m_view->setPage(newPage); + + m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + + m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='lineedit' id='mylineedit'/></body></html>")); + QTRY_COMPARE(loadSpy.count(), 1); + + newPage->mainFrame()->evaluateJavaScript("function testme(text) { var lineedit = document.getElementById('mylineedit'); lineedit.setText(text); lineedit.selectAll(); }"); + + newPage->mainFrame()->evaluateJavaScript("testme('foo')"); + + qt_drt_garbageCollector_collect(); + + // don't crash! + newPage->mainFrame()->evaluateJavaScript("testme('bar')"); +} QTEST_MAIN(tst_QWebPage) #include "tst_qwebpage.moc" diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.qrc b/WebKit/qt/tests/qwebpage/tst_qwebpage.qrc new file mode 100644 index 0000000..3085ce2 --- /dev/null +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.qrc @@ -0,0 +1,10 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>frametest/index.html</file> + <file>frametest/frame_a.html</file> + <file>frametest/iframe.html</file> + <file>frametest/iframe2.html</file> + <file>frametest/iframe3.html</file> +</qresource> +</RCC> + diff --git a/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro b/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro new file mode 100644 index 0000000..5d10993 --- /dev/null +++ b/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = tst_qwebplugindatabase +include(../../../../WebKit.pri) +SOURCES += tst_qwebplugindatabase.cpp +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebplugindatabase/tst_qwebplugindatabase.cpp b/WebKit/qt/tests/qwebplugindatabase/tst_qwebplugindatabase.cpp new file mode 100644 index 0000000..c0533ad --- /dev/null +++ b/WebKit/qt/tests/qwebplugindatabase/tst_qwebplugindatabase.cpp @@ -0,0 +1,401 @@ +/* + Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <QtTest/QtTest> + +#include <qdir.h> +#include <qwebframe.h> +#include <qwebpage.h> +#include <qwebplugindatabase.h> +#include <qwebsettings.h> +#include <qvariant.h> + +class tst_QWebPluginDatabase : public QObject +{ + Q_OBJECT + +private slots: + void installedPlugins(); + void searchPaths(); + void null_data(); + void null(); + void pluginForMimeType(); + void enabled(); + void operatorequal_data(); + void operatorequal(); + void preferredPlugin(); +}; + +typedef QWebPluginInfo::MimeType MimeType; + +void tst_QWebPluginDatabase::installedPlugins() +{ + QWebPage page; + page.settings()->setAttribute(QWebSettings::PluginsEnabled, true); + QWebFrame* frame = page.mainFrame(); + + QVariantMap jsPluginsMap = frame->evaluateJavaScript("window.navigator.plugins").toMap(); + QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins(); + QCOMPARE(plugins, QWebSettings::pluginDatabase()->plugins()); + + int length = jsPluginsMap["length"].toInt(); + QCOMPARE(length, plugins.count()); + + for (int i = 0; i < length; ++i) { + QWebPluginInfo plugin = plugins.at(i); + + QVariantMap jsPlugin = frame->evaluateJavaScript(QString("window.navigator.plugins[%1]").arg(i)).toMap(); + QString name = jsPlugin["name"].toString(); + QString description = jsPlugin["description"].toString(); + QString fileName = jsPlugin["filename"].toString(); + + QCOMPARE(plugin.name(), name); + QCOMPARE(plugin.description(), description); + QCOMPARE(QFileInfo(plugin.path()).fileName(), fileName); + + QList<MimeType> mimeTypes; + int mimeTypesCount = jsPlugin["length"].toInt(); + + for (int j = 0; j < mimeTypesCount; ++j) { + QVariantMap jsMimeType = frame->evaluateJavaScript(QString("window.navigator.plugins[%1][%2]").arg(i).arg(j)).toMap(); + + MimeType mimeType; + mimeType.name = jsMimeType["type"].toString(); + mimeType.description = jsMimeType["description"].toString(); + mimeType.fileExtensions = jsMimeType["suffixes"].toString().split(',', QString::SkipEmptyParts); + + mimeTypes.append(mimeType); + QVERIFY(plugin.supportsMimeType(mimeType.name)); + } + + QCOMPARE(plugin.mimeTypes(), mimeTypes); + + QVERIFY(!plugin.isNull()); + QVERIFY(plugin.isEnabled()); + } +} + +void tst_QWebPluginDatabase::searchPaths() +{ + QWebPluginDatabase* database = QWebSettings::pluginDatabase(); + QList<QWebPluginInfo> plugins = database->plugins(); + QStringList directories = database->searchPaths(); + QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories); + + database->setSearchPaths(directories); + QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories); + QCOMPARE(database->searchPaths(), directories); + QCOMPARE(database->plugins(), plugins); + database->refresh(); + QCOMPARE(database->plugins(), plugins); + + database->setSearchPaths(QStringList()); + QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories); + QCOMPARE(database->searchPaths(), QStringList()); + QCOMPARE(database->plugins().count(), 0); + + database->setSearchPaths(directories); + QCOMPARE(database->searchPaths(), directories); + database->addSearchPath(QDir::tempPath()); + QCOMPARE(database->searchPaths().count(), directories.count() + 1); + QVERIFY(database->searchPaths().contains(QDir::tempPath())); + directories.append(QDir::tempPath()); + QCOMPARE(database->searchPaths(), directories); + + // As an empty set of search paths has been set, the database has been rebuilt + // from scratch after bringing the old path set back. + // Because the QWebPlugins no longer point to the same PluginPackages, + // the list is also no longer equal to the older one, even though it contains + // the same information. + QCOMPARE(database->plugins().count(), plugins.count()); + plugins = database->plugins(); + QCOMPARE(database->plugins(), plugins); + + for (int i = (directories.count() - 1); i >= 0; --i) { + QDir directory(directories.at(i)); + if (!directory.exists() || !directory.count()) + directories.removeAt(i); + } + + database->setSearchPaths(directories); + QCOMPARE(database->plugins(), plugins); + database->refresh(); + QCOMPARE(database->plugins(), plugins); + + database->setSearchPaths(QWebPluginDatabase::defaultSearchPaths()); + directories = QWebPluginDatabase::defaultSearchPaths(); + QCOMPARE(QWebPluginDatabase::defaultSearchPaths(), directories); + QCOMPARE(database->searchPaths(), directories); + QCOMPARE(database->plugins(), plugins); +} + +Q_DECLARE_METATYPE(QWebPluginInfo) +void tst_QWebPluginDatabase::null_data() +{ + QTest::addColumn<QWebPluginInfo>("plugin"); + QTest::addColumn<bool>("null"); + + QTest::newRow("null") << QWebPluginInfo() << true; + QTest::newRow("foo") << QWebSettings::pluginDatabase()->pluginForMimeType("foobarbaz") << true; + + QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins(); + for (int i = 0; i < plugins.count(); ++i) + QTest::newRow(QString::number(i).toUtf8().constData()) << plugins.at(i) << false; +} + +void tst_QWebPluginDatabase::null() +{ + QFETCH(QWebPluginInfo, plugin); + QFETCH(bool, null); + + QCOMPARE(plugin.isNull(), null); +} + +void tst_QWebPluginDatabase::pluginForMimeType() +{ + QMultiMap<QString, QWebPluginInfo> pluginsMap; + QWebPluginDatabase* database = QWebSettings::pluginDatabase(); + QList<QWebPluginInfo> plugins = database->plugins(); + + for (int i = 0; i < plugins.count(); ++i) { + QWebPluginInfo plugin = plugins.at(i); + + QList<MimeType> mimeTypes = plugin.mimeTypes(); + for (int j = 0; j < mimeTypes.count(); ++j) { + QString mimeType = mimeTypes.at(j).name; + pluginsMap.insert(mimeType, plugin); + QVERIFY(plugin.supportsMimeType(mimeType)); + } + } + + for (int i = 0; i < plugins.count(); ++i) { + QWebPluginInfo plugin = plugins.at(i); + + QList<MimeType> mimeTypes = plugin.mimeTypes(); + for (int j = 0; j < mimeTypes.count(); ++j) { + QString mimeType = mimeTypes.at(j).name; + + QVERIFY(pluginsMap.count(mimeType) > 0); + if (pluginsMap.count(mimeType) > 1) + continue; + + QWebPluginInfo pluginForMimeType = database->pluginForMimeType(mimeType); + QCOMPARE(pluginForMimeType, plugin); + database->setSearchPaths(database->searchPaths()); + QCOMPARE(pluginForMimeType, plugin); + QCOMPARE(pluginForMimeType, database->pluginForMimeType(mimeType.toUpper())); + QCOMPARE(pluginForMimeType, database->pluginForMimeType(mimeType.toLower())); + QVERIFY(plugin.supportsMimeType(mimeType)); + QVERIFY(!pluginForMimeType.isNull()); + QVERIFY(!plugin.isNull()); + } + } +} + +void tst_QWebPluginDatabase::enabled() +{ + QMultiMap<QString, QWebPluginInfo> pluginsMap; + QWebPluginDatabase* database = QWebSettings::pluginDatabase(); + QList<QWebPluginInfo> plugins = database->plugins(); + + for (int i = 0; i < plugins.count(); ++i) { + QWebPluginInfo plugin = plugins.at(i); + + QList<MimeType> mimeTypes = plugin.mimeTypes(); + for (int j = 0; j < mimeTypes.count(); ++j) { + QString mimeType = mimeTypes.at(j).name; + pluginsMap.insert(mimeType, plugin); + QVERIFY(plugin.supportsMimeType(mimeType)); + } + } + + QMultiMap<QString, QWebPluginInfo>::iterator it = pluginsMap.begin(); + while (it != pluginsMap.end()) { + QString mimeType = it.key(); + QWebPluginInfo plugin = it.value(); + QWebPluginInfo pluginForMimeType = database->pluginForMimeType(mimeType); + + QVERIFY(pluginsMap.count(mimeType) > 0); + + if (pluginsMap.count(mimeType) == 1) { + QCOMPARE(plugin, pluginForMimeType); + + QVERIFY(plugin.isEnabled()); + QVERIFY(pluginForMimeType.isEnabled()); + plugin.setEnabled(false); + QVERIFY(!plugin.isEnabled()); + QVERIFY(!pluginForMimeType.isEnabled()); + } else { + QVERIFY(plugin.isEnabled()); + QVERIFY(pluginForMimeType.isEnabled()); + plugin.setEnabled(false); + QVERIFY(!plugin.isEnabled()); + } + + QVERIFY(!plugin.isNull()); + QVERIFY(!pluginForMimeType.isNull()); + + QWebPluginInfo pluginForMimeType2 = database->pluginForMimeType(mimeType); + if (pluginsMap.count(mimeType) == 1) { + QVERIFY(pluginForMimeType2 != plugin); + QVERIFY(pluginForMimeType2.isNull()); + } else { + QVERIFY(pluginForMimeType2 != plugin); + QVERIFY(!pluginForMimeType2.isNull()); + } + + plugin.setEnabled(true); + + ++it; + } +} + +void tst_QWebPluginDatabase::operatorequal_data() +{ + QTest::addColumn<QWebPluginInfo>("first"); + QTest::addColumn<QWebPluginInfo>("second"); + QTest::addColumn<bool>("equal"); + + QWebPluginDatabase* database = QWebSettings::pluginDatabase(); + QTest::newRow("null") << QWebPluginInfo() << QWebPluginInfo() << true; + QTest::newRow("application/x-shockwave-flash") << database->pluginForMimeType("application/x-shockwave-flash") + << database->pluginForMimeType("application/x-shockwave-flash") << true; + QTest::newRow("foo/bar-baz") << database->pluginForMimeType("foo/bar-baz") + << database->pluginForMimeType("foo/bar-baz") << true; + + QList<QWebPluginInfo> plugins = database->plugins(); + for (int i = 0; i < (plugins.count() - 1); ++i) { + QWebPluginInfo first = plugins.at(i); + QWebPluginInfo second = plugins.at(i + 1); + + QTest::newRow(QString("%1==%2").arg(first.name(), second.name()).toUtf8().constData()) + << first << second << false; + } +} + +void tst_QWebPluginDatabase::operatorequal() +{ + QFETCH(QWebPluginInfo, first); + QFETCH(QWebPluginInfo, second); + QFETCH(bool, equal); + + QCOMPARE(first == second, equal); +} + +void tst_QWebPluginDatabase::preferredPlugin() +{ + QMultiMap<QString, QWebPluginInfo> pluginsMap; + QWebPluginDatabase* database = QWebSettings::pluginDatabase(); + QList<QWebPluginInfo> plugins = database->plugins(); + + for (int i = 0; i < plugins.count(); ++i) { + QWebPluginInfo plugin = plugins.at(i); + + QList<MimeType> mimeTypes = plugin.mimeTypes(); + for (int j = 0; j < mimeTypes.count(); ++j) { + QString mimeType = mimeTypes.at(j).name; + pluginsMap.insert(mimeType, plugin); + } + } + + QMultiMap<QString, QWebPluginInfo>::iterator it = pluginsMap.begin(); + while (it != pluginsMap.end()) { + QString mimeType = it.key(); + + if (pluginsMap.count(mimeType) > 1) { + QList<QWebPluginInfo> pluginsForMimeType = pluginsMap.values(mimeType); + QWebPluginInfo plugin = database->pluginForMimeType(mimeType); + QVERIFY(plugin.supportsMimeType(mimeType)); + + pluginsForMimeType.removeAll(plugin); + for (int i = 0; i < pluginsForMimeType.count(); ++i) { + QWebPluginInfo anotherPlugin = pluginsForMimeType.at(i); + QVERIFY(plugin.supportsMimeType(mimeType)); + QVERIFY(plugin != anotherPlugin); + + QCOMPARE(database->pluginForMimeType(mimeType), plugin); + database->setPreferredPluginForMimeType(mimeType, anotherPlugin); + QCOMPARE(database->pluginForMimeType(mimeType), anotherPlugin); + + anotherPlugin.setEnabled(false); + QCOMPARE(database->pluginForMimeType(mimeType), plugin); + + anotherPlugin.setEnabled(true); + QCOMPARE(database->pluginForMimeType(mimeType), anotherPlugin); + database->setSearchPaths(database->searchPaths()); + QCOMPARE(database->pluginForMimeType(mimeType), anotherPlugin); + + database->setPreferredPluginForMimeType(mimeType, QWebPluginInfo()); + QCOMPARE(database->pluginForMimeType(mimeType), plugin); + } + } else { + QWebPluginInfo plugin = database->pluginForMimeType(mimeType); + QCOMPARE(pluginsMap.value(mimeType), plugin); + + database->setPreferredPluginForMimeType(mimeType, plugin); + QCOMPARE(database->pluginForMimeType(mimeType), plugin); + + plugin.setEnabled(false); + QCOMPARE(database->pluginForMimeType(mimeType), QWebPluginInfo()); + plugin.setEnabled(true); + + database->setPreferredPluginForMimeType(mimeType, QWebPluginInfo()); + QCOMPARE(database->pluginForMimeType(mimeType), plugin); + } + + ++it; + } + + if (pluginsMap.keys().count() >= 2) { + QStringList mimeTypes = pluginsMap.uniqueKeys(); + + QString mimeType1 = mimeTypes.at(0); + QString mimeType2 = mimeTypes.at(1); + QWebPluginInfo plugin1 = database->pluginForMimeType(mimeType1); + QWebPluginInfo plugin2 = database->pluginForMimeType(mimeType2); + + int i = 2; + while (plugin2.supportsMimeType(mimeType1) + && !mimeType2.isEmpty() + && i < mimeTypes.count()) { + mimeType2 = mimeTypes.at(i); + plugin2 = database->pluginForMimeType(mimeType2); + ++i; + } + + plugin1 = database->pluginForMimeType(mimeType1); + QVERIFY(plugin1.supportsMimeType(mimeType1)); + QVERIFY(!plugin1.isNull()); + plugin2 = database->pluginForMimeType(mimeType2); + QVERIFY(plugin2.supportsMimeType(mimeType2)); + QVERIFY(!plugin2.isNull()); + + database->setPreferredPluginForMimeType(mimeType2, plugin1); + QVERIFY(!plugin1.supportsMimeType(mimeType2)); + QCOMPARE(database->pluginForMimeType(mimeType2), plugin2); + + database->setPreferredPluginForMimeType(mimeType1, plugin1); + QVERIFY(!plugin2.supportsMimeType(mimeType1)); + QCOMPARE(database->pluginForMimeType(mimeType2), plugin2); + } +} + +QTEST_MAIN(tst_QWebPluginDatabase) + +#include "tst_qwebplugindatabase.moc" diff --git a/WebKit/qt/tests/qwebview/.gitignore b/WebKit/qt/tests/qwebview/.gitignore new file mode 100644 index 0000000..444afe6 --- /dev/null +++ b/WebKit/qt/tests/qwebview/.gitignore @@ -0,0 +1 @@ +qwebview diff --git a/WebKit/qt/tests/qwebview/qwebview.pro b/WebKit/qt/tests/qwebview/qwebview.pro new file mode 100644 index 0000000..799ccfb --- /dev/null +++ b/WebKit/qt/tests/qwebview/qwebview.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = tst_qwebview +include(../../../../WebKit.pri) +SOURCES += tst_qwebview.cpp +QT += testlib network +QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKit/qt/tests/qwebview/tst_qwebview.cpp b/WebKit/qt/tests/qwebview/tst_qwebview.cpp new file mode 100644 index 0000000..01d0e92 --- /dev/null +++ b/WebKit/qt/tests/qwebview/tst_qwebview.cpp @@ -0,0 +1,172 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Torch Mobile Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qtest.h> + +#include <qpainter.h> +#include <qwebview.h> +#include <qwebpage.h> +#include <qnetworkrequest.h> +#include <qdiriterator.h> +#include <qwebkitversion.h> + +class tst_QWebView : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void renderHints(); + void guessUrlFromString_data(); + void guessUrlFromString(); + void getWebKitVersion(); +}; + +// This will be called before the first test function is executed. +// It is only called once. +void tst_QWebView::initTestCase() +{ +} + +// This will be called after the last test function is executed. +// It is only called once. +void tst_QWebView::cleanupTestCase() +{ +} + +// This will be called before each test function is executed. +void tst_QWebView::init() +{ +} + +// This will be called after every test function. +void tst_QWebView::cleanup() +{ +} + +void tst_QWebView::renderHints() +{ + QWebView webView; + + // default is only text antialiasing + QVERIFY(!(webView.renderHints() & QPainter::Antialiasing)); + QVERIFY(webView.renderHints() & QPainter::TextAntialiasing); + QVERIFY(!(webView.renderHints() & QPainter::SmoothPixmapTransform)); + QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing)); + + webView.setRenderHint(QPainter::Antialiasing, true); + QVERIFY(webView.renderHints() & QPainter::Antialiasing); + QVERIFY(webView.renderHints() & QPainter::TextAntialiasing); + QVERIFY(!(webView.renderHints() & QPainter::SmoothPixmapTransform)); + QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing)); + + webView.setRenderHint(QPainter::Antialiasing, false); + QVERIFY(!(webView.renderHints() & QPainter::Antialiasing)); + QVERIFY(webView.renderHints() & QPainter::TextAntialiasing); + QVERIFY(!(webView.renderHints() & QPainter::SmoothPixmapTransform)); + QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing)); + + webView.setRenderHint(QPainter::SmoothPixmapTransform, true); + QVERIFY(!(webView.renderHints() & QPainter::Antialiasing)); + QVERIFY(webView.renderHints() & QPainter::TextAntialiasing); + QVERIFY(webView.renderHints() & QPainter::SmoothPixmapTransform); + QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing)); + + webView.setRenderHint(QPainter::SmoothPixmapTransform, false); + QVERIFY(webView.renderHints() & QPainter::TextAntialiasing); + QVERIFY(!(webView.renderHints() & QPainter::SmoothPixmapTransform)); + QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing)); +} + +void tst_QWebView::guessUrlFromString_data() +{ + QTest::addColumn<QString>("string"); + QTest::addColumn<QUrl>("guessUrlFromString"); + + // Null + QTest::newRow("null") << QString() << QUrl(); + + // File + QDirIterator it(QDir::homePath()); + QString fileString; + int c = 0; + while (it.hasNext()) { + it.next(); + QTest::newRow(QString("file-%1").arg(c++).toLatin1()) << it.filePath() << QUrl::fromLocalFile(it.filePath()); + } + + // basic latin1 + QTest::newRow("unicode-0") << QString::fromUtf8("å.com/") << QUrl::fromEncoded(QString::fromUtf8("http://å.com/").toUtf8(), QUrl::TolerantMode); + // unicode + QTest::newRow("unicode-1") << QString::fromUtf8("λ.com/") << QUrl::fromEncoded(QString::fromUtf8("http://λ.com/").toUtf8(), QUrl::TolerantMode); + + // no scheme + QTest::newRow("add scheme-0") << "webkit.org" << QUrl("http://webkit.org"); + QTest::newRow("add scheme-1") << "www.webkit.org" << QUrl("http://www.webkit.org"); + QTest::newRow("add scheme-2") << "ftp.webkit.org" << QUrl("ftp://ftp.webkit.org"); + QTest::newRow("add scheme-3") << "webkit" << QUrl("webkit"); + + // QUrl's tolerant parser should already handle this + QTest::newRow("not-encoded-0") << "http://webkit.org/test page.html" << QUrl("http://webkit.org/test%20page.html"); + + // Make sure the :80, i.e. port doesn't screw anything up + QUrl portUrl("http://webkit.org"); + portUrl.setPort(80); + QTest::newRow("port-0") << "webkit.org:80" << portUrl; + QTest::newRow("port-1") << "http://webkit.org:80" << portUrl; + + // mailto doesn't have a ://, but is valid + QUrl mailto("ben@meyerhome.net"); + mailto.setScheme("mailto"); + QTest::newRow("mailto") << "mailto:ben@meyerhome.net" << mailto; + + // misc + QTest::newRow("localhost-0") << "localhost" << QUrl("http://localhost"); + QTest::newRow("localhost-1") << "localhost:80" << QUrl("http://localhost:80"); + QTest::newRow("spaces-0") << " http://webkit.org/test page.html " << QUrl("http://webkit.org/test%20page.html"); + + // FYI: The scheme in the resulting url user + QUrl authUrl("user:pass@domain.com"); + QTest::newRow("misc-1") << "user:pass@domain.com" << authUrl; +} + +// public static QUrl guessUrlFromString(QString const& string) +void tst_QWebView::guessUrlFromString() +{ + QFETCH(QString, string); + QFETCH(QUrl, guessUrlFromString); + + QUrl url = QWebView::guessUrlFromString(string); + QCOMPARE(url, guessUrlFromString); +} + +void tst_QWebView::getWebKitVersion() +{ + QVERIFY(qWebKitVersion().toDouble() > 0); +} + +QTEST_MAIN(tst_QWebView) +#include "tst_qwebview.moc" + diff --git a/WebKit/qt/tests/tests.pro b/WebKit/qt/tests/tests.pro index f08830d..b5f66ee 100644 --- a/WebKit/qt/tests/tests.pro +++ b/WebKit/qt/tests/tests.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = qwebframe qwebpage +SUBDIRS = qwebframe qwebpage qwebelement qwebhistoryinterface qwebplugindatabase qwebview qwebhistory +greaterThan(QT_MINOR_VERSION, 4): SUBDIRS += benchmarks/painting/tst_painting.pro benchmarks/loading/tst_loading.pro |