diff options
author | Pierre Rossi <pierre.rossi@theqtcompany.com> | 2015-07-07 13:02:09 +0200 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2015-07-08 08:00:36 +0000 |
commit | 81449c0c804735b71ba2f225005482c7c0123dad (patch) | |
tree | e7a595d1b72f30190c408b3f69a1c6fc1f8bf3a1 /tests/auto | |
parent | b401f4ab3e0bcbf0da781a8d78032752f11500ab (diff) | |
download | qtwebchannel-81449c0c804735b71ba2f225005482c7c0123dad.tar.gz |
Support subclass property getters and setters.
QDialog for instance adds a setter for the modal property already
exposed by QWidget.
Object.defineProperty requires configurable set to true in order to
add that setter at a later stage.
Adds some reusable autotest logic with a soft dependency on QJSEngine to
test some of the C++/JS integration aspects.
Task-number: QTBUG-46548
Change-Id: Ibd49274f7d334c068c4006fb09417abf911c24e9
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.cpp | 205 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.h | 2 | ||||
-rw-r--r-- | tests/auto/webchannel/webchannel.pro | 5 |
3 files changed, 212 insertions, 0 deletions
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index e36a1b3..f1911e5 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.cpp @@ -38,9 +38,156 @@ #include <qmetaobjectpublisher_p.h> #include <QtTest> +#ifdef WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE +#include <QJSEngine> +#endif QT_USE_NAMESPACE +#ifdef WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE +class TestJSEngine; + +class TestEngineTransport : public QWebChannelAbstractTransport +{ + Q_OBJECT +public: + TestEngineTransport(TestJSEngine *); + void sendMessage(const QJsonObject &message) Q_DECL_OVERRIDE; + + Q_INVOKABLE void channelSetupReady(); + Q_INVOKABLE void send(const QByteArray &message); +private: + TestJSEngine *m_testEngine; +}; + +class ConsoleLogger : public QObject +{ + Q_OBJECT +public: + ConsoleLogger(QObject *parent = 0); + + Q_INVOKABLE void log(const QString &text); + Q_INVOKABLE void error(const QString &text); + + int errorCount() const { return m_errCount; } + int logCount() const { return m_logCount; } + QString lastError() const { return m_lastError; } + +private: + int m_errCount; + int m_logCount; + QString m_lastError; + +}; + + + +ConsoleLogger::ConsoleLogger(QObject *parent) + : QObject(parent) + , m_errCount(0) + , m_logCount(0) +{ +} + +void ConsoleLogger::log(const QString &text) +{ + m_logCount++; + qDebug("LOG: %s", qPrintable(text)); +} + +void ConsoleLogger::error(const QString &text) +{ + m_errCount++; + m_lastError = text; + qWarning("ERROR: %s", qPrintable(text)); +} + + +// A test JS engine with convenience integration with WebChannel. +class TestJSEngine : public QJSEngine +{ + Q_OBJECT +public: + TestJSEngine(); + + TestEngineTransport *transport() const; + ConsoleLogger *logger() const; + void initWebChannelJS(); + +signals: + void channelSetupReady(TestEngineTransport *transport); + +private: + TestEngineTransport *m_transport; + ConsoleLogger *m_logger; +}; + +TestEngineTransport::TestEngineTransport(TestJSEngine *engine) + : QWebChannelAbstractTransport(engine) + , m_testEngine(engine) +{ +} + +void TestEngineTransport::sendMessage(const QJsonObject &message) +{ + QByteArray json = QJsonDocument(message).toJson(QJsonDocument::Compact); + QJSValue callback = m_testEngine->evaluate(QStringLiteral("transport.onmessage")); + Q_ASSERT(callback.isCallable()); + QJSValue arg = m_testEngine->newObject(); + QJSValue data = m_testEngine->evaluate(QString::fromLatin1("JSON.parse('%1');").arg(QString::fromUtf8(json))); + Q_ASSERT(!data.isError()); + arg.setProperty(QStringLiteral("data"), data); + QJSValue val = callback.call((QJSValueList() << arg)); + Q_ASSERT(!val.isError()); +} + +void TestEngineTransport::channelSetupReady() +{ + emit m_testEngine->channelSetupReady(m_testEngine->transport()); +} + +void TestEngineTransport::send(const QByteArray &message) +{ + QJsonDocument doc(QJsonDocument::fromJson(message)); + emit messageReceived(doc.object(), this); +} + + +TestJSEngine::TestJSEngine() + : m_transport(new TestEngineTransport(this)) + , m_logger(new ConsoleLogger(this)) +{ + globalObject().setProperty("transport", newQObject(m_transport)); + globalObject().setProperty("console", newQObject(m_logger)); + + QString webChannelJSPath(QStringLiteral(":/qtwebchannel/qwebchannel.js")); + QFile webChannelJS(webChannelJSPath); + if (!webChannelJS.open(QFile::ReadOnly)) + qFatal("Error opening qwebchannel.js"); + QString source(QString::fromUtf8(webChannelJS.readAll())); + evaluate(source, webChannelJSPath); +} + +TestEngineTransport *TestJSEngine::transport() const +{ + return m_transport; +} + +ConsoleLogger *TestJSEngine::logger() const +{ + return m_logger; +} + +void TestJSEngine::initWebChannelJS() +{ + globalObject().setProperty(QStringLiteral("channel"), newObject()); + QJSValue channel = evaluate(QStringLiteral("channel = new QWebChannel(transport, function(channel) { transport.channelSetupReady();});")); + Q_ASSERT(!channel.isError()); +} + +#endif // WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE + + TestWebChannel::TestWebChannel(QObject *parent) : QObject(parent) , m_dummyTransport(new DummyTransport(this)) @@ -408,5 +555,63 @@ void TestWebChannel::benchRegisterObjects() channel.registerObjects(objects); } } +#ifdef WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE + +class SubclassedTestObject : public TestObject +{ + Q_OBJECT + Q_PROPERTY(QString bar READ bar WRITE setBar NOTIFY theBarHasChanged) +public: + void setBar(const QString &newBar); +signals: + void theBarHasChanged(); +}; + +void SubclassedTestObject::setBar(const QString &newBar) +{ + if (!newBar.isNull()) + emit theBarHasChanged(); +} + +class TestSubclassedFunctor { +public: + TestSubclassedFunctor(TestJSEngine *engine) + : m_engine(engine) + { + } + + void operator()() { + QCOMPARE(m_engine->logger()->errorCount(), 0); + } +private: + TestJSEngine *m_engine; +}; +#endif // WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE + +void TestWebChannel::qtbug46548_overriddenProperties() +{ +#ifndef WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE + QSKIP("A JS engine is required for this test to make sense."); +#else + SubclassedTestObject obj; + obj.setObjectName("subclassedTestObject"); + + QWebChannel webChannel; + webChannel.registerObject(obj.objectName(), &obj); + TestJSEngine engine; + webChannel.connectTo(engine.transport()); + QSignalSpy spy(&engine, &TestJSEngine::channelSetupReady); + connect(&engine, &TestJSEngine::channelSetupReady, TestSubclassedFunctor(&engine)); + engine.initWebChannelJS(); + if (!spy.count()) + spy.wait(); + QCOMPARE(spy.count(), 1); + QJSValue subclassedTestObject = engine.evaluate("channel.objects[\"subclassedTestObject\"]"); + QVERIFY(subclassedTestObject.isObject()); + +#endif // WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE +} QTEST_MAIN(TestWebChannel) + +#include "tst_webchannel.moc" diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h index 649e61f..b2a1040 100644 --- a/tests/auto/webchannel/tst_webchannel.h +++ b/tests/auto/webchannel/tst_webchannel.h @@ -244,6 +244,8 @@ private slots: void benchPropertyUpdates(); void benchRegisterObjects(); + void qtbug46548_overriddenProperties(); + private: DummyTransport *m_dummyTransport; diff --git a/tests/auto/webchannel/webchannel.pro b/tests/auto/webchannel/webchannel.pro index 40b324e..2dcc610 100644 --- a/tests/auto/webchannel/webchannel.pro +++ b/tests/auto/webchannel/webchannel.pro @@ -12,3 +12,8 @@ SOURCES += \ HEADERS += \ tst_webchannel.h + +qtHaveModule(qml) { + DEFINES += WEBCHANNEL_TESTS_CAN_USE_JS_ENGINE + QT += qml +} |