diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2013-11-13 13:29:56 +0100 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2013-11-22 17:29:12 +0100 |
commit | e8d890b6020e2f2ec2e4ee3b1295963d4dbb1637 (patch) | |
tree | f549064966f5eebc8090e30bcbac22daebd5c06c | |
parent | d711e1cfb0e7a08c6c9c1309905a19b6addebb4d (diff) | |
download | qtwebchannel-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.pro | 1 | ||||
-rw-r--r-- | src/src.pro | 4 | ||||
-rw-r--r-- | tests/qml/WebChannelTest.qml | 124 | ||||
-rw-r--r-- | tests/qml/method.html | 20 | ||||
-rw-r--r-- | tests/qml/property.html | 24 | ||||
-rw-r--r-- | tests/qml/qml.pro | 2 | ||||
-rw-r--r-- | tests/qml/signal.html | 20 | ||||
-rw-r--r-- | tests/qml/tst_metaobjectpublisher.qml | 162 | ||||
-rw-r--r-- | tests/qml/tst_webchannel.qml | 76 |
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 } |