summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2013-11-13 13:29:56 +0100
committerMilian Wolff <milian.wolff@kdab.com>2013-11-22 17:29:12 +0100
commite8d890b6020e2f2ec2e4ee3b1295963d4dbb1637 (patch)
treef549064966f5eebc8090e30bcbac22daebd5c06c
parentd711e1cfb0e7a08c6c9c1309905a19b6addebb4d (diff)
downloadqtwebchannel-e8d890b6020e2f2ec2e4ee3b1295963d4dbb1637.tar.gz
Add an initial test suite for the MetaObjectPublisher
This tests the functionality of publishing a plain QtObject from QML to the HTML client. It tests property binding, i.e. reading and writing of an objects property on the client side, as well as change notification tracking. Furthermore a server-side method is invoked from the client and signal submission from the server to the client is tested. Change-Id: I62e544cddf4483b57535a9bc1e05a36105ec6622 Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
-rw-r--r--qwebchannel.pro1
-rw-r--r--src/src.pro4
-rw-r--r--tests/qml/WebChannelTest.qml124
-rw-r--r--tests/qml/method.html20
-rw-r--r--tests/qml/property.html24
-rw-r--r--tests/qml/qml.pro2
-rw-r--r--tests/qml/signal.html20
-rw-r--r--tests/qml/tst_metaobjectpublisher.qml162
-rw-r--r--tests/qml/tst_webchannel.qml76
9 files changed, 359 insertions, 74 deletions
diff --git a/qwebchannel.pro b/qwebchannel.pro
index 9611cb3..bbb213a 100644
--- a/qwebchannel.pro
+++ b/qwebchannel.pro
@@ -6,3 +6,4 @@ SUBDIRS = \
tests
examples.depends = src
+tests.depends = src
diff --git a/src/src.pro b/src/src.pro
index c20f118..bc61f5b 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -9,8 +9,8 @@ CONFIG += qt plugin
TARGET = $$qtLibraryTarget($$TARGET)
# Input
-SOURCES += qwebchannel_plugin.cpp
-HEADERS += qwebchannel_plugin.h
+SOURCES += $$PWD/qwebchannel_plugin.cpp
+HEADERS += $$PWD/qwebchannel_plugin.h
RESOURCES += \
resources.qrc
diff --git a/tests/qml/WebChannelTest.qml b/tests/qml/WebChannelTest.qml
new file mode 100644
index 0000000..ca2996d
--- /dev/null
+++ b/tests/qml/WebChannelTest.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QWebChannel module on Qt labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+
+import Qt.labs.WebChannel 1.0
+import QtWebKit 3.0
+import QtWebKit.experimental 1.0
+
+TestCase {
+ // only run after the webchannel has finished initialization
+ when: webChannel.baseUrl != ""
+
+ property var lastLoadStatus
+
+ WebView {
+ id: view
+
+ experimental.preferences.developerExtrasEnabled: true
+
+ onLoadingChanged: {
+ // NOTE: we cannot use spy.signalArguments nor save the loadRequest anywhere, as it gets
+ // deleted after the slots connected to the signal have finished... i.e. it's a weak pointer,
+ // not a shared pointer. As such, we have to copy out the interesting data we need later on here...
+ lastLoadStatus = loadRequest.status
+ }
+
+ SignalSpy {
+ id: loadingSpy
+ target: view
+ signalName: "onLoadingChanged"
+ }
+ }
+
+ WebChannel {
+ id: webChannel
+ }
+ property var webChannel: webChannel
+
+ SignalSpy {
+ id: rawMessageSpy
+ target: webChannel
+ signalName: "onRawMessageReceived"
+ }
+ property var rawMessageSpy: rawMessageSpy
+ property var rawMessageIdx: 0;
+
+ SignalSpy {
+ id: pongSpy
+ target: webChannel
+ signalName: "onPongReceived"
+ }
+ property var pongSpy: pongSpy
+
+ function loadUrl(url)
+ {
+ verify(webChannel.baseUrl != "", "webChannel.baseUrl is empty");
+ view.url = url + "?webChannelBaseUrl=" + webChannel.baseUrl;
+ // now wait for page to finish loading
+ do {
+ loadingSpy.wait(500);
+ } while (view.loading);
+ compare(lastLoadStatus, WebView.LoadSucceededStatus);
+ }
+
+ function cleanup()
+ {
+ view.url = "";
+ loadingSpy.clear();
+ rawMessageSpy.clear();
+ rawMessageIdx = 0;
+ pongSpy.clear();
+ }
+
+ function awaitRawMessage()
+ {
+ rawMessageSpy.wait(500);
+ if (rawMessageSpy.signalArguments.length <= rawMessageIdx) {
+ // still no message received, fail
+ return null;
+ }
+ return rawMessageSpy.signalArguments[rawMessageIdx++][0];
+ }
+
+ function awaitMessage()
+ {
+ var msg = awaitRawMessage()
+ if (!msg) {
+ return msg;
+ }
+ return JSON.parse(msg);
+ }
+}
diff --git a/tests/qml/method.html b/tests/qml/method.html
new file mode 100644
index 0000000..618550f
--- /dev/null
+++ b/tests/qml/method.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script type="text/javascript" src="qrc:///qwebchannel/webchannel.js"></script>
+ <script type="text/javascript" src="qrc:///qwebchannel/qobject.js"></script>
+ <script type="text/javascript">
+ //BEGIN SETUP
+ var baseUrl = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search)[1]);
+ new QWebChannel(baseUrl, function(channel) {
+ setupQObjectWebChannel(channel, function() {
+ channel.subscribe("invokeMethod", function(arg) {
+ myObj.myMethod(arg);
+ });
+ });
+ });
+ //END SETUP
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/tests/qml/property.html b/tests/qml/property.html
new file mode 100644
index 0000000..1a8360a
--- /dev/null
+++ b/tests/qml/property.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <script type="text/javascript" src="qrc:///qwebchannel/webchannel.js"></script>
+ <script type="text/javascript" src="qrc:///qwebchannel/qobject.js"></script>
+ <script type="text/javascript">
+ //BEGIN SETUP
+ var baseUrl = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search)[1]);
+ new QWebChannel(baseUrl, function(channel) {
+ setupQObjectWebChannel(channel, function() {
+ channel.exec({label: "init", value: myObj.myProperty()});
+ myObj.myPropertyChanged.connect(function() {
+ channel.exec({label: "changed", value: myObj.myProperty()});
+ });
+ channel.subscribe("setProperty", function(newValue) {
+ myObj.myProperty = newValue;
+ });
+ });
+ });
+ //END SETUP
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/tests/qml/qml.pro b/tests/qml/qml.pro
index d687e63..c969291 100644
--- a/tests/qml/qml.pro
+++ b/tests/qml/qml.pro
@@ -4,7 +4,7 @@ TARGET = qml
CONFIG += warn_on qmltestcase
-IMPORTPATH += $$OUT_PWD/../../src
+IMPORTPATH += $$OUT_PWD/../../src $$PWD
SOURCES += \
qml.cpp
diff --git a/tests/qml/signal.html b/tests/qml/signal.html
new file mode 100644
index 0000000..e3815cb
--- /dev/null
+++ b/tests/qml/signal.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script type="text/javascript" src="qrc:///qwebchannel/webchannel.js"></script>
+ <script type="text/javascript" src="qrc:///qwebchannel/qobject.js"></script>
+ <script type="text/javascript">
+ //BEGIN SETUP
+ var baseUrl = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search)[1]);
+ new QWebChannel(baseUrl, function(channel) {
+ setupQObjectWebChannel(channel, function() {
+ myObj.mySignal.connect(function(arg) {
+ channel.exec({label: "signalReceived", value: arg});
+ });
+ });
+ });
+ //END SETUP
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/tests/qml/tst_metaobjectpublisher.qml b/tests/qml/tst_metaobjectpublisher.qml
new file mode 100644
index 0000000..7739b06
--- /dev/null
+++ b/tests/qml/tst_metaobjectpublisher.qml
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QWebChannel module on Qt labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import Qt.labs.WebChannel 1.0
+
+WebChannelTest {
+ name: "MetaObjectPublisher"
+ id: test
+
+ property var lastMethodArg
+
+ QtObject {
+ id: myObj
+ property int myProperty: 1
+
+ signal mySignal(var arg)
+
+ function myMethod(arg)
+ {
+ lastMethodArg = arg;
+ }
+ }
+
+ MetaObjectPublisher {
+ id: publisher
+ webChannel: test.webChannel
+
+ Connections {
+ target: webChannel
+ onRawMessageReceived: {
+ var message = JSON.parse(rawMessage);
+ verify(message);
+ publisher.handleRequest(message);
+ }
+ }
+ }
+
+ function initTestCase()
+ {
+ publisher.registerObjects({
+ "myObj": myObj
+ });
+ }
+
+ function awaitInit()
+ {
+ var msg = awaitMessage();
+ verify(msg);
+ verify(msg.data);
+ verify(msg.data.type);
+ compare(msg.data.type, "Qt.init");
+ }
+
+ function awaitIdle()
+ {
+ var msg = awaitMessage();
+ verify(msg);
+ verify(msg.data);
+ compare(msg.data.type, "Qt.idle");
+ verify(publisher.clientIsIdle)
+ }
+
+ function test_property()
+ {
+ loadUrl("property.html");
+ awaitInit();
+ var msg = awaitMessage();
+ compare(msg.data.label, "init");
+ compare(msg.data.value, 1);
+ compare(myObj.myProperty, 1);
+
+ awaitIdle();
+
+ // change property, should be propagated to HTML client and a message be send there
+ myObj.myProperty = 2;
+ msg = awaitMessage();
+ compare(msg.data.label, "changed");
+ compare(msg.data.value, 2);
+ compare(myObj.myProperty, 2);
+
+ awaitIdle();
+
+ // now trigger a write from the client side
+ webChannel.sendMessage("setProperty", 3);
+ msg = awaitMessage();
+ compare(myObj.myProperty, 3);
+
+ // the above write is also propagated to the HTML client
+ msg = awaitMessage();
+ compare(msg.data.label, "changed");
+ compare(msg.data.value, 3);
+
+ awaitIdle();
+ }
+
+ function test_method()
+ {
+ loadUrl("method.html");
+ awaitInit();
+ awaitIdle();
+
+ webChannel.sendMessage("invokeMethod", "test");
+
+ var msg = awaitMessage();
+ compare(msg.data.type, "Qt.invokeMethod");
+ compare(msg.data.object, "myObj");
+ compare(msg.data.args, ["test"]);
+
+ compare(lastMethodArg, "test")
+ }
+
+ function test_signal()
+ {
+ loadUrl("signal.html");
+ awaitInit();
+
+ var msg = awaitMessage();
+ compare(msg.data.type, "Qt.connectToSignal");
+ compare(msg.data.object, "myObj");
+ compare(msg.data.signal, "mySignal");
+
+ awaitIdle();
+
+ myObj.mySignal("test");
+
+ msg = awaitMessage();
+ compare(msg.data.label, "signalReceived");
+ compare(msg.data.value, "test");
+ }
+}
diff --git a/tests/qml/tst_webchannel.qml b/tests/qml/tst_webchannel.qml
index 10f885d..a915ea3 100644
--- a/tests/qml/tst_webchannel.qml
+++ b/tests/qml/tst_webchannel.qml
@@ -32,96 +32,31 @@
****************************************************************************/
import QtQuick 2.0
-import QtTest 1.0
-import Qt.labs.WebChannel 1.0
-import QtWebKit 3.0
-
-TestCase {
+WebChannelTest {
name: "WebChannel"
- // only run after the webchannel has finished initialization
- when: webChannel.baseUrl != ""
-
- property var lastLoadStatus
-
- WebView {
- id: view
-
- onLoadingChanged: {
- // NOTE: we cannot use spy.signalArguments nor save the loadRequest anywhere, as it gets
- // deleted after the slots connected to the signal have finished... i.e. it's a weak pointer,
- // not a shared pointer. As such, we have to copy out the interesting data we need later on here...
- lastLoadStatus = loadRequest.status
- }
-
- SignalSpy {
- id: loadingSpy
- target: view
- signalName: "onLoadingChanged"
- }
- }
-
- WebChannel {
- id: webChannel
- }
-
- SignalSpy {
- id: rawMessageSpy
- target: webChannel
- signalName: "onRawMessageReceived"
- }
-
- SignalSpy {
- id: pongSpy
- target: webChannel
- signalName: "onPongReceived"
- }
-
- function loadUrl(url)
- {
- verify(webChannel.baseUrl != "", "webChannel.baseUrl is empty");
- view.url = url + "?webChannelBaseUrl=" + webChannel.baseUrl;
- // now wait for page to finish loading
- do {
- loadingSpy.wait(500);
- } while (view.loading);
- compare(lastLoadStatus, WebView.LoadSucceededStatus);
- }
-
- function cleanup()
- {
- view.url = "";
- loadingSpy.clear();
- rawMessageSpy.clear();
- }
-
- //BEGIN TESTS
function test_receiveRawMessage()
{
loadUrl("receiveRaw.html");
- rawMessageSpy.wait(500);
- compare(rawMessageSpy.signalArguments[0][0], "foobar");
+ compare(awaitRawMessage(), "foobar");
}
function test_sendMessage()
{
loadUrl("send.html");
webChannel.sendMessage("myMessage", "foobar");
- rawMessageSpy.wait(500);
- compare(rawMessageSpy.signalArguments[0][0], "myMessagePong:foobar");
+ compare(awaitRawMessage(), "myMessagePong:foobar");
}
function test_respondMessage()
{
loadUrl("respond.html");
- rawMessageSpy.wait(500);
- var msg = JSON.parse(rawMessageSpy.signalArguments[0][0]);
+ var msg = awaitMessage();
verify(msg.id);
compare(msg.data, "foobar");
webChannel.respond(msg.id, "barfoo");
- rawMessageSpy.wait(500);
- compare(rawMessageSpy.signalArguments[1][0], "received:barfoo");
+ compare(awaitRawMessage(), "received:barfoo");
}
function test_ping()
@@ -131,5 +66,4 @@ TestCase {
pongSpy.wait(500);
compare(pongSpy.count, 1);
}
- //END TESTS
}