summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2017-03-22 16:29:46 +0100
committerPeter Varga <pvarga@inf.u-szeged.hu>2017-08-31 07:40:20 +0000
commit656b7fdd2d972946fe980f4089f5e9d01160dc68 (patch)
tree283251893c9afe456f1d3198de80bf099dd6afad
parent2710c66f0c27874aa455be91a6c24c7fd7fa7523 (diff)
Add auto tests for MultipleMouseClickHelper
Qt WebEngine implements a custom handler for multiple mouse clicks. These tests are intended to test whether the mouse click events are properly forwarded to the Chromium's RenderWidgetHost. Custom mouse click test functions have been also added for the custom mouse click handler. Change-Id: Ifdc7d09f5e0f0f76c37e137e5743482bf3fb8abb Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-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;