summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/webengine/api/qquickwebenginetestsupport.cpp69
-rw-r--r--src/webengine/api/qquickwebenginetestsupport_p.h19
-rw-r--r--src/webengine/plugin/testsupport/plugin.cpp2
-rw-r--r--src/webengine/webengine.pro2
-rw-r--r--tests/auto/quick/qmltests/data/tst_mouseClick.qml131
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro1
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp95
7 files changed, 319 insertions, 0 deletions
diff --git a/src/webengine/api/qquickwebenginetestsupport.cpp b/src/webengine/api/qquickwebenginetestsupport.cpp
index 41f374766..b3290d3cc 100644
--- a/src/webengine/api/qquickwebenginetestsupport.cpp
+++ b/src/webengine/api/qquickwebenginetestsupport.cpp
@@ -40,9 +40,15 @@
#include "qquickwebenginetestsupport_p.h"
#include "qquickwebengineloadrequest_p.h"
+#include <QQuickWindow>
+#include <QtTest/qtest.h>
QT_BEGIN_NAMESPACE
+namespace QTest {
+ int Q_TESTLIB_EXPORT defaultMouseDelay();
+}
+
QQuickWebEngineErrorPage::QQuickWebEngineErrorPage()
{
}
@@ -101,9 +107,67 @@ bool QQuickWebEngineTestInputContext::isInputPanelVisible() const
}
+QQuickWebEngineTestEvent::QQuickWebEngineTestEvent()
+{
+}
+
+bool QQuickWebEngineTestEvent::mouseMultiClick(QObject *item, qreal x, qreal y, int clickCount)
+{
+ QTEST_ASSERT(item);
+
+ QWindow *view = eventWindow(item);
+ if (!view)
+ return false;
+
+ for (int i = 0; i < clickCount; ++i) {
+ mouseEvent(QMouseEvent::MouseButtonPress, view, item, QPointF(x, y));
+ mouseEvent(QMouseEvent::MouseButtonRelease, view, item, QPointF(x, y));
+ }
+ QTest::lastMouseTimestamp += QTest::mouseDoubleClickInterval;
+
+ return true;
+}
+
+QWindow *QQuickWebEngineTestEvent::eventWindow(QObject *item)
+{
+ QWindow *window = qobject_cast<QWindow *>(item);
+ if (window)
+ return window;
+
+ QQuickItem *quickItem = qobject_cast<QQuickItem *>(item);
+ if (quickItem)
+ return quickItem->window();
+
+ QQuickItem *testParentItem = qobject_cast<QQuickItem *>(parent());
+ if (testParentItem)
+ return testParentItem->window();
+
+ return nullptr;
+}
+
+void QQuickWebEngineTestEvent::mouseEvent(QEvent::Type type, QWindow *window, QObject *item, const QPointF &_pos)
+{
+ QTest::qWait(QTest::defaultMouseDelay());
+ QTest::lastMouseTimestamp += QTest::defaultMouseDelay();
+
+ QPoint pos;
+ QQuickItem *sgitem = qobject_cast<QQuickItem *>(item);
+ if (sgitem)
+ pos = sgitem->mapToScene(_pos).toPoint();
+
+ QMouseEvent me(type, pos, window->mapFromGlobal(pos), Qt::LeftButton, Qt::LeftButton, 0);
+ me.setTimestamp(++QTest::lastMouseTimestamp);
+
+ QSpontaneKeyEvent::setSpontaneous(&me);
+ if (!qApp->notify(window, &me))
+ QTest::qWarn("Mouse click event not accepted by receiving window");
+}
+
+
QQuickWebEngineTestSupport::QQuickWebEngineTestSupport()
: m_errorPage(new QQuickWebEngineErrorPage)
, m_testInputContext(new QQuickWebEngineTestInputContext)
+ , m_testEvent(new QQuickWebEngineTestEvent)
{
}
@@ -117,6 +181,11 @@ QQuickWebEngineTestInputContext *QQuickWebEngineTestSupport::testInputContext()
return m_testInputContext.data();
}
+QQuickWebEngineTestEvent * QQuickWebEngineTestSupport::testEvent() const
+{
+ return m_testEvent.data();
+}
+
QT_END_NAMESPACE
#include "moc_qquickwebenginetestsupport_p.cpp"
diff --git a/src/webengine/api/qquickwebenginetestsupport_p.h b/src/webengine/api/qquickwebenginetestsupport_p.h
index a84d00307..b601fb47c 100644
--- a/src/webengine/api/qquickwebenginetestsupport_p.h
+++ b/src/webengine/api/qquickwebenginetestsupport_p.h
@@ -54,12 +54,14 @@
#include <private/qinputmethod_p.h>
#include <private/qtwebengineglobal_p.h>
+#include <QEvent>
#include <QObject>
#include <QUrl>
QT_BEGIN_NAMESPACE
class QQuickWebEngineLoadRequest;
+class QWindow;
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineErrorPage : public QObject {
Q_OBJECT
@@ -92,15 +94,31 @@ private:
bool m_visible;
};
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTestEvent : public QObject {
+ Q_OBJECT
+
+public:
+ QQuickWebEngineTestEvent();
+
+public Q_SLOTS:
+ bool mouseMultiClick(QObject *item, qreal x, qreal y, int clickCount);
+
+private:
+ QWindow *eventWindow(QObject *item = 0);
+ void mouseEvent(QEvent::Type type, QWindow *window, QObject *item, const QPointF &_pos);
+};
+
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTestSupport : public QObject {
Q_OBJECT
Q_PROPERTY(QQuickWebEngineErrorPage *errorPage READ errorPage CONSTANT FINAL)
Q_PROPERTY(QQuickWebEngineTestInputContext *testInputContext READ testInputContext CONSTANT FINAL)
+ Q_PROPERTY(QQuickWebEngineTestEvent *testEvent READ testEvent CONSTANT FINAL)
public:
QQuickWebEngineTestSupport();
QQuickWebEngineErrorPage *errorPage() const;
QQuickWebEngineTestInputContext *testInputContext() const;
+ QQuickWebEngineTestEvent *testEvent() const;
Q_SIGNALS:
void windowCloseRejected();
@@ -109,6 +127,7 @@ Q_SIGNALS:
private:
QScopedPointer<QQuickWebEngineErrorPage> m_errorPage;
QScopedPointer<QQuickWebEngineTestInputContext> m_testInputContext;
+ QScopedPointer<QQuickWebEngineTestEvent> m_testEvent;
};
QT_END_NAMESPACE
diff --git a/src/webengine/plugin/testsupport/plugin.cpp b/src/webengine/plugin/testsupport/plugin.cpp
index c7eda2405..d5c43a859 100644
--- a/src/webengine/plugin/testsupport/plugin.cpp
+++ b/src/webengine/plugin/testsupport/plugin.cpp
@@ -60,6 +60,8 @@ public:
tr("Cannot create a separate instance of WebEngineErrorPage"));
qmlRegisterUncreatableType<QQuickWebEngineTestInputContext>(uri, 1, 0, "TestInputContext",
tr("Cannot create a separate instance of WebEngineErrorPage"));
+ qmlRegisterUncreatableType<QQuickWebEngineTestEvent>(uri, 1, 0, "WebEngineTestEvent",
+ tr("Cannot create a separate instance of WebEngineTestEvent"));
}
};
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index f8df714c0..f4bc65edb 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -56,6 +56,8 @@ HEADERS = \
ui_delegates_manager.h
isQMLTestSupportApiEnabled() {
+ QT += testlib
+
SOURCES += api/qquickwebenginetestsupport.cpp
HEADERS += api/qquickwebenginetestsupport_p.h
diff --git a/tests/auto/quick/qmltests/data/tst_mouseClick.qml b/tests/auto/quick/qmltests/data/tst_mouseClick.qml
new file mode 100644
index 000000000..527102f59
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_mouseClick.qml
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.4
+
+import QtWebEngine.testsupport 1.0
+
+TestWebEngineView {
+ id: webEngineView
+ width: 200
+ height: 200
+
+ testSupport: WebEngineTestSupport {
+ function mouseMultiClick(item, x, y, clickCount) {
+ if (!item)
+ qtest_fail("No item given to mouseMultiClick", 1);
+
+ if (x === undefined)
+ x = item.width / 2;
+ if (y === undefined)
+ y = item.height / 2;
+ if (!testEvent.mouseMultiClick(item, x, y, clickCount))
+ qtest_fail("window not shown", 2);
+ }
+
+ function mouseDoubleClick(item, x, y) {
+ mouseMultiClick(item, x, y, 2);
+ }
+
+ function mouseTripleClick(item, x, y) {
+ mouseMultiClick(item, x, y, 3);
+ }
+ }
+
+
+ TestCase {
+ name: "WebEngineViewMouseClick"
+ when: windowShown
+
+ function getElementCenter(element) {
+ var center;
+ runJavaScript("(function() {" +
+ " var elem = document.getElementById('" + element + "');" +
+ " var rect = elem.getBoundingClientRect();" +
+ " return { 'x': (rect.left + rect.right) / 2, 'y': (rect.top + rect.bottom) / 2 };" +
+ "})();", function(result) { center = result } );
+ tryVerify(function() { return center != undefined; });
+ return center;
+ }
+
+ function getTextSelection() {
+ var textSelection;
+ runJavaScript("window.getSelection().toString()", function(result) { textSelection = result });
+ tryVerify(function() { return textSelection != undefined; });
+ return textSelection;
+ }
+
+ function test_singleClick() {
+ webEngineView.settings.focusOnNavigationEnabled = false;
+ webEngineView.loadHtml("<html><body>" +
+ "<form><input id='input' width='150' type='text' value='The Qt Company' /></form>" +
+ "</body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+ verify(!getActiveElementId());
+
+ var center = getElementCenter("input");
+ mouseClick(webEngineView, center.x, center.y);
+ verifyElementHasFocus("input");
+ compare(getTextSelection(), "");
+ }
+
+ function test_doubleClick() {
+ webEngineView.settings.focusOnNavigationEnabled = true;
+ webEngineView.loadHtml("<html><body onload='document.getElementById(\"input\").focus()'>" +
+ "<form><input id='input' width='150' type='text' value='The Qt Company' /></form>" +
+ "</body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ var center = getElementCenter("input");
+ webEngineView.testSupport.mouseDoubleClick(webEngineView, center.x, center.y);
+ verifyElementHasFocus("input");
+ tryVerify(function() { return getTextSelection() == "Company" });
+
+ mouseClick(webEngineView, center.x, center.y);
+ tryVerify(function() { return getTextSelection() == "" });
+ }
+
+ function test_tripleClick() {
+ webEngineView.settings.focusOnNavigationEnabled = true;
+ webEngineView.loadHtml("<html><body onload='document.getElementById(\"input\").focus()'>" +
+ "<form><input id='input' width='150' type='text' value='The Qt Company' /></form>" +
+ "</body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ var center = getElementCenter("input");
+ webEngineView.testSupport.mouseTripleClick(webEngineView, center.x, center.y);
+ verifyElementHasFocus("input");
+ tryVerify(function() { return getTextSelection() == "The Qt Company" });
+
+ mouseClick(webEngineView, center.x, center.y);
+ tryVerify(function() { return getTextSelection() == "" });
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 39b9d0151..ceb246dc0 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -61,6 +61,7 @@ OTHER_FILES += \
$$PWD/data/tst_loadProgress.qml \
$$PWD/data/tst_loadRecursionCrash.qml \
$$PWD/data/tst_loadUrl.qml \
+ $$PWD/data/tst_mouseClick.qml \
$$PWD/data/tst_navigationHistory.qml \
$$PWD/data/tst_navigationRequested.qml \
$$PWD/data/tst_newViewRequest.qml \
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 2ed461e57..5fe02ce5d 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -92,6 +92,30 @@ static QRect elementGeometry(QWebEnginePage *page, const QString &id)
return QRect(coords[0].toInt(), coords[1].toInt(), coords[2].toInt(), coords[3].toInt());
}
+QT_BEGIN_NAMESPACE
+namespace QTest {
+ int Q_TESTLIB_EXPORT defaultMouseDelay();
+
+ static void mouseEvent(QEvent::Type type, QWidget *widget, const QPoint &pos)
+ {
+ QTest::qWait(QTest::defaultMouseDelay());
+ lastMouseTimestamp += QTest::defaultMouseDelay();
+ QMouseEvent me(type, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ me.setTimestamp(++lastMouseTimestamp);
+ QSpontaneKeyEvent::setSpontaneous(&me);
+ qApp->sendEvent(widget, &me);
+ }
+
+ static void mouseMultiClick(QWidget *widget, const QPoint pos, int clickCount)
+ {
+ for (int i = 0; i < clickCount; ++i) {
+ mouseEvent(QMouseEvent::MouseButtonPress, widget, pos);
+ mouseEvent(QMouseEvent::MouseButtonRelease, widget, pos);
+ }
+ lastMouseTimestamp += mouseDoubleClickInterval;
+ }
+}
+QT_END_NAMESPACE
class tst_QWebEngineView : public QObject
{
@@ -133,6 +157,7 @@ private Q_SLOTS:
void inputMethodsTextFormat();
void keyboardEvents();
void keyboardFocusAfterPopup();
+ void mouseClick();
void postData();
void inputFieldOverridesShortcuts();
@@ -1222,6 +1247,76 @@ void tst_QWebEngineView::keyboardFocusAfterPopup()
QTRY_COMPARE(evaluateJavaScriptSync(webView->page(), "document.getElementById('input1').value").toString(), QStringLiteral("x"));
}
+void tst_QWebEngineView::mouseClick()
+{
+ QWebEngineView view;
+ view.show();
+ view.resize(200, 200);
+ QTest::qWaitForWindowExposed(&view);
+
+ QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
+ QPoint textInputCenter;
+
+ // Single Click
+ view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false);
+ selectionChangedSpy.clear();
+
+ view.setHtml("<html><body>"
+ "<form><input id='input' width='150' type='text' value='The Qt Company' /></form>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ QVERIFY(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString().isEmpty());
+ textInputCenter = elementCenter(view.page(), "input");
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input"));
+ QCOMPARE(selectionChangedSpy.count(), 0);
+ QVERIFY(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString().isEmpty());
+
+ // Double click
+ view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
+ selectionChangedSpy.clear();
+
+ view.setHtml("<html><body onload='document.getElementById(\"input\").focus()'>"
+ "<form><input id='input' width='150' type='text' value='The Qt Company' /></form>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ textInputCenter = elementCenter(view.page(), "input");
+ QTest::mouseMultiClick(view.focusProxy(), textInputCenter, 2);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 1);
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input"));
+ QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QStringLiteral("Company"));
+
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 2);
+ QVERIFY(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString().isEmpty());
+
+ // Triple click
+ view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
+ selectionChangedSpy.clear();
+
+ view.setHtml("<html><body onload='document.getElementById(\"input\").focus()'>"
+ "<form><input id='input' width='150' type='text' value='The Qt Company' /></form>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ textInputCenter = elementCenter(view.page(), "input");
+ QTest::mouseMultiClick(view.focusProxy(), textInputCenter, 3);
+ QVERIFY(selectionChangedSpy.wait());
+ QTRY_COMPARE(selectionChangedSpy.count(), 2);
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input"));
+ QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QStringLiteral("The Qt Company"));
+
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 3);
+ QVERIFY(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString().isEmpty());
+}
+
void tst_QWebEngineView::postData()
{
QMap<QString, QString> postData;