diff options
Diffstat (limited to 'WebKit/qt/tests')
28 files changed, 1512 insertions, 220 deletions
diff --git a/WebKit/qt/tests/benchmarks/loading/loading.pro b/WebKit/qt/tests/benchmarks/loading/loading.pro index 8b24274..99c64a5 100644 --- a/WebKit/qt/tests/benchmarks/loading/loading.pro +++ b/WebKit/qt/tests/benchmarks/loading/loading.pro @@ -1 +1,3 @@ +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../../.. include(../../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/benchmarks/painting/painting.pro b/WebKit/qt/tests/benchmarks/painting/painting.pro index 8acdd5c..99c64a5 100644 --- a/WebKit/qt/tests/benchmarks/painting/painting.pro +++ b/WebKit/qt/tests/benchmarks/painting/painting.pro @@ -1 +1,3 @@ -include(../../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../../.. +include(../../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp b/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp index f4531fd..fc5b8e3 100644 --- a/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp +++ b/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp @@ -19,6 +19,7 @@ #include <QtTest/QtTest> +#include <qwebelement.h> #include <qwebframe.h> #include <qwebview.h> #include <qpainter.h> @@ -59,6 +60,7 @@ public Q_SLOTS: private Q_SLOTS: void paint_data(); void paint(); + void textAreas(); private: QWebView* m_view; @@ -105,5 +107,30 @@ void tst_Painting::paint() } } +void tst_Painting::textAreas() +{ + m_view->load(QUrl("data:text/html;<html><body></body></html>")); + ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); + + QWebElement bodyElement = m_page->mainFrame()->findFirstElement("body"); + + int count = 100; + while (count--) { + QString markup("<textarea cols='1' rows='1'></textarea>"); + bodyElement.appendInside(markup); + } + + /* force a layout */ + QWebFrame* mainFrame = m_page->mainFrame(); + mainFrame->toPlainText(); + + QPixmap pixmap(mainFrame->contentsSize()); + QBENCHMARK { + QPainter painter(&pixmap); + mainFrame->render(&painter, QRect(QPoint(0, 0), mainFrame->contentsSize())); + painter.end(); + } +} + QTEST_MAIN(tst_Painting) #include "tst_painting.moc" diff --git a/WebKit/qt/tests/hybridPixmap/hybridPixmap.pro b/WebKit/qt/tests/hybridPixmap/hybridPixmap.pro index 0e49a70..9e80870 100644 --- a/WebKit/qt/tests/hybridPixmap/hybridPixmap.pro +++ b/WebKit/qt/tests/hybridPixmap/hybridPixmap.pro @@ -1,6 +1,7 @@ # ------------------------------------------------- # Project created by QtCreator 2009-12-10T11:25:02 # ------------------------------------------------- +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) TARGET = hybridPixmap SOURCES += widget.cpp diff --git a/WebKit/qt/tests/hybridPixmap/test.html b/WebKit/qt/tests/hybridPixmap/test.html index ddaf75c..0f2c345 100644 --- a/WebKit/qt/tests/hybridPixmap/test.html +++ b/WebKit/qt/tests/hybridPixmap/test.html @@ -9,11 +9,17 @@ var obj = myWidget.image; var pxm = myWidget.pixmap; - var img = obj.toHTMLImageElement(); + var img = new Image; + obj.assignToHTMLImageElement(img); var img1 = document.getElementById("img1"); var img2 = document.getElementById("img2"); + var img3 = document.getElementById("img3"); + var img4 = document.getElementById("img4"); document.body.appendChild(img); - document.body.appendChild(pxm.toHTMLImageElement()); + obj.assignToHTMLImageElement(img3); + pxm.assignToHTMLImageElement(img4); + myWidget.compare(pxm.width, img4.width); + myWidget.compare(obj.width, img3.width); var signalsFired = 0; myWidget.compare(obj.toString(),"[Qt Native Pixmap "+obj.width+","+obj.height+"]"); myWidget.compare(String(pxm),"[Qt Native Pixmap "+pxm.width+","+pxm.height+"]"); @@ -53,5 +59,7 @@ <body onload="startTest()"> <img id="img1" /> <img id="img2" /> + <img id="img3" /> + <img id="img4" /> </body> </html> diff --git a/WebKit/qt/tests/hybridPixmap/widget.ui b/WebKit/qt/tests/hybridPixmap/widget.ui index 4f2b3b8..272d6a7 100644 --- a/WebKit/qt/tests/hybridPixmap/widget.ui +++ b/WebKit/qt/tests/hybridPixmap/widget.ui @@ -11,14 +11,14 @@ </rect> </property> <property name="windowTitle"> - <string>Widget</string> + <string notr="true">Widget</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="WebView" name="webView" native="true"> <property name="url" stdset="0"> <url> - <string>about:blank</string> + <string notr="true">about:blank</string> </url> </property> </widget> @@ -28,7 +28,7 @@ <item> <widget class="QLabel" name="lbl1"> <property name="text"> - <string/> + <string notr="true"/> </property> </widget> </item> @@ -47,21 +47,21 @@ </size> </property> <property name="text"> - <string>Image from Qt to HTML</string> + <string notr="true">Image from Qt to HTML</string> </property> </widget> </item> <item> <widget class="QLabel" name="lbl3"> <property name="text"> - <string>Pixmap from Qt to HTML</string> + <string notr="true">Pixmap from Qt to HTML</string> </property> </widget> </item> <item> <widget class="QLabel" name="lbl4"> <property name="text"> - <string/> + <string notr="true"/> </property> </widget> </item> diff --git a/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro b/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro +++ b/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qgraphicswebview/resources/input_types.html b/WebKit/qt/tests/qgraphicswebview/resources/input_types.html new file mode 100644 index 0000000..18ab314 --- /dev/null +++ b/WebKit/qt/tests/qgraphicswebview/resources/input_types.html @@ -0,0 +1,8 @@ +<html><body> +<input type='text' maxlength='20' style='position: absolute; left: 10px; top: 0px; height: 50px; width: 100px;'/><br> +<input type='password' style='position: absolute; left: 10px; top: 50px; height: 50px; width: 100px;'/><br> +<input type='tel' style='position: absolute; left: 10px; top: 100px; height: 50px; width: 100px;'/><br> +<input type='number' style='position: absolute; left: 10px; top: 150px; height: 50px; width: 100px;'/><br> +<input type='email' style='position: absolute; left: 10px; top: 200px; height: 50px; width: 100px;'/><br> +<input type='url' style='position: absolute; left: 10px; top: 250px; height: 50px; width: 100px;'/><br>" +</body></html>
\ No newline at end of file diff --git a/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp b/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp index 657e09f..09a21e1 100644 --- a/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp +++ b/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp @@ -19,6 +19,7 @@ #include "../util.h" #include <QtTest/QtTest> +#include <QGraphicsSceneMouseEvent> #include <QGraphicsView> #include <qgraphicswebview.h> #include <qwebpage.h> @@ -31,6 +32,10 @@ class tst_QGraphicsWebView : public QObject private slots: void qgraphicswebview(); void crashOnViewlessWebPages(); + void microFocusCoordinates(); + void focusInputTypes(); + void crashOnSetScaleBeforeSetUrl(); + void widgetsRenderingThroughCache(); }; void tst_QGraphicsWebView::qgraphicswebview() @@ -74,6 +79,29 @@ private slots: } }; +class GraphicsWebView : public QGraphicsWebView +{ + Q_OBJECT + +public: + GraphicsWebView(QGraphicsItem* parent = 0): QGraphicsWebView(parent) + { + } + + void fireMouseClick(QPointF point) { + QGraphicsSceneMouseEvent presEv(QEvent::GraphicsSceneMousePress); + presEv.setPos(point); + presEv.setButton(Qt::LeftButton); + presEv.setButtons(Qt::LeftButton); + QGraphicsSceneMouseEvent relEv(QEvent::GraphicsSceneMouseRelease); + relEv.setPos(point); + relEv.setButton(Qt::LeftButton); + relEv.setButtons(Qt::LeftButton); + QGraphicsWebView::sceneEvent(&presEv); + QGraphicsWebView::sceneEvent(&relEv); + } +}; + void tst_QGraphicsWebView::crashOnViewlessWebPages() { QGraphicsScene scene; @@ -83,25 +111,156 @@ void tst_QGraphicsWebView::crashOnViewlessWebPages() WebPage* page = new WebPage; webView->setPage(page); page->webView = webView; - connect(page->mainFrame(), SIGNAL(initialLayoutCompleted()), page, SLOT(aborting())); - scene.addItem(webView); view.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); view.resize(600, 480); webView->resize(view.geometry().size()); + QCoreApplication::processEvents(); view.show(); - page->mainFrame()->setHtml(QString("data:text/html," - "<frameset cols=\"25%,75%\">" - "<frame src=\"data:text/html,foo \">" - "<frame src=\"data:text/html,bar\">" - "</frameset>")); + // Resizing the page will resize and layout the empty "about:blank" + // page, so we first connect the signal afterward. + connect(page->mainFrame(), SIGNAL(initialLayoutCompleted()), page, SLOT(aborting())); + + page->mainFrame()->load(QUrl("data:text/html," + "<frameset cols=\"25%,75%\">" + "<frame src=\"data:text/html,foo \">" + "<frame src=\"data:text/html,bar\">" + "</frameset>")); QVERIFY(waitForSignal(page, SIGNAL(loadFinished(bool)))); + delete page; } +void tst_QGraphicsWebView::crashOnSetScaleBeforeSetUrl() +{ + QGraphicsWebView* webView = new QGraphicsWebView; + webView->setScale(2.0); + delete webView; +} + +void tst_QGraphicsWebView::widgetsRenderingThroughCache() +{ + // Widgets should be rendered the same way with and without + // intermediate cache (tiling for example). + // See bug https://bugs.webkit.org/show_bug.cgi?id=47767 where + // widget are rendered as disabled when caching is using. + + QGraphicsWebView* webView = new QGraphicsWebView; + webView->setHtml(QLatin1String("<body style=\"background-color: white\"><input type=range></input><input type=checkbox></input><input type=radio></input><input type=file></input></body>")); + + QGraphicsView view; + view.show(); + QGraphicsScene* scene = new QGraphicsScene(&view); + view.setScene(scene); + scene->addItem(webView); + view.setGeometry(QRect(0, 0, 500, 500)); + QWidget *const widget = &view; + QTest::qWaitForWindowShown(widget); + + // 1. Reference without tiling. + webView->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, false); + QPixmap referencePixmap(view.size()); + widget->render(&referencePixmap); + + // 2. With tiling. + webView->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, true); + QPixmap viewWithTiling(view.size()); + widget->render(&viewWithTiling); + QApplication::processEvents(); + viewWithTiling.fill(); + widget->render(&viewWithTiling); + + QCOMPARE(referencePixmap.toImage(), viewWithTiling.toImage()); +} + +void tst_QGraphicsWebView::microFocusCoordinates() +{ + QWebPage* page = new QWebPage; + QGraphicsWebView* webView = new QGraphicsWebView; + webView->setPage( page ); + QGraphicsView* view = new QGraphicsView; + QGraphicsScene* scene = new QGraphicsScene(view); + view->setScene(scene); + scene->addItem(webView); + view->setGeometry(QRect(0,0,500,500)); + + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input1' style='font--family: serif' value='' maxlength='20'/><br>" \ + "<canvas id='canvas1' width='500' height='500'/>" \ + "<input type='password'/><br>" \ + "<canvas id='canvas2' width='500' height='500'/>" \ + "</body></html>"); + + page->mainFrame()->setFocus(); + + QVariant initialMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(initialMicroFocus.isValid()); + + page->mainFrame()->scroll(0,300); + + QVariant currentMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(currentMicroFocus.isValid()); + + QCOMPARE(initialMicroFocus.toRect().translated(QPoint(0,-300)), currentMicroFocus.toRect()); + + delete view; +} + +void tst_QGraphicsWebView::focusInputTypes() +{ + QWebPage* page = new QWebPage; + GraphicsWebView* webView = new GraphicsWebView; + webView->setPage( page ); + QGraphicsView* view = new QGraphicsView; + QGraphicsScene* scene = new QGraphicsScene(view); + view->setScene(scene); + scene->addItem(webView); + view->setGeometry(QRect(0,0,500,500)); + QCoreApplication::processEvents(); + QUrl url("qrc:///resources/input_types.html"); + page->mainFrame()->load(url); + page->mainFrame()->setFocus(); + + QVERIFY(waitForSignal(page, SIGNAL(loadFinished(bool)))); + + // 'text' type + webView->fireMouseClick(QPointF(20.0, 10.0)); +#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(Q_OS_SYMBIAN) + QVERIFY(webView->inputMethodHints() & Qt::ImhNoAutoUppercase); + QVERIFY(webView->inputMethodHints() & Qt::ImhNoPredictiveText); +#else + QVERIFY(webView->inputMethodHints() == Qt::ImhNone); +#endif + + // 'password' field + webView->fireMouseClick(QPointF(20.0, 60.0)); + QVERIFY(webView->inputMethodHints() & Qt::ImhHiddenText); + + // 'tel' field + webView->fireMouseClick(QPointF(20.0, 110.0)); + QVERIFY(webView->inputMethodHints() & Qt::ImhDialableCharactersOnly); + + // 'number' field + webView->fireMouseClick(QPointF(20.0, 160.0)); + QVERIFY(webView->inputMethodHints() & Qt::ImhDigitsOnly); + + // 'email' field + webView->fireMouseClick(QPointF(20.0, 210.0)); + QVERIFY(webView->inputMethodHints() & Qt::ImhEmailCharactersOnly); + + // 'url' field + webView->fireMouseClick(QPointF(20.0, 260.0)); + QVERIFY(webView->inputMethodHints() & Qt::ImhUrlCharactersOnly); + + delete webView; + delete view; +} + + + QTEST_MAIN(tst_QGraphicsWebView) #include "tst_qgraphicswebview.moc" diff --git a/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.qrc b/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.qrc new file mode 100644 index 0000000..c91bb9c --- /dev/null +++ b/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>resources/input_types.html</file> +</qresource> +</RCC> + diff --git a/WebKit/qt/tests/qwebelement/qwebelement.pro b/WebKit/qt/tests/qwebelement/qwebelement.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebelement/qwebelement.pro +++ b/WebKit/qt/tests/qwebelement/qwebelement.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp b/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp index 8db0ec3..88816e8 100644 --- a/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp +++ b/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp @@ -71,6 +71,7 @@ private slots: void lastChildPreviousSibling(); void hasSetFocus(); void render(); + void addElementToHead(); private: QWebView* m_view; @@ -430,9 +431,9 @@ void tst_QWebElement::frame() 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()); + m_mainFrame->load(QUrl("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," + "<p>frame1\">" + "<frame src=\"data:text/html,<p>frame2\"></frameset>")); waitForSignal(m_page, SIGNAL(loadFinished(bool))); @@ -887,7 +888,7 @@ void tst_QWebElement::nullSelect() void tst_QWebElement::firstChildNextSibling() { - m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another commend><table>"); + m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another comment--><table>"); QWebElement body = m_mainFrame->findFirstElement("body"); QVERIFY(!body.isNull()); @@ -902,7 +903,7 @@ void tst_QWebElement::firstChildNextSibling() void tst_QWebElement::lastChildPreviousSibling() { - m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another commend><table>"); + m_mainFrame->setHtml("<body><!--comment--><p>Test</p><!--another comment--><table>"); QWebElement body = m_mainFrame->findFirstElement("body"); QVERIFY(!body.isNull()); @@ -1013,5 +1014,15 @@ void tst_QWebElement::render() QVERIFY(image3 == image4); } +void tst_QWebElement::addElementToHead() +{ + m_mainFrame->setHtml("<html><head></head><body></body></html>"); + QWebElement head = m_mainFrame->findFirstElement("head"); + QVERIFY(!head.isNull()); + QString append = "<script type=\"text/javascript\">var t = 0;</script>"; + head.appendInside(append); + QCOMPARE(head.toInnerXml(), append); +} + QTEST_MAIN(tst_QWebElement) #include "tst_qwebelement.moc" diff --git a/WebKit/qt/tests/qwebframe/qwebframe.pro b/WebKit/qt/tests/qwebframe/qwebframe.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebframe/qwebframe.pro +++ b/WebKit/qt/tests/qwebframe/qwebframe.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index 0fb0bd6..eb3ae0a 100644 --- a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -33,6 +33,7 @@ #include <QRegExp> #include <QNetworkRequest> #include <QNetworkReply> +#include <QTextCodec> #ifndef QT_NO_OPENSSL #include <qsslerror.h> #endif @@ -57,6 +58,7 @@ class MyQObject : public QObject Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty) Q_PROPERTY(QVariantList variantListProperty READ variantListProperty WRITE setVariantListProperty) + Q_PROPERTY(QVariantMap variantMapProperty READ variantMapProperty WRITE setVariantMapProperty) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) Q_PROPERTY(QStringList stringListProperty READ stringListProperty WRITE setStringListProperty) Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty) @@ -66,6 +68,8 @@ class MyQObject : public QObject Q_PROPERTY(int readOnlyProperty READ readOnlyProperty) Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) Q_PROPERTY(CustomType propWithCustomType READ propWithCustomType WRITE setPropWithCustomType) + Q_PROPERTY(QWebElement webElementProperty READ webElementProperty WRITE setWebElementProperty) + Q_PROPERTY(QObject* objectStarProperty READ objectStarProperty WRITE setObjectStarProperty) Q_ENUMS(Policy Strategy) Q_FLAGS(Ability) @@ -103,7 +107,13 @@ public: m_hiddenValue(456.0), m_writeOnlyValue(789), m_readOnlyValue(987), - m_qtFunctionInvoked(-1) { } + m_objectStar(0), + m_qtFunctionInvoked(-1) + { + m_variantMapValue.insert("a", QVariant(123)); + m_variantMapValue.insert("b", QVariant(QLatin1String("foo"))); + m_variantMapValue.insert("c", QVariant::fromValue<QObject*>(this)); + } ~MyQObject() { } @@ -128,6 +138,13 @@ public: m_variantListValue = value; } + QVariantMap variantMapProperty() const { + return m_variantMapValue; + } + void setVariantMapProperty(const QVariantMap &value) { + m_variantMapValue = value; + } + QString stringProperty() const { return m_stringValue; } @@ -181,6 +198,14 @@ public: m_shortcut = seq; } + QWebElement webElementProperty() const { + return m_webElement; + } + + void setWebElementProperty(const QWebElement& element) { + m_webElement = element; + } + CustomType propWithCustomType() const { return m_customType; } @@ -188,6 +213,15 @@ public: m_customType = c; } + QObject* objectStarProperty() const { + return m_objectStar; + } + + void setObjectStarProperty(QObject* object) { + m_objectStar = object; + } + + int qtFunctionInvoked() const { return m_qtFunctionInvoked; } @@ -433,6 +467,10 @@ public Q_SLOTS: m_qtFunctionInvoked = 35; m_actuals << arg; } + void myOverloadedSlot(const QWebElement &arg) { + m_qtFunctionInvoked = 36; + m_actuals << QVariant::fromValue<QWebElement>(arg); + } void qscript_call(int arg) { m_qtFunctionInvoked = 40; @@ -459,6 +497,7 @@ private: int m_intValue; QVariant m_variantValue; QVariantList m_variantListValue; + QVariantMap m_variantMapValue; QString m_stringValue; QStringList m_stringListValue; QByteArray m_byteArrayValue; @@ -467,7 +506,9 @@ private: int m_writeOnlyValue; int m_readOnlyValue; QKeySequence m_shortcut; + QWebElement m_webElement; CustomType m_customType; + QObject* m_objectStar; int m_qtFunctionInvoked; QVariantList m_actuals; }; @@ -558,9 +599,15 @@ private slots: void setHtml(); void setHtmlWithResource(); void setHtmlWithBaseURL(); + void setHtmlWithJSAlert(); void ipv6HostEncoding(); void metaData(); +#if !defined(Q_WS_MAEMO_5) && !defined(Q_OS_SYMBIAN) + // as maemo 5 && symbian do not use QComboBoxes to implement the popups + // this test does not make sense for it. void popupFocus(); +#endif + void inputFieldFocus(); void hitTestContent(); void jsByteArray(); void ownership(); @@ -570,11 +617,14 @@ private slots: void hasSetFocus(); void render(); void scrollPosition(); + void scrollToAnchor(); + void scrollbarsOff(); void evaluateWillCauseRepaint(); void qObjectWrapperWithSameIdentity(); - void scrollRecursively(); void introspectQtMethods_data(); void introspectQtMethods(); + void setContent_data(); + void setContent(); private: QString evalJS(const QString&s) { @@ -645,13 +695,13 @@ private: QWebView* m_view; QWebPage* m_page; MyQObject* m_myObject; - QWebView* m_popupTestView; - int m_popupTestPaintCount; + QWebView* m_inputFieldsTestView; + int m_inputFieldTestPaintCount; }; tst_QWebFrame::tst_QWebFrame() : sTrue("true"), sFalse("false"), sUndefined("undefined"), sArray("array"), sFunction("function"), sError("error"), - sString("string"), sObject("object"), sNumber("number"), m_popupTestView(0), m_popupTestPaintCount(0) + sString("string"), sObject("object"), sNumber("number"), m_inputFieldsTestView(0), m_inputFieldTestPaintCount(0) { } @@ -661,10 +711,10 @@ tst_QWebFrame::~tst_QWebFrame() bool tst_QWebFrame::eventFilter(QObject* watched, QEvent* event) { - // used on the popupFocus test - if (watched == m_popupTestView) { + // used on the inputFieldFocus test + if (watched == m_inputFieldsTestView) { if (event->type() == QEvent::Paint) - m_popupTestPaintCount++; + m_inputFieldTestPaintCount++; } return QObject::eventFilter(watched, event); } @@ -685,6 +735,7 @@ void tst_QWebFrame::cleanup() void tst_QWebFrame::getSetStaticProperty() { + m_page->mainFrame()->setHtml("<html><head><body></body></html>"); QCOMPARE(evalJS("typeof myObject.noSuchProperty"), sUndefined); // initial value (set in MyQObject constructor) @@ -731,6 +782,21 @@ void tst_QWebFrame::getSetStaticProperty() { QString type; + QVariant ret = evalJSV("myObject.variantMapProperty", type); + QCOMPARE(type, sObject); + QCOMPARE(ret.type(), QVariant::Map); + QVariantMap vm = ret.value<QVariantMap>(); + QCOMPARE(vm.size(), 3); + QCOMPARE(vm.value("a").toInt(), 123); + QCOMPARE(vm.value("b").toString(), QLatin1String("foo")); + QCOMPARE(vm.value("c").value<QObject*>(), static_cast<QObject*>(m_myObject)); + } + QCOMPARE(evalJS("myObject.variantMapProperty.a === 123"), sTrue); + QCOMPARE(evalJS("myObject.variantMapProperty.b === 'foo'"), sTrue); + QCOMPARE(evalJS("myObject.variantMapProperty.c.variantMapProperty.b === 'foo'"), sTrue); + + { + QString type; QVariant ret = evalJSV("myObject.stringListProperty", type); QCOMPARE(type, sArray); QCOMPARE(ret.type(), QVariant::List); @@ -824,6 +890,8 @@ void tst_QWebFrame::getSetStaticProperty() QCOMPARE(evalJS("myObject.stringListProperty[1]"), QLatin1String("two")); QCOMPARE(evalJS("typeof myObject.stringListProperty[2]"), sString); QCOMPARE(evalJS("myObject.stringListProperty[2]"), QLatin1String("true")); + evalJS("myObject.webElementProperty=document.body;"); + QCOMPARE(evalJS("myObject.webElementProperty.tagName"), QLatin1String("BODY")); // try to delete QCOMPARE(evalJS("delete myObject.intProperty"), sFalse); @@ -860,6 +928,21 @@ void tst_QWebFrame::getSetStaticProperty() QCOMPARE(evalJS("myObject.readOnlyProperty = 654;" "myObject.readOnlyProperty == 987"), sTrue); QCOMPARE(m_myObject->readOnlyProperty(), 987); + + // QObject* property + m_myObject->setObjectStarProperty(0); + QCOMPARE(m_myObject->objectStarProperty(), (QObject*)0); + QCOMPARE(evalJS("myObject.objectStarProperty == null"), sTrue); + QCOMPARE(evalJS("typeof myObject.objectStarProperty"), sObject); + QCOMPARE(evalJS("Boolean(myObject.objectStarProperty)"), sFalse); + QCOMPARE(evalJS("String(myObject.objectStarProperty) == 'null'"), sTrue); + QCOMPARE(evalJS("myObject.objectStarProperty.objectStarProperty"), + sUndefined); + m_myObject->setObjectStarProperty(this); + QCOMPARE(evalJS("myObject.objectStarProperty != null"), sTrue); + QCOMPARE(evalJS("typeof myObject.objectStarProperty"), sObject); + QCOMPARE(evalJS("Boolean(myObject.objectStarProperty)"), sTrue); + QCOMPARE(evalJS("String(myObject.objectStarProperty) != 'null'"), sTrue); } void tst_QWebFrame::getSetDynamicProperty() @@ -1483,26 +1566,26 @@ void tst_QWebFrame::connectAndDisconnect() QString type; QString ret = evalJS("(function() { }).connect()", type); QCOMPARE(type, sError); - QCOMPARE(ret, QLatin1String("TypeError: Result of expression '(function() { }).connect' [undefined] is not a function.")); + QCOMPARE(ret, QLatin1String("TypeError: 'undefined' is not a function")); } { QString type; QString ret = evalJS("var o = { }; o.connect = Function.prototype.connect; o.connect()", type); QCOMPARE(type, sError); - QCOMPARE(ret, QLatin1String("TypeError: Result of expression 'o.connect' [undefined] is not a function.")); + QCOMPARE(ret, QLatin1String("TypeError: 'undefined' is not a function")); } { QString type; QString ret = evalJS("(function() { }).connect(123)", type); QCOMPARE(type, sError); - QCOMPARE(ret, QLatin1String("TypeError: Result of expression '(function() { }).connect' [undefined] is not a function.")); + QCOMPARE(ret, QLatin1String("TypeError: 'undefined' is not a function")); } { QString type; QString ret = evalJS("var o = { }; o.connect = Function.prototype.connect; o.connect(123)", type); QCOMPARE(type, sError); - QCOMPARE(ret, QLatin1String("TypeError: Result of expression 'o.connect' [undefined] is not a function.")); + QCOMPARE(ret, QLatin1String("TypeError: 'undefined' is not a function")); } { @@ -1886,6 +1969,13 @@ void tst_QWebFrame::overloadedSlots() f.call(QString(), QStringList() << m_engine->newVariant(QVariant("ciao"))); QCOMPARE(m_myObject->qtFunctionInvoked(), 35); */ + + // should pick myOverloadedSlot(QRegExp) + m_myObject->resetQtFunctionInvoked(); + evalJS("myObject.myOverloadedSlot(document.body)"); + QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=37319", Continue); + QCOMPARE(m_myObject->qtFunctionInvoked(), 36); + // should pick myOverloadedSlot(QObject*) m_myObject->resetQtFunctionInvoked(); evalJS("myObject.myOverloadedSlot(myObject)"); @@ -2299,7 +2389,9 @@ void tst_QWebFrame::javaScriptWindowObjectCleared_data() { QTest::addColumn<QString>("html"); QTest::addColumn<int>("signalCount"); - QTest::newRow("with <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 1; + QTest::newRow("with <script>") << "<html><body><script>i=0</script><p>hello world</p></body></html>" << 1; + // NOTE: Empty scripts no longer cause this signal to be emitted. + QTest::newRow("with empty <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 0; QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0; } @@ -2399,6 +2491,33 @@ void tst_QWebFrame::setHtmlWithBaseURL() QCOMPARE(m_view->page()->history()->count(), 0); } +class MyPage : public QWebPage +{ +public: + MyPage() : QWebPage(), alerts(0) {} + int alerts; + +protected: + virtual void javaScriptAlert(QWebFrame*, const QString& msg) + { + alerts++; + QCOMPARE(msg, QString("foo")); + // Should not be enough to trigger deferred loading, since we've upped the HTML + // tokenizer delay in the Qt frameloader. See HTMLTokenizer::continueProcessing() + QTest::qWait(1000); + } +}; + +void tst_QWebFrame::setHtmlWithJSAlert() +{ + QString html("<html><head></head><body><script>alert('foo');</script><p>hello world</p></body></html>"); + MyPage page; + m_view->setPage(&page); + page.mainFrame()->setHtml(html); + QCOMPARE(page.alerts, 1); + QCOMPARE(m_view->page()->mainFrame()->toHtml(), html); +} + class TestNetworkManager : public QNetworkAccessManager { public: @@ -2468,6 +2587,7 @@ void tst_QWebFrame::metaData() QCOMPARE(metaData.value("nonexistant"), QString()); } +#if !defined(Q_WS_MAEMO_5) && !defined(Q_OS_SYMBIAN) void tst_QWebFrame::popupFocus() { QWebView view; @@ -2485,42 +2605,61 @@ void tst_QWebFrame::popupFocus() " </body>" "</html>"); view.resize(400, 100); - view.show(); + // Call setFocus before show to work around http://bugreports.qt.nokia.com/browse/QTBUG-14762 view.setFocus(); + view.show(); + QTest::qWaitForWindowShown(&view); + view.activateWindow(); QTRY_VERIFY(view.hasFocus()); // open the popup by clicking. check if focus is on the popup - QTest::mouseClick(&view, Qt::LeftButton, 0, QPoint(25, 25)); - QObject* webpopup = firstChildByClassName(&view, "WebCore::QWebPopup"); + const QWebElement webCombo = view.page()->mainFrame()->documentElement().findFirst(QLatin1String("select[name=select]")); + QTest::mouseClick(&view, Qt::LeftButton, 0, webCombo.geometry().center()); + QObject* webpopup = firstChildByClassName(&view, "QComboBox"); QComboBox* combo = qobject_cast<QComboBox*>(webpopup); QVERIFY(combo != 0); QTRY_VERIFY(!view.hasFocus() && combo->view()->hasFocus()); // Focus should be on the popup // hide the popup and check if focus is on the page combo->hidePopup(); - QTRY_VERIFY(view.hasFocus() && !combo->view()->hasFocus()); // Focus should be back on the WebView + QTRY_VERIFY(view.hasFocus()); // Focus should be back on the WebView +} +#endif + +void tst_QWebFrame::inputFieldFocus() +{ + QWebView view; + view.setHtml("<html><body><input type=\"text\"></input></body></html>"); + view.resize(400, 100); + view.show(); + QTest::qWaitForWindowShown(&view); + view.activateWindow(); + view.setFocus(); + QTRY_VERIFY(view.hasFocus()); // double the flashing time, should at least blink once already int delay = qApp->cursorFlashTime() * 2; // focus the lineedit and check if it blinks - QTest::mouseClick(&view, Qt::LeftButton, 0, QPoint(200, 25)); - m_popupTestView = &view; + const QWebElement inputElement = view.page()->mainFrame()->documentElement().findFirst(QLatin1String("input[type=text]")); + QTest::mouseClick(&view, Qt::LeftButton, 0, inputElement.geometry().center()); + m_inputFieldsTestView = &view; view.installEventFilter( this ); QTest::qWait(delay); - QVERIFY2(m_popupTestPaintCount >= 3, + QVERIFY2(m_inputFieldTestPaintCount >= 3, "The input field should have a blinking caret"); } void tst_QWebFrame::hitTestContent() { - QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\">link text</a></body></html>"); + QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\" id=\"link\">link text</a></body></html>"); QWebPage page; QWebFrame* frame = page.mainFrame(); frame->setHtml(html); page.setViewportSize(QSize(200, 0)); //no height so link is not visible - QWebHitTestResult result = frame->hitTestContent(QPoint(10, 100)); + const QWebElement linkElement = frame->documentElement().findFirst(QLatin1String("a#link")); + QWebHitTestResult result = frame->hitTestContent(linkElement.geometry().center()); QCOMPARE(result.linkText(), QString("link text")); QWebElement link = result.linkElement(); QCOMPARE(link.attribute("target"), QString("_foo")); @@ -2741,6 +2880,70 @@ void tst_QWebFrame::scrollPosition() QCOMPARE(y, 29); } +void tst_QWebFrame::scrollToAnchor() +{ + QWebPage page; + page.setViewportSize(QSize(480, 800)); + QWebFrame* frame = page.mainFrame(); + + QString html("<html><body><p style=\"margin-bottom: 1500px;\">Hello.</p>" + "<p><a id=\"foo\">This</a> is an anchor</p>" + "<p style=\"margin-bottom: 1500px;\"><a id=\"bar\">This</a> is another anchor</p>" + "</body></html>"); + frame->setHtml(html); + frame->setScrollPosition(QPoint(0, 0)); + QCOMPARE(frame->scrollPosition().x(), 0); + QCOMPARE(frame->scrollPosition().y(), 0); + + QWebElement fooAnchor = frame->findFirstElement("a[id=foo]"); + + frame->scrollToAnchor("foo"); + QCOMPARE(frame->scrollPosition().y(), fooAnchor.geometry().top()); + + frame->scrollToAnchor("bar"); + frame->scrollToAnchor("foo"); + QCOMPARE(frame->scrollPosition().y(), fooAnchor.geometry().top()); + + frame->scrollToAnchor("top"); + QCOMPARE(frame->scrollPosition().y(), 0); + + frame->scrollToAnchor("bar"); + frame->scrollToAnchor("notexist"); + QVERIFY(frame->scrollPosition().y() != 0); +} + + +void tst_QWebFrame::scrollbarsOff() +{ + QWebView view; + QWebFrame* mainFrame = view.page()->mainFrame(); + + mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); + mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); + + QString html("<script>" \ + " function checkScrollbar() {" \ + " if (innerWidth === document.documentElement.offsetWidth)" \ + " document.getElementById('span1').innerText = 'SUCCESS';" \ + " else" \ + " document.getElementById('span1').innerText = 'FAIL';" \ + " }" \ + "</script>" \ + "<body>" \ + " <div style='margin-top:1000px ; margin-left:1000px'>" \ + " <a id='offscreen' href='a'>End</a>" \ + " </div>" \ + "<span id='span1'></span>" \ + "</body>"); + + + view.setHtml(html); + ::waitForSignal(&view, SIGNAL(loadFinished(bool))); + + mainFrame->evaluateJavaScript("checkScrollbar();"); + QCOMPARE(mainFrame->documentElement().findAll("span").at(0).toPlainText(), QString("SUCCESS")); +} + void tst_QWebFrame::evaluateWillCauseRepaint() { QWebView view; @@ -2749,12 +2952,7 @@ void tst_QWebFrame::evaluateWillCauseRepaint() view.setHtml(html); view.show(); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QTest::qWaitForWindowShown(&view); -#else - QTest::qWait(2000); -#endif - view.page()->mainFrame()->evaluateJavaScript( "document.getElementById('junk').style.display = 'none';"); @@ -2799,70 +2997,6 @@ void tst_QWebFrame::qObjectWrapperWithSameIdentity() QCOMPARE(mainFrame->toPlainText(), QString("test2")); } -void tst_QWebFrame::scrollRecursively() -{ - // The test content is - // a nested frame set - // The main frame scrolls - // and has two children - // an iframe and a div overflow - // both scroll - QWebView webView; - QWebPage* webPage = webView.page(); - QSignalSpy loadSpy(webPage, SIGNAL(loadFinished(bool))); - QUrl url = QUrl("qrc:///testiframe.html"); - webPage->mainFrame()->load(url); - QTRY_COMPARE(loadSpy.count(), 1); - - QList<QWebFrame*> children = webPage->mainFrame()->childFrames(); - QVERIFY(children.count() == 1); - - // 1st test - // call scrollRecursively over mainframe - // verify scrolled - // verify scroll postion changed - QPoint scrollPosition(webPage->mainFrame()->scrollPosition()); - QVERIFY(webPage->mainFrame()->scrollRecursively(10, 10)); - QVERIFY(scrollPosition != webPage->mainFrame()->scrollPosition()); - - // 2nd test - // call scrollRecursively over child iframe - // verify scrolled - // verify child scroll position changed - // verify parent's scroll position did not change - scrollPosition = webPage->mainFrame()->scrollPosition(); - QPoint childScrollPosition = children.at(0)->scrollPosition(); - QVERIFY(children.at(0)->scrollRecursively(10, 10)); - QVERIFY(scrollPosition == webPage->mainFrame()->scrollPosition()); - QVERIFY(childScrollPosition != children.at(0)->scrollPosition()); - - // 3rd test - // call scrollRecursively over div overflow - // verify scrolled == true - // verify parent and child frame's scroll postion did not change - QWebElement div = webPage->mainFrame()->documentElement().findFirst("#content1"); - QMouseEvent evpres(QEvent::MouseMove, div.geometry().center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); - webPage->event(&evpres); - scrollPosition = webPage->mainFrame()->scrollPosition(); - childScrollPosition = children.at(0)->scrollPosition(); - QVERIFY(webPage->mainFrame()->scrollRecursively(5, 5)); - QVERIFY(childScrollPosition == children.at(0)->scrollPosition()); - QVERIFY(scrollPosition == webPage->mainFrame()->scrollPosition()); - - // 4th test - // call scrollRecursively twice over childs iframe - // verify scrolled == true first time - // verify parent's scroll == true second time - // verify parent and childs scroll position changed - childScrollPosition = children.at(0)->scrollPosition(); - QVERIFY(children.at(0)->scrollRecursively(-10, -10)); - QVERIFY(childScrollPosition != children.at(0)->scrollPosition()); - scrollPosition = webPage->mainFrame()->scrollPosition(); - QVERIFY(children.at(0)->scrollRecursively(-10, -10)); - QVERIFY(scrollPosition != webPage->mainFrame()->scrollPosition()); - -} - void tst_QWebFrame::introspectQtMethods_data() { QTest::addColumn<QString>("objectExpression"); @@ -2905,5 +3039,34 @@ void tst_QWebFrame::introspectQtMethods() QVERIFY(evalJSV("var props=[]; for (var p in myObject.deleteLater) {props.push(p);}; props.sort()").toStringList().isEmpty()); } +void tst_QWebFrame::setContent_data() +{ + QTest::addColumn<QString>("mimeType"); + QTest::addColumn<QByteArray>("testContents"); + QTest::addColumn<QString>("expected"); + + QString str = QString::fromUtf8("ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει"); + QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str; + + QTextCodec *utf16 = QTextCodec::codecForName("UTF-16"); + if (utf16) + QTest::newRow("UTF-16 plain text") << "text/plain; charset=utf-16" << utf16->fromUnicode(str) << str; + + str = QString::fromUtf8("Une chaîne de caractères à sa façon."); + QTest::newRow("latin-1 plain text") << "text/plain; charset=iso-8859-1" << str.toLatin1() << str; + + +} + +void tst_QWebFrame::setContent() +{ + QFETCH(QString, mimeType); + QFETCH(QByteArray, testContents); + QFETCH(QString, expected); + m_view->setContent(testContents, mimeType); + QWebFrame* mainFrame = m_view->page()->mainFrame(); + QCOMPARE(expected , mainFrame->toPlainText()); +} + QTEST_MAIN(tst_QWebFrame) #include "tst_qwebframe.moc" diff --git a/WebKit/qt/tests/qwebhistory/qwebhistory.pro b/WebKit/qt/tests/qwebhistory/qwebhistory.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebhistory/qwebhistory.pro +++ b/WebKit/qt/tests/qwebhistory/qwebhistory.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp b/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp index e967dcc..783214c 100644 --- a/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp +++ b/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp @@ -59,6 +59,8 @@ private slots: void saveAndRestore_crash_1(); void saveAndRestore_crash_2(); void saveAndRestore_crash_3(); + void popPushState_data(); + void popPushState(); void clear(); @@ -82,7 +84,7 @@ void tst_QWebHistory::init() { page = new QWebPage(this); frame = page->mainFrame(); - connect(page, SIGNAL(loadFinished(bool)), &waitForLoadFinished, SLOT(quit())); + connect(page, SIGNAL(loadFinished(bool)), &waitForLoadFinished, SLOT(quit()), Qt::QueuedConnection); for (int i = 1;i < 6;i++) { loadPage(i); @@ -124,6 +126,7 @@ void tst_QWebHistory::back() } //try one more time (too many). crash test hist->back(); + QCOMPARE(page->mainFrame()->toPlainText(), QString("page1")); } /** @@ -144,6 +147,7 @@ void tst_QWebHistory::forward() } //try one more time (too many). crash test hist->forward(); + QCOMPARE(page->mainFrame()->toPlainText(), QString("page") + QString::number(histsize)); } /** @@ -349,6 +353,25 @@ void tst_QWebHistory::saveAndRestore_crash_3() delete page2; } +void tst_QWebHistory::popPushState_data() +{ + QTest::addColumn<QString>("script"); + QTest::newRow("pushState") << "history.pushState(123, \"foo\");"; + QTest::newRow("replaceState") << "history.replaceState(\"a\", \"b\");"; + QTest::newRow("back") << "history.back();"; + QTest::newRow("forward") << "history.forward();"; + QTest::newRow("clearState") << "history.clearState();"; +} + +/** Crash test, WebKit bug 38840 (https://bugs.webkit.org/show_bug.cgi?id=38840) */ +void tst_QWebHistory::popPushState() +{ + QFETCH(QString, script); + QWebPage page; + page.mainFrame()->setHtml("<html><body>long live Qt!</body></html>"); + page.mainFrame()->evaluateJavaScript(script); +} + /** ::clear */ void tst_QWebHistory::clear() { diff --git a/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro b/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro +++ b/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp b/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp index 435cada..84b12d2 100644 --- a/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp +++ b/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp @@ -23,6 +23,7 @@ #include <qwebpage.h> #include <qwebview.h> #include <qwebframe.h> +#include <qwebelement.h> #include <qwebhistoryinterface.h> #include <QDebug> @@ -85,9 +86,10 @@ public: 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")); + m_view->setHtml("<html><style>:link{color:green}:visited{color:red}</style><body><a href='http://www.trolltech.com' id='vlink'>Trolltech</a></body></html>"); + QWebElement anchor = m_view->page()->mainFrame()->findFirstElement("a[id=vlink]"); + QString linkColor = anchor.styleProperty("color", QWebElement::ComputedStyle); + QCOMPARE(linkColor, QString::fromLatin1("rgb(255, 0, 0)")); } QTEST_MAIN(tst_QWebHistoryInterface) diff --git a/WebKit/qt/tests/qwebinspector/qwebinspector.pro b/WebKit/qt/tests/qwebinspector/qwebinspector.pro index e99c7f4..e915d60 100644 --- a/WebKit/qt/tests/qwebinspector/qwebinspector.pro +++ b/WebKit/qt/tests/qwebinspector/qwebinspector.pro @@ -1 +1,3 @@ +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebpage/qwebpage.pro b/WebKit/qt/tests/qwebpage/qwebpage.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebpage/qwebpage.pro +++ b/WebKit/qt/tests/qwebpage/qwebpage.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index ba7a87e..c27ba02 100644 --- a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -20,12 +20,16 @@ */ #include "../util.h" +#include "../WebCoreSupport/DumpRenderTreeSupportQt.h" #include <QDir> #include <QGraphicsWidget> #include <QLineEdit> +#include <QLocale> #include <QMenu> #include <QPushButton> +#include <QStyle> #include <QtTest/QtTest> +#include <QTextCharFormat> #include <qgraphicsscene.h> #include <qgraphicsview.h> #include <qgraphicswebview.h> @@ -37,6 +41,7 @@ #include <qwebpage.h> #include <qwebsecurityorigin.h> #include <qwebview.h> +#include <qimagewriter.h> class EventSpy : public QObject, public QList<QEvent::Type> { @@ -72,14 +77,15 @@ private slots: void cleanupTestCase(); void acceptNavigationRequest(); - void infiniteLoopJS(); + void geolocationRequestJS(); void loadFinished(); void acceptNavigationRequestWithNewWindow(); void userStyleSheet(); void modified(); void contextMenuCrash(); void database(); - void createPlugin(); + void createPluginWithPluginsEnabled(); + void createPluginWithPluginsDisabled(); void destroyPlugin_data(); void destroyPlugin(); void createViewlessPlugin_data(); @@ -91,6 +97,7 @@ private slots: void backActionUpdate(); void frameAt(); void requestCache(); + void loadCachedPage(); void protectBindingsRuntimeObjectsFromCollector(); void localURLSchemes(); void testOptionalJSObjects(); @@ -98,10 +105,16 @@ private slots: void consoleOutput(); void inputMethods_data(); void inputMethods(); + void inputMethodsTextFormat_data(); + void inputMethodsTextFormat(); void defaultTextEncoding(); void errorPageExtension(); void errorPageExtensionInIFrames(); void errorPageExtensionInFrameset(); + void userAgentApplicationName(); + void userAgentLocaleChange(); + + void viewModes(); void crashTests_LazyInitializationOfMainFrame(); @@ -111,7 +124,11 @@ private slots: void originatingObjectInNetworkRequests(); void testJSPrompt(); void showModalDialog(); - + void testStopScheduledPageRefresh(); + void findText(); + void supportedContentType(); + void infiniteLoopJS(); + private: QWebView* m_view; QWebPage* m_page; @@ -201,16 +218,64 @@ public: public slots: bool shouldInterruptJavaScript() { - return true; + return true; + } + void requestPermission(QWebFrame* frame, QWebPage::Feature feature) + { + if (m_allowGeolocation) + setFeaturePermission(frame, feature, PermissionGrantedByUser); + else + setFeaturePermission(frame, feature, PermissionDeniedByUser); + } + +public: + void setGeolocationPermission(bool allow) + { + m_allowGeolocation = allow; } + +private: + bool m_allowGeolocation; }; 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->setHtml(QString("<html><body>test</body></html>"), QUrl()); m_view->page()->mainFrame()->evaluateJavaScript("var run = true;var a = 1;while(run){a++;}"); + delete newPage; +} + +void tst_QWebPage::geolocationRequestJS() +{ + /* + This test is disabled because it can only succeed if ENABLE(GEOLOCATION) is true. + The code needs to be updated when the API of requestPermissionFromUser is updated. + */ + QSKIP("Test disabled as long as geolocation is disabled from the build.", SkipSingle); + + JSTestPage* newPage = new JSTestPage(m_view); + connect(newPage, SIGNAL(requestPermissionFromUser(QWebFrame*, QWebPage::Feature)), + newPage, SLOT(requestPermission(QWebFrame*, QWebPage::Feature))); + + newPage->setGeolocationPermission(false); + m_view->setPage(newPage); + m_view->setHtml(QString("<html><body>test</body></html>"), QUrl()); + m_view->page()->mainFrame()->evaluateJavaScript("var errorCode = 0; function error(err) { errorCode = err.code; } function success(pos) { } navigator.geolocation.getCurrentPosition(success, error)"); + QTest::qWait(2000); + QVariant empty = m_view->page()->mainFrame()->evaluateJavaScript("errorCode"); + + QVERIFY(empty.type() == QVariant::Double && empty.toInt() != 0); + + newPage->setGeolocationPermission(true); + m_view->page()->mainFrame()->evaluateJavaScript("errorCode = 0; navigator.geolocation.getCurrentPosition(success, error);"); + empty = m_view->page()->mainFrame()->evaluateJavaScript("errorCode"); + + //http://dev.w3.org/geo/api/spec-source.html#position + //PositionError: const unsigned short PERMISSION_DENIED = 1; + QVERIFY(empty.type() == QVariant::Double && empty.toInt() != 1); + delete newPage; } void tst_QWebPage::loadFinished() @@ -220,9 +285,9 @@ void tst_QWebPage::loadFinished() QSignalSpy spyLoadStarted(m_view, SIGNAL(loadStarted())); QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); - m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," - "<head><meta http-equiv='refresh' content='1'></head>foo \">" - "<frame src=\"data:text/html,bar\"></frameset>"), QUrl()); + m_view->page()->mainFrame()->load(QUrl("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," + "<head><meta http-equiv='refresh' content='1'></head>foo \">" + "<frame src=\"data:text/html,bar\"></frameset>")); QTRY_COMPARE(spyLoadFinished.count(), 1); QTRY_VERIFY(spyLoadStarted.count() > 1); @@ -230,8 +295,8 @@ void tst_QWebPage::loadFinished() spyLoadFinished.clear(); - m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," - "foo \"><frame src=\"data:text/html,bar\"></frameset>"), QUrl()); + m_view->page()->mainFrame()->load(QUrl("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," + "foo \"><frame src=\"data:text/html,bar\"></frameset>")); QTRY_COMPARE(spyLoadFinished.count(), 1); QCOMPARE(spyLoadFinished.count(), 1); } @@ -350,6 +415,21 @@ void tst_QWebPage::userStyleSheet() QCOMPARE(networkManager->requestedUrls.at(0), QUrl("http://does.not/exist.png")); } +void tst_QWebPage::viewModes() +{ + m_view->setHtml("<body></body>"); + m_page->setProperty("_q_viewMode", "minimized"); + + QVariant empty = m_page->mainFrame()->evaluateJavaScript("window.styleMedia.matchMedium(\"(-webkit-view-mode)\")"); + QVERIFY(empty.type() == QVariant::Bool && empty.toBool()); + + QVariant minimized = m_page->mainFrame()->evaluateJavaScript("window.styleMedia.matchMedium(\"(-webkit-view-mode: minimized)\")"); + QVERIFY(minimized.type() == QVariant::Bool && minimized.toBool()); + + QVariant maximized = m_page->mainFrame()->evaluateJavaScript("window.styleMedia.matchMedium(\"(-webkit-view-mode: maximized)\")"); + QVERIFY(maximized.type() == QVariant::Bool && !maximized.toBool()); +} + void tst_QWebPage::modified() { m_page->mainFrame()->setUrl(QUrl("data:text/html,<body>blub")); @@ -515,27 +595,20 @@ protected: } }; -void tst_QWebPage::createPlugin() +static void createPlugin(QWebView *view) { - QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); + QSignalSpy loadSpy(view, SIGNAL(loadFinished(bool))); - PluginPage* newPage = new PluginPage(m_view); - m_view->setPage(newPage); + PluginPage* newPage = new PluginPage(view); + view->setPage(newPage); - // plugins not enabled by default, so the plugin shouldn't be loaded - m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); + // type has to be application/x-qt-plugin + view->setHtml(QString("<html><body><object type='application/x-foobarbaz' classid='pushbutton' id='mybutton'/></body></html>")); QTRY_COMPARE(loadSpy.count(), 1); QCOMPARE(newPage->calls.count(), 0); - m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); - - // type has to be application/x-qt-plugin - m_view->setHtml(QString("<html><body><object type='application/x-foobarbaz' classid='pushbutton' id='mybutton'/></body></html>")); + view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); QTRY_COMPARE(loadSpy.count(), 2); - QCOMPARE(newPage->calls.count(), 0); - - m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); - QTRY_COMPARE(loadSpy.count(), 3); QCOMPARE(newPage->calls.count(), 1); { PluginPage::CallInfo ci = newPage->calls.takeFirst(); @@ -566,11 +639,11 @@ void tst_QWebPage::createPlugin() QCOMPARE(newPage->mainFrame()->evaluateJavaScript("mybutton.clicked.toString()").toString(), QString::fromLatin1("function clicked() {\n [native code]\n}")); - m_view->setHtml(QString("<html><body><table>" + view->setHtml(QString("<html><body><table>" "<tr><object type='application/x-qt-plugin' classid='lineedit' id='myedit'/></tr>" "<tr><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></tr>" "</table></body></html>"), QUrl("http://foo.bar.baz")); - QTRY_COMPARE(loadSpy.count(), 4); + QTRY_COMPARE(loadSpy.count(), 3); QCOMPARE(newPage->calls.count(), 2); { PluginPage::CallInfo ci = newPage->calls.takeFirst(); @@ -602,14 +675,22 @@ void tst_QWebPage::createPlugin() QVERIFY(ci.returnValue != 0); QVERIFY(ci.returnValue->inherits("QPushButton")); } +} - m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, false); - - m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); - QTRY_COMPARE(loadSpy.count(), 5); - QCOMPARE(newPage->calls.count(), 0); +void tst_QWebPage::createPluginWithPluginsEnabled() +{ + m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + createPlugin(m_view); } +void tst_QWebPage::createPluginWithPluginsDisabled() +{ + // Qt Plugins should be loaded by QtWebKit even when PluginsEnabled is + // false. The client decides whether a Qt plugin is enabled or not when + // it decides whether or not to instantiate it. + m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, false); + createPlugin(m_view); +} // Standard base class for template PluginTracerPage. In tests it is used as interface. class PluginCounterPage : public QWebPage { @@ -722,10 +803,6 @@ void tst_QWebPage::createViewlessPlugin() } -// import private API -void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName); -QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page); - void tst_QWebPage::multiplePageGroupsAndLocalStorage() { QDir dir(QDir::currentPath()); @@ -737,12 +814,12 @@ void tst_QWebPage::multiplePageGroupsAndLocalStorage() view1.page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true); view1.page()->settings()->setLocalStoragePath(QDir::toNativeSeparators(QDir::currentPath() + "/path1")); - qt_webpage_setGroupName(view1.page(), "group1"); + DumpRenderTreeSupportQt::webPageSetGroupName(view1.page(), "group1"); view2.page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true); view2.page()->settings()->setLocalStoragePath(QDir::toNativeSeparators(QDir::currentPath() + "/path2")); - qt_webpage_setGroupName(view2.page(), "group2"); - QCOMPARE(qt_webpage_groupName(view1.page()), QString("group1")); - QCOMPARE(qt_webpage_groupName(view2.page()), QString("group2")); + DumpRenderTreeSupportQt::webPageSetGroupName(view2.page(), "group2"); + QCOMPARE(DumpRenderTreeSupportQt::webPageGroupName(view1.page()), QString("group1")); + QCOMPARE(DumpRenderTreeSupportQt::webPageGroupName(view2.page()), QString("group2")); view1.setHtml(QString("<html><body> </body></html>"), QUrl("http://www.myexample.com")); @@ -797,7 +874,7 @@ public: void tst_QWebPage::cursorMovements() { CursorTrackedPage* page = new CursorTrackedPage; - QString content("<html><body<p id=one>The quick brown fox</p><p id=two>jumps over the lazy dog</p><p>May the source<br/>be with you!</p></body></html>"); + QString content("<html><body><p id=one>The quick brown fox</p><p id=two>jumps over the lazy dog</p><p>May the source<br/>be with you!</p></body></html>"); page->mainFrame()->setHtml(content); // this will select the first paragraph @@ -989,7 +1066,7 @@ void tst_QWebPage::cursorMovements() void tst_QWebPage::textSelection() { CursorTrackedPage* page = new CursorTrackedPage; - QString content("<html><body<p id=one>The quick brown fox</p>" \ + QString content("<html><body><p id=one>The quick brown fox</p>" \ "<p id=two>jumps over the lazy dog</p>" \ "<p>May the source<br/>be with you!</p></body></html>"); page->mainFrame()->setHtml(content); @@ -1077,7 +1154,7 @@ void tst_QWebPage::textSelection() void tst_QWebPage::textEditing() { CursorTrackedPage* page = new CursorTrackedPage; - QString content("<html><body<p id=one>The quick brown fox</p>" \ + QString content("<html><body><p id=one>The quick brown fox</p>" \ "<p id=two>jumps over the lazy dog</p>" \ "<p>May the source<br/>be with you!</p></body></html>"); page->mainFrame()->setHtml(content); @@ -1220,6 +1297,37 @@ void tst_QWebPage::requestCache() (int)QNetworkRequest::PreferCache); } +void tst_QWebPage::loadCachedPage() +{ + TestPage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + page.settings()->setMaximumPagesInCache(3); + + page.mainFrame()->load(QUrl("data:text/html,This is first page")); + + QTRY_COMPARE(loadSpy.count(), 1); + QTRY_COMPARE(page.navigations.count(), 1); + + QUrl firstPageUrl = page.mainFrame()->url(); + page.mainFrame()->load(QUrl("data:text/html,This is second page")); + + QTRY_COMPARE(loadSpy.count(), 2); + QTRY_COMPARE(page.navigations.count(), 2); + + page.triggerAction(QWebPage::Stop); + QVERIFY(page.history()->canGoBack()); + + QSignalSpy urlSpy(page.mainFrame(), SIGNAL(urlChanged(QUrl))); + QVERIFY(urlSpy.isValid()); + + page.triggerAction(QWebPage::Back); + ::waitForSignal(page.mainFrame(), SIGNAL(urlChanged(QUrl))); + QCOMPARE(urlSpy.size(), 1); + + QList<QVariant> arguments1 = urlSpy.takeFirst(); + QCOMPARE(arguments1.at(0).toUrl(), firstPageUrl); + +} void tst_QWebPage::backActionUpdate() { QWebView view; @@ -1268,12 +1376,9 @@ void tst_QWebPage::inputMethods_data() { QTest::addColumn<QString>("viewType"); QTest::newRow("QWebView") << "QWebView"; -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QTest::newRow("QGraphicsWebView") << "QGraphicsWebView"; -#endif } -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) static Qt::InputMethodHints inputMethodHints(QObject* object) { if (QGraphicsObject* o = qobject_cast<QGraphicsObject*>(object)) @@ -1282,14 +1387,11 @@ static Qt::InputMethodHints inputMethodHints(QObject* object) return w->inputMethodHints(); return Qt::InputMethodHints(); } -#endif static bool inputMethodEnabled(QObject* object) { -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) if (QGraphicsObject* o = qobject_cast<QGraphicsObject*>(object)) return o->flags() & QGraphicsItem::ItemAcceptsInputMethod; -#endif if (QWidget* w = qobject_cast<QWidget*>(object)) return w->testAttribute(Qt::WA_InputMethodEnabled); return false; @@ -1306,9 +1408,7 @@ void tst_QWebPage::inputMethods() wv->setPage(page); view = wv; container = view; - } -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) - else if (viewType == "QGraphicsWebView") { + } else if (viewType == "QGraphicsWebView") { QGraphicsWebView* wv = new QGraphicsWebView; wv->setPage(page); view = wv; @@ -1320,9 +1420,7 @@ void tst_QWebPage::inputMethods() wv->setGeometry(QRect(0, 0, 500, 500)); container = gv; - } -#endif - else + } else QVERIFY2(false, "Unknown view type"); page->settings()->setFontFamily(QWebSettings::SerifFont, "FooSerifFont"); @@ -1341,17 +1439,32 @@ void tst_QWebPage::inputMethods() QMouseEvent evrel(QEvent::MouseButtonRelease, inputs.at(0).geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); page->event(&evrel); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) - QVERIFY(!viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); -#endif + // This part of the test checks if the SIP (Software Input Panel) is triggered, + // which normally happens on mobile platforms, when a user input form receives + // a mouse click. + int inputPanel = 0; + if (viewType == "QWebView") { + if (QWebView* wv = qobject_cast<QWebView*>(view)) + inputPanel = wv->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel); + } else if (viewType == "QGraphicsWebView") { + if (QGraphicsWebView* wv = qobject_cast<QGraphicsWebView*>(view)) + inputPanel = wv->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel); + } + + // For non-mobile platforms RequestSoftwareInputPanel event is not called + // because there is no SIP (Software Input Panel) triggered. In the case of a + // mobile platform, an input panel, e.g. virtual keyboard, is usually invoked + // and the RequestSoftwareInputPanel event is called. For these two situations + // this part of the test can verified as the checks below. + if (inputPanel) + QVERIFY(viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); + else + QVERIFY(!viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); viewEventSpy.clear(); page->event(&evpres); page->event(&evrel); - -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QVERIFY(viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); -#endif //ImMicroFocus QVariant variant = page->inputMethodQuery(Qt::ImMicroFocus); @@ -1379,7 +1492,6 @@ void tst_QWebPage::inputMethods() page->event(&eventText); } -#if QT_VERSION >= 0x040600 //ImMaximumTextLength variant = page->inputMethodQuery(Qt::ImMaximumTextLength); QCOMPARE(20, variant.toInt()); @@ -1403,14 +1515,32 @@ void tst_QWebPage::inputMethods() variant = page->inputMethodQuery(Qt::ImCurrentSelection); QString selectionValue = variant.value<QString>(); QCOMPARE(selectionValue, QString("eb")); -#endif + + //Set selection with negative length + inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 6, -5, QVariant()); + QInputMethodEvent eventSelection3("",inputAttributes); + page->event(&eventSelection3); + + //ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 1); + + //ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 6); + + //ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("tWebK")); //ImSurroundingText variant = page->inputMethodQuery(Qt::ImSurroundingText); QString value = variant.value<QString>(); QCOMPARE(value, QString("QtWebKit")); -#if QT_VERSION >= 0x040600 { QList<QInputMethodEvent::Attribute> attributes; // Clear the selection, so the next test does not clear any contents. @@ -1424,7 +1554,112 @@ void tst_QWebPage::inputMethods() variant = page->inputMethodQuery(Qt::ImSurroundingText); value = variant.value<QString>(); QCOMPARE(value, QString("QtWebKit")); -#endif + + // Cancel current composition first + inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant()); + QInputMethodEvent eventSelection4("", inputAttributes); + page->event(&eventSelection4); + + // START - Tests for Selection when the Editor is NOT in Composition mode + + // LEFT to RIGHT selection + // Deselect the selection by sending MouseButtonPress events + // This moves the current cursor to the end of the text + page->event(&evpres); + page->event(&evrel); + + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event(QString(), attributes); + event.setCommitString("XXX", 0, 0); + page->event(&event); + event.setCommitString(QString(), -2, 2); // Erase two characters. + page->event(&event); + event.setCommitString(QString(), -1, 1); // Erase one character. + page->event(&event); + variant = page->inputMethodQuery(Qt::ImSurroundingText); + value = variant.value<QString>(); + QCOMPARE(value, QString("QtWebKit")); + } + + //Move to the start of the line + page->triggerAction(QWebPage::MoveToStartOfLine); + + QKeyEvent keyRightEventPress(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); + QKeyEvent keyRightEventRelease(QEvent::KeyRelease, Qt::Key_Right, Qt::NoModifier); + + //Move 2 characters RIGHT + for (int j = 0; j < 2; ++j) { + page->event(&keyRightEventPress); + page->event(&keyRightEventRelease); + } + + //Select to the end of the line + page->triggerAction(QWebPage::SelectEndOfLine); + + //ImAnchorPosition QtWebKit + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 2); + + //ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 8); + + //ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("WebKit")); + + //RIGHT to LEFT selection + //Deselect the selection (this moves the current cursor to the end of the text) + page->event(&evpres); + page->event(&evrel); + + //ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 8); + + //ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 8); + + //ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + QKeyEvent keyLeftEventPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QKeyEvent keyLeftEventRelease(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier); + + //Move 2 characters LEFT + for (int i = 0; i < 2; ++i) { + page->event(&keyLeftEventPress); + page->event(&keyLeftEventRelease); + } + + //Select to the start of the line + page->triggerAction(QWebPage::SelectStartOfLine); + + //ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 6); + + //ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 0); + + //ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("QtWebK")); + + //END - Tests for Selection when the Editor is not in Composition mode //ImhHiddenText QMouseEvent evpresPassword(QEvent::MouseButtonPress, inputs.at(1).geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); @@ -1433,13 +1668,11 @@ void tst_QWebPage::inputMethods() page->event(&evrelPassword); QVERIFY(inputMethodEnabled(view)); -#if QT_VERSION >= 0x040600 QVERIFY(inputMethodHints(view) & Qt::ImhHiddenText); page->event(&evpres); page->event(&evrel); QVERIFY(!(inputMethodHints(view) & Qt::ImhHiddenText)); -#endif page->mainFrame()->setHtml("<html><body><p>nothing to input here"); viewEventSpy.clear(); @@ -1452,15 +1685,383 @@ void tst_QWebPage::inputMethods() page->event(&evrel); } -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QVERIFY(!viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); -#endif + + //START - Test for sending empty QInputMethodEvent + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input3' value='QtWebKit2'/>" \ + "</body></html>"); + page->mainFrame()->evaluateJavaScript("var inputEle = document.getElementById('input3'); inputEle.focus(); inputEle.select();"); + + //Send empty QInputMethodEvent + QInputMethodEvent emptyEvent; + page->event(&emptyEvent); + + QString inputValue = page->mainFrame()->evaluateJavaScript("document.getElementById('input3').value").toString(); + QCOMPARE(inputValue, QString("QtWebKit2")); + //END - Test for sending empty QInputMethodEvent + + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input4' value='QtWebKit inputMethod'/>" \ + "</body></html>"); + page->mainFrame()->evaluateJavaScript("var inputEle = document.getElementById('input4'); inputEle.focus(); inputEle.select();"); + + // Clear the selection, also cancel the ongoing composition if there is one. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant()); + attributes.append(newSelection); + QInputMethodEvent event("", attributes); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + variant = page->inputMethodQuery(Qt::ImSurroundingText); + QString surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("QtWebKit inputMethod")); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 0); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 0); + + // 1. Insert a character to the begining of the line. + // Send temporary text, which makes the editor has composition 'm'. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("m", attributes); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("QtWebKit inputMethod")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 0); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 0); + + // Send temporary text, which makes the editor has composition 'n'. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("n", attributes); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("QtWebKit inputMethod")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 0); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 0); + + // Send commit text, which makes the editor conforms composition. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("", attributes); + event.setCommitString("o"); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oQtWebKit inputMethod")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 1); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 1); + + // 2. insert a character to the middle of the line. + // Send temporary text, which makes the editor has composition 'd'. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("d", attributes); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oQtWebKit inputMethod")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 1); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 1); + + // Send commit text, which makes the editor conforms composition. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("", attributes); + event.setCommitString("e"); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oeQtWebKit inputMethod")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 2); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 2); + + // 3. Insert a character to the end of the line. + page->triggerAction(QWebPage::MoveToEndOfLine); + + // Send temporary text, which makes the editor has composition 't'. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("t", attributes); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oeQtWebKit inputMethod")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 22); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 22); + + // Send commit text, which makes the editor conforms composition. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("", attributes); + event.setCommitString("t"); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oeQtWebKit inputMethodt")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 23); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 23); + + // 4. Replace the selection. + page->triggerAction(QWebPage::SelectPreviousWord); + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("inputMethodt")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oeQtWebKit inputMethodt")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 11); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 23); + + // Send temporary text, which makes the editor has composition 'w'. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("w", attributes); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oeQtWebKit ")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 11); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 11); + + // Send commit text, which makes the editor conforms composition. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("", attributes); + event.setCommitString("2"); + page->event(&event); + } + + // ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("")); + + // ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + surroundingValue = variant.value<QString>(); + QCOMPARE(surroundingValue, QString("oeQtWebKit 2")); + + // ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 12); + + // ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 12); delete container; } -// import a little DRT helper function to trigger the garbage collector -void QWEBKIT_EXPORT qt_drt_garbageCollector_collect(); +void tst_QWebPage::inputMethodsTextFormat_data() +{ + QTest::addColumn<QString>("string"); + QTest::addColumn<int>("start"); + QTest::addColumn<int>("length"); + + QTest::newRow("") << QString("") << 0 << 0; + QTest::newRow("Q") << QString("Q") << 0 << 1; + QTest::newRow("Qt") << QString("Qt") << 0 << 1; + QTest::newRow("Qt") << QString("Qt") << 0 << 2; + QTest::newRow("Qt") << QString("Qt") << 1 << 1; + QTest::newRow("Qt ") << QString("Qt ") << 0 << 1; + QTest::newRow("Qt ") << QString("Qt ") << 1 << 1; + QTest::newRow("Qt ") << QString("Qt ") << 2 << 1; + QTest::newRow("Qt ") << QString("Qt ") << 2 << -1; + QTest::newRow("Qt ") << QString("Qt ") << -2 << 3; + QTest::newRow("Qt ") << QString("Qt ") << 0 << 3; + QTest::newRow("Qt by") << QString("Qt by") << 0 << 1; + QTest::newRow("Qt by Nokia") << QString("Qt by Nokia") << 0 << 1; +} + + +void tst_QWebPage::inputMethodsTextFormat() +{ + QWebPage* page = new QWebPage; + QWebView* view = new QWebView; + view->setPage(page); + page->settings()->setFontFamily(QWebSettings::SerifFont, "FooSerifFont"); + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input1' style='font-family: serif' value='' maxlength='20'/>"); + page->mainFrame()->evaluateJavaScript("document.getElementById('input1').focus()"); + page->mainFrame()->setFocus(); + view->show(); + + QFETCH(QString, string); + QFETCH(int, start); + QFETCH(int, length); + + QList<QInputMethodEvent::Attribute> attrs; + QTextCharFormat format; + format.setUnderlineStyle(QTextCharFormat::SingleUnderline); + format.setUnderlineColor(Qt::red); + attrs.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, start, length, format)); + QInputMethodEvent im(string, attrs); + page->event(&im); + + QTest::qWait(1000); + + delete view; +} void tst_QWebPage::protectBindingsRuntimeObjectsFromCollector() { @@ -1478,7 +2079,7 @@ void tst_QWebPage::protectBindingsRuntimeObjectsFromCollector() newPage->mainFrame()->evaluateJavaScript("testme('foo')"); - qt_drt_garbageCollector_collect(); + DumpRenderTreeSupportQt::garbageCollectorCollect(); // don't crash! newPage->mainFrame()->evaluateJavaScript("testme('bar')"); @@ -1603,7 +2204,8 @@ public: { ErrorPageExtensionReturn* errorPage = static_cast<ErrorPageExtensionReturn*>(output); - errorPage->content = "data:text/html,error"; + errorPage->contentType = "text/html"; + errorPage->content = "error"; return true; } }; @@ -1620,7 +2222,7 @@ void tst_QWebPage::errorPageExtension() page->mainFrame()->setUrl(QUrl("http://non.existent/url")); QTRY_COMPARE(spyLoadFinished.count(), 2); - QCOMPARE(page->mainFrame()->toPlainText(), QString("data:text/html,error")); + QCOMPARE(page->mainFrame()->toPlainText(), QString("error")); QCOMPARE(page->history()->count(), 2); QCOMPARE(page->history()->currentItem().url(), QUrl("http://non.existent/url")); QCOMPARE(page->history()->canGoBack(), true); @@ -1647,14 +2249,15 @@ void tst_QWebPage::errorPageExtensionInIFrames() ErrorPage* page = new ErrorPage; m_view->setPage(page); - m_view->setHtml(QString("data:text/html," - "<h1>h1</h1>" - "<iframe src='data:text/html,<p/>p'></iframe>" - "<iframe src='non-existent.html'></iframe>")); + m_view->page()->mainFrame()->load(QUrl( + "data:text/html," + "<h1>h1</h1>" + "<iframe src='data:text/html,<p/>p'></iframe>" + "<iframe src='http://non.existent/url'></iframe>")); QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); QTRY_COMPARE(spyLoadFinished.count(), 1); - QCOMPARE(page->mainFrame()->childFrames()[1]->toPlainText(), QString("data:text/html,error")); + QCOMPARE(page->mainFrame()->childFrames()[1]->toPlainText(), QString("error")); m_view->setPage(0); } @@ -1668,11 +2271,43 @@ void tst_QWebPage::errorPageExtensionInFrameset() QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); QTRY_COMPARE(spyLoadFinished.count(), 1); - QCOMPARE(page->mainFrame()->childFrames()[1]->toPlainText(), QString("data:text/html,error")); + QCOMPARE(page->mainFrame()->childFrames()[1]->toPlainText(), QString("error")); m_view->setPage(0); } +class FriendlyWebPage : public QWebPage +{ +public: + friend class tst_QWebPage; +}; + +void tst_QWebPage::userAgentApplicationName() +{ + const QString oldApplicationName = QCoreApplication::applicationName(); + FriendlyWebPage page; + + const QString applicationNameMarker = QString::fromUtf8("StrangeName\342\210\236"); + QCoreApplication::setApplicationName(applicationNameMarker); + QVERIFY(page.userAgentForUrl(QUrl()).contains(applicationNameMarker)); + + QCoreApplication::setApplicationName(oldApplicationName); +} + +void tst_QWebPage::userAgentLocaleChange() +{ + FriendlyWebPage page; + m_view->setPage(&page); + + const QString markerString = QString::fromLatin1(" nn-NO)"); + + if (page.userAgentForUrl(QUrl()).contains(markerString)) + QSKIP("marker string already present", SkipSingle); + + m_view->setLocale(QLocale(QString::fromLatin1("nn_NO"))); + QVERIFY(page.userAgentForUrl(QUrl()).contains(markerString)); +} + void tst_QWebPage::crashTests_LazyInitializationOfMainFrame() { { @@ -1746,7 +2381,7 @@ void tst_QWebPage::originatingObjectInNetworkRequests() m_page->setNetworkAccessManager(networkManager); networkManager->requests.clear(); - m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," + m_view->setHtml(QString("<frameset cols=\"25%,75%\"><frame src=\"data:text/html," "<head><meta http-equiv='refresh' content='1'></head>foo \">" "<frame src=\"data:text/html,bar\"></frameset>"), QUrl()); QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); @@ -1756,10 +2391,8 @@ void tst_QWebPage::originatingObjectInNetworkRequests() QList<QWebFrame*> childFrames = m_page->mainFrame()->childFrames(); QCOMPARE(childFrames.count(), 2); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) for (int i = 0; i < 2; ++i) QVERIFY(qobject_cast<QWebFrame*>(networkManager->requests.at(i).originatingObject()) == childFrames.at(i)); -#endif } /** @@ -1850,5 +2483,121 @@ void tst_QWebPage::showModalDialog() QCOMPARE(res, QString("This is a test")); } +void tst_QWebPage::testStopScheduledPageRefresh() +{ + // Without QWebPage::StopScheduledPageRefresh + QWebPage page1; + page1.setNetworkAccessManager(new TestNetworkManager(&page1)); + page1.mainFrame()->setHtml("<html><head>" + "<meta http-equiv=\"refresh\"content=\"0;URL=qrc:///resources/index.html\">" + "</head><body><h1>Page redirects immediately...</h1>" + "</body></html>"); + QVERIFY(::waitForSignal(&page1, SIGNAL(loadFinished(bool)))); + QTest::qWait(500); + QCOMPARE(page1.mainFrame()->url(), QUrl(QLatin1String("qrc:///resources/index.html"))); + + // With QWebPage::StopScheduledPageRefresh + QWebPage page2; + page2.setNetworkAccessManager(new TestNetworkManager(&page2)); + page2.mainFrame()->setHtml("<html><head>" + "<meta http-equiv=\"refresh\"content=\"1;URL=qrc:///resources/index.html\">" + "</head><body><h1>Page redirect test with 1 sec timeout...</h1>" + "</body></html>"); + page2.triggerAction(QWebPage::StopScheduledPageRefresh); + QTest::qWait(1500); + QCOMPARE(page2.mainFrame()->url().toString(), QLatin1String("about:blank")); +} + +void tst_QWebPage::findText() +{ + m_view->setHtml(QString("<html><head></head><body><div>foo bar</div></body></html>")); + m_page->triggerAction(QWebPage::SelectAll); + QVERIFY(!m_page->selectedText().isEmpty()); + m_page->findText(""); + QVERIFY(m_page->selectedText().isEmpty()); + QStringList words = (QStringList() << "foo" << "bar"); + foreach (QString subString, words) { + m_page->findText(subString, QWebPage::FindWrapsAroundDocument); + QCOMPARE(m_page->selectedText(), subString); + m_page->findText(""); + QVERIFY(m_page->selectedText().isEmpty()); + } +} + +struct ImageExtensionMap { + const char* extension; + const char* mimeType; +}; + +static const ImageExtensionMap extensionMap[] = { + { "bmp", "image/bmp" }, + { "css", "text/css" }, + { "gif", "image/gif" }, + { "html", "text/html" }, + { "htm", "text/html" }, + { "ico", "image/x-icon" }, + { "jpeg", "image/jpeg" }, + { "jpg", "image/jpeg" }, + { "js", "application/x-javascript" }, + { "mng", "video/x-mng" }, + { "pbm", "image/x-portable-bitmap" }, + { "pgm", "image/x-portable-graymap" }, + { "pdf", "application/pdf" }, + { "png", "image/png" }, + { "ppm", "image/x-portable-pixmap" }, + { "rss", "application/rss+xml" }, + { "svg", "image/svg+xml" }, + { "text", "text/plain" }, + { "tif", "image/tiff" }, + { "tiff", "image/tiff" }, + { "txt", "text/plain" }, + { "xbm", "image/x-xbitmap" }, + { "xml", "text/xml" }, + { "xpm", "image/x-xpm" }, + { "xsl", "text/xsl" }, + { "xhtml", "application/xhtml+xml" }, + { "wml", "text/vnd.wap.wml" }, + { "wmlc", "application/vnd.wap.wmlc" }, + { 0, 0 } +}; + +static QString getMimeTypeForExtension(const QString &ext) +{ + const ImageExtensionMap *e = extensionMap; + while (e->extension) { + if (ext.compare(QLatin1String(e->extension), Qt::CaseInsensitive) == 0) + return QLatin1String(e->mimeType); + ++e; + } + + return QString(); +} + +void tst_QWebPage::supportedContentType() +{ + QStringList contentTypes; + + // Add supported non image types... + contentTypes << "text/html" << "text/xml" << "text/xsl" << "text/plain" << "text/" + << "application/xml" << "application/xhtml+xml" << "application/vnd.wap.xhtml+xml" + << "application/rss+xml" << "application/atom+xml" << "application/json"; + + // Add supported image types... + Q_FOREACH(const QByteArray& imageType, QImageWriter::supportedImageFormats()) { + const QString mimeType = getMimeTypeForExtension(imageType); + if (!mimeType.isEmpty()) + contentTypes << mimeType; + } + + // Get the mime types supported by webkit... + const QStringList supportedContentTypes = m_page->supportedContentTypes(); + + Q_FOREACH(const QString& mimeType, contentTypes) + QVERIFY2(supportedContentTypes.contains(mimeType), QString("'%1' is not a supported content type!").arg(mimeType).toLatin1()); + + Q_FOREACH(const QString& mimeType, contentTypes) + QVERIFY2(m_page->supportsContentType(mimeType), QString("Cannot handle content types '%1'!").arg(mimeType).toLatin1()); +} + QTEST_MAIN(tst_QWebPage) #include "tst_qwebpage.moc" diff --git a/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro b/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro index e99c7f4..e915d60 100644 --- a/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro +++ b/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro @@ -1 +1,3 @@ +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebview/qwebview.pro b/WebKit/qt/tests/qwebview/qwebview.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebview/qwebview.pro +++ b/WebKit/qt/tests/qwebview/qwebview.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebview/resources/input_types.html b/WebKit/qt/tests/qwebview/resources/input_types.html new file mode 100644 index 0000000..2e893af --- /dev/null +++ b/WebKit/qt/tests/qwebview/resources/input_types.html @@ -0,0 +1,9 @@ +<html><body> +<input type='text' maxlength='20' style='position: absolute; left: 10px; top: 0px; height: 50px; width: 100px;'/><br> +<input type='password' style='position: absolute; left: 10px; top: 50px; height: 50px; width: 100px;'/><br> +<input type='tel' style='position: absolute; left: 10px; top: 100px; height: 50px; width: 100px;'/><br> +<input type='number' style='position: absolute; left: 10px; top: 150px; height: 50px; width: 100px;'/><br> +<input type='email' style='position: absolute; left: 10px; top: 200px; height: 50px; width: 100px;'/><br> +<input type='url' style='position: absolute; left: 10px; top: 250px; height: 50px; width: 100px;'/><br> +<textarea style='position: absolute; left: 10px; top: 310px; height: 50px; width: 100px;' rows="2" cols="20">blah blah blah blah</textarea><br> +</body></html> diff --git a/WebKit/qt/tests/qwebview/tst_qwebview.cpp b/WebKit/qt/tests/qwebview/tst_qwebview.cpp index ebcf4bb..8cd2f3f 100644 --- a/WebKit/qt/tests/qwebview/tst_qwebview.cpp +++ b/WebKit/qt/tests/qwebview/tst_qwebview.cpp @@ -28,10 +28,9 @@ #include <qnetworkrequest.h> #include <qdiriterator.h> #include <qwebkitversion.h> +#include <qwebelement.h> #include <qwebframe.h> -#include <QDebug> - class tst_QWebView : public QObject { Q_OBJECT @@ -48,6 +47,8 @@ private slots: void reusePage_data(); void reusePage(); + void microFocusCoordinates(); + void focusInputTypes(); void crashTests(); }; @@ -141,22 +142,14 @@ void tst_QWebView::reusePage() } view1->show(); -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QTest::qWaitForWindowShown(view1); -#else - QTest::qWait(2000); -#endif delete view1; QVERIFY(page != 0); // deleting view must not have deleted the page, since it's not a child of view QWebView *view2 = new QWebView; view2->setPage(page); view2->show(); // in Windowless mode, you should still be able to see the plugin here -#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QTest::qWaitForWindowShown(view2); -#else - QTest::qWait(2000); -#endif delete view2; delete page; // must not crash @@ -203,6 +196,115 @@ void tst_QWebView::crashTests() QTRY_VERIFY(tester.m_executed); // If fail it means that the test wasn't executed. } +void tst_QWebView::microFocusCoordinates() +{ + QWebPage* page = new QWebPage; + QWebView* webView = new QWebView; + webView->setPage( page ); + + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input1' style='font--family: serif' value='' maxlength='20'/><br>" \ + "<canvas id='canvas1' width='500' height='500'/>" \ + "<input type='password'/><br>" \ + "<canvas id='canvas2' width='500' height='500'/>" \ + "</body></html>"); + + page->mainFrame()->setFocus(); + + QVariant initialMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(initialMicroFocus.isValid()); + + page->mainFrame()->scroll(0,50); + + QVariant currentMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(currentMicroFocus.isValid()); + + QCOMPARE(initialMicroFocus.toRect().translated(QPoint(0,-50)), currentMicroFocus.toRect()); +} + +void tst_QWebView::focusInputTypes() +{ + QWebView webView; + webView.show(); + QTest::qWaitForWindowShown(&webView); + + QUrl url("qrc:///resources/input_types.html"); + QWebFrame* const mainFrame = webView.page()->mainFrame(); + mainFrame->load(url); + mainFrame->setFocus(); + + QVERIFY(waitForSignal(&webView, SIGNAL(loadFinished(bool)))); + + // 'text' type + QWebElement inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=text]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); +#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(Q_OS_SYMBIAN) + QVERIFY(webView.inputMethodHints() & Qt::ImhNoAutoUppercase); + QVERIFY(webView.inputMethodHints() & Qt::ImhNoPredictiveText); +#else + QVERIFY(webView.inputMethodHints() == Qt::ImhNone); +#endif + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'password' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=password]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhHiddenText); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'tel' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=tel]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhDialableCharactersOnly); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'number' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=number]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhDigitsOnly); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'email' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=email]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhEmailCharactersOnly); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'url' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=url]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhUrlCharactersOnly); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'password' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=password]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhHiddenText); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'text' type + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=text]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); +#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(Q_OS_SYMBIAN) + QVERIFY(webView.inputMethodHints() & Qt::ImhNoAutoUppercase); + QVERIFY(webView.inputMethodHints() & Qt::ImhNoPredictiveText); +#else + QVERIFY(webView.inputMethodHints() == Qt::ImhNone); +#endif + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'password' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=password]")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhHiddenText); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); + + // 'text area' field + inputElement = mainFrame->documentElement().findFirst(QLatin1String("textarea")); + QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center()); + QVERIFY(webView.inputMethodHints() == Qt::ImhNone); + QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled)); +} QTEST_MAIN(tst_QWebView) #include "tst_qwebview.moc" diff --git a/WebKit/qt/tests/qwebview/tst_qwebview.qrc b/WebKit/qt/tests/qwebview/tst_qwebview.qrc index 5abc64c..8710a9a 100644 --- a/WebKit/qt/tests/qwebview/tst_qwebview.qrc +++ b/WebKit/qt/tests/qwebview/tst_qwebview.qrc @@ -2,6 +2,7 @@ <qresource> <file>resources/index.html</file> <file>resources/frame_a.html</file> + <file>resources/input_types.html</file> </qresource> </RCC> diff --git a/WebKit/qt/tests/tests.pri b/WebKit/qt/tests/tests.pri index 187950a..a795ff8 100644 --- a/WebKit/qt/tests/tests.pri +++ b/WebKit/qt/tests/tests.pri @@ -1,14 +1,15 @@ TEMPLATE = app CONFIG -= app_bundle -TARGET = tst_$$TARGET -SOURCES += $$_PRO_FILE_PWD_/$${TARGET}.cpp +VPATH += $$_PRO_FILE_PWD_ +# Add the tst_ prefix, In QTDIR_build it's done by qttest_p4.prf +CONFIG(QTDIR_build) { load(qttest_p4) } +ELSE { TARGET = tst_$$TARGET } +SOURCES += $${TARGET}.cpp INCLUDEPATH += \ $$PWD \ $$PWD/../Api -exists($$_PRO_FILE_PWD_/$${TARGET}.qrc):RESOURCES += $$_PRO_FILE_PWD_/$${TARGET}.qrc - include(../../../WebKit.pri) QT += testlib network diff --git a/WebKit/qt/tests/tests.pro b/WebKit/qt/tests/tests.pro index 5e19202..22fece5 100644 --- a/WebKit/qt/tests/tests.pro +++ b/WebKit/qt/tests/tests.pro @@ -1,4 +1,4 @@ TEMPLATE = subdirs SUBDIRS = qwebframe qwebpage qwebelement qgraphicswebview qwebhistoryinterface qwebview qwebhistory qwebinspector hybridPixmap -greaterThan(QT_MINOR_VERSION, 4): SUBDIRS += benchmarks/painting benchmarks/loading +SUBDIRS += benchmarks/painting benchmarks/loading |