From 392a5fd64e9d0ee98b26f8c6f4bc1bc3d17934fd Mon Sep 17 00:00:00 2001 From: Skycoder42 Date: Thu, 2 Aug 2018 00:52:37 +0200 Subject: [PATCH] added datasync and more qml tests --- .gitignore | 1 + .../mvvmdatasyncquick/ChangeRemoteView11.qml | 2 + src/mvvmcore/binding.cpp | 8 ++- src/mvvmcore/binding.h | 2 +- src/mvvmcore/binding_p.h | 3 + .../datasyncsettingsaccessor.cpp | 13 +++- .../datasyncsettingsaccessor.h | 3 + src/mvvmdatasyncwidgets/changeremotedialog.ui | 5 +- tests/auto/auto.pro | 5 ++ .../datasyncsettingsaccessor.pro | 14 +++++ .../tst_datasyncsettingsaccessor.cpp | 57 +++++++++++++++++ .../mvvmdatasynccore/mvvmdatasynccore.pro | 4 ++ tests/auto/qml/qml.pro | 3 +- tests/auto/qml/qmlmvvmcore/qmlmvvmcore.pro | 16 +++++ .../auto/qml/qmlmvvmcore/tst_qmlmvvmcore.cpp | 4 ++ .../auto/qml/qmlmvvmcore/tst_qmlmvvmcore.qml | 61 +++++++++++++++++++ tests/auto/settings.xml | 59 ------------------ tests/shared/tst_isettingsaccessor.h | 53 ++++++++-------- 18 files changed, 222 insertions(+), 91 deletions(-) create mode 100644 tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/datasyncsettingsaccessor.pro create mode 100644 tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/tst_datasyncsettingsaccessor.cpp create mode 100644 tests/auto/mvvmdatasynccore/mvvmdatasynccore.pro create mode 100644 tests/auto/qml/qmlmvvmcore/qmlmvvmcore.pro create mode 100644 tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.cpp create mode 100644 tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.qml delete mode 100644 tests/auto/settings.xml diff --git a/.gitignore b/.gitignore index a63120c..bcecf0e 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,4 @@ qpmx.user.json .qpmx-dev-cache qpmx.json.user *.pro.dummy +*.qmlc diff --git a/src/imports/mvvmdatasyncquick/ChangeRemoteView11.qml b/src/imports/mvvmdatasyncquick/ChangeRemoteView11.qml index 01f0709..2c6c7e4 100644 --- a/src/imports/mvvmdatasyncquick/ChangeRemoteView11.qml +++ b/src/imports/mvvmdatasyncquick/ChangeRemoteView11.qml @@ -69,6 +69,7 @@ Page { id: _urlEdit Layout.fillWidth: true + placeholderText: "wss://example.org/qdsapp/" validator: UrlValidator { allowedSchemes: ["ws", "wss"] } @@ -92,6 +93,7 @@ Page { id: _accessKeyEdit Layout.fillWidth: true echoMode: TextInput.Password + placeholderText: "Optional access secret" MvvmBinding { viewModel: _changeRemoteView.viewModel diff --git a/src/mvvmcore/binding.cpp b/src/mvvmcore/binding.cpp index 3819f33..c819775 100644 --- a/src/mvvmcore/binding.cpp +++ b/src/mvvmcore/binding.cpp @@ -108,6 +108,10 @@ Binding::operator bool() const void Binding::unbind() { if(d) { + if(d->modelToViewConnection) + QObject::disconnect(d->modelToViewConnection); + if(d->viewToModelConnection) + QObject::disconnect(d->viewToModelConnection); d->deleteLater(); d.clear(); } @@ -165,7 +169,7 @@ void BindingPrivate::bindFrom(QMetaMethod changeSignal) changeSignal = viewModelProperty.notifySignal(); } auto trigger = metaObject()->method(metaObject()->indexOfSlot("viewModelTrigger()")); - connect(viewModel, changeSignal, this, trigger); + modelToViewConnection = connect(viewModel, changeSignal, this, trigger); } void BindingPrivate::bindTo(QMetaMethod changeSignal) @@ -177,7 +181,7 @@ void BindingPrivate::bindTo(QMetaMethod changeSignal) changeSignal = viewProperty.notifySignal(); } auto trigger = metaObject()->method(metaObject()->indexOfSlot("viewTrigger()")); - connect(view, changeSignal, this, trigger); + viewToModelConnection = connect(view, changeSignal, this, trigger); } void BindingPrivate::testReadable(const QMetaProperty &property, bool asView) const diff --git a/src/mvvmcore/binding.h b/src/mvvmcore/binding.h index 13ac327..4ef5825 100644 --- a/src/mvvmcore/binding.h +++ b/src/mvvmcore/binding.h @@ -39,7 +39,7 @@ public: Q_INVOKABLE void unbind(); private: - QPointer d; + QPointer d; }; //! Create a multidirectional binding between properties diff --git a/src/mvvmcore/binding_p.h b/src/mvvmcore/binding_p.h index a8009c0..4a6d67e 100644 --- a/src/mvvmcore/binding_p.h +++ b/src/mvvmcore/binding_p.h @@ -38,6 +38,9 @@ private: QMetaProperty viewModelProperty; QMetaProperty viewProperty; + QMetaObject::Connection modelToViewConnection; + QMetaObject::Connection viewToModelConnection; + void testReadable(const QMetaProperty &property, bool asView) const; void testWritable(const QMetaProperty &property, bool asView) const; void testNotifier(const QMetaProperty &property, bool asView) const; diff --git a/src/mvvmdatasynccore/datasyncsettingsaccessor.cpp b/src/mvvmdatasynccore/datasyncsettingsaccessor.cpp index 01cda18..089be1a 100644 --- a/src/mvvmdatasynccore/datasyncsettingsaccessor.cpp +++ b/src/mvvmdatasynccore/datasyncsettingsaccessor.cpp @@ -29,7 +29,10 @@ DataSyncSettingsAccessor::DataSyncSettingsAccessor(QtDataSync::DataStore *store, DataSyncSettingsAccessor::DataSyncSettingsAccessor(QtDataSync::DataTypeStore *store, QObject *parent) : ISettingsAccessor{parent}, d{new DataSyncSettingsAccessorPrivate{store}} -{} +{ + connect(d->store, &QtDataSync::DataTypeStoreBase::dataChanged, + this, &DataSyncSettingsAccessor::dataChanged); +} DataSyncSettingsAccessor::~DataSyncSettingsAccessor() = default; @@ -89,6 +92,14 @@ void DataSyncSettingsAccessor::sync() // nothing needs to be done } +void DataSyncSettingsAccessor::dataChanged(const QString &key, const QVariant &value) +{ + if(value.isValid()) + emit entryChanged(key, value.value().value()); + else + emit entryRemoved(key); +} + // ------------- Private Implementation ------------- DataSyncSettingsAccessorPrivate::DataSyncSettingsAccessorPrivate(QtDataSync::DataTypeStore *store) : diff --git a/src/mvvmdatasynccore/datasyncsettingsaccessor.h b/src/mvvmdatasynccore/datasyncsettingsaccessor.h index e7d1eb6..d02bf1f 100644 --- a/src/mvvmdatasynccore/datasyncsettingsaccessor.h +++ b/src/mvvmdatasynccore/datasyncsettingsaccessor.h @@ -31,6 +31,9 @@ public: public Q_SLOTS: void sync() override; +private Q_SLOTS: + void dataChanged(const QString &key, const QVariant &value); + private: QScopedPointer d; }; diff --git a/src/mvvmdatasyncwidgets/changeremotedialog.ui b/src/mvvmdatasyncwidgets/changeremotedialog.ui index 2b24893..c799f58 100644 --- a/src/mvvmdatasyncwidgets/changeremotedialog.ui +++ b/src/mvvmdatasyncwidgets/changeremotedialog.ui @@ -218,7 +218,10 @@ :/de/skycoder42/qtmvvm/widgets/icons/remove.ico:/de/skycoder42/qtmvvm/widgets/icons/remove.ico - &Remove Selected Header + &Remove Header + + + Remove selected Header Del diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 7e7eed6..746b4e6 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -3,3 +3,8 @@ TEMPLATE = subdirs SUBDIRS += cmake \ mvvmcore \ qml + +qtHaveModule(datasync) { + SUBDIRS += \ + mvvmdatasynccore +} diff --git a/tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/datasyncsettingsaccessor.pro b/tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/datasyncsettingsaccessor.pro new file mode 100644 index 0000000..7b622b8 --- /dev/null +++ b/tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/datasyncsettingsaccessor.pro @@ -0,0 +1,14 @@ +TEMPLATE = app + +QT += testlib mvvmdatasynccore +QT -= gui +CONFIG += console +CONFIG -= app_bundle + +TARGET = tst_datasyncsettingsaccessor + +HEADERS += \ + ../../../shared/tst_isettingsaccessor.h + +SOURCES += \ + tst_datasyncsettingsaccessor.cpp diff --git a/tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/tst_datasyncsettingsaccessor.cpp b/tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/tst_datasyncsettingsaccessor.cpp new file mode 100644 index 0000000..358937d --- /dev/null +++ b/tests/auto/mvvmdatasynccore/datasyncsettingsaccessor/tst_datasyncsettingsaccessor.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include "../../../shared/tst_isettingsaccessor.h" +using namespace QtDataSync; +using namespace QtMvvm; + +class DataSyncSettingsAccessorTest : public ISettingsAccessorTest +{ + Q_OBJECT + +protected: + ISettingsAccessor *createFirst() override; + ISettingsAccessor *createSecond() override; + bool testSyncChangeSignals() override; + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + +private: + QTemporaryDir tDir; +}; + +ISettingsAccessor *DataSyncSettingsAccessorTest::createFirst() +{ + return new DataSyncSettingsAccessor{this}; +} + +ISettingsAccessor *DataSyncSettingsAccessorTest::createSecond() +{ + return new DataSyncSettingsAccessor{this}; +} + +bool DataSyncSettingsAccessorTest::testSyncChangeSignals() +{ + return true; +} + +void DataSyncSettingsAccessorTest::initTestCase() +{ + Setup{}.setLocalDir(tDir.path()) + .setKeyStoreProvider(QStringLiteral("plain")) + .create(); +} + +void DataSyncSettingsAccessorTest::cleanupTestCase() +{ + delete first; + delete second; + Setup::removeSetup(DefaultSetup, true); + tDir.remove(); +} + +QTEST_MAIN(DataSyncSettingsAccessorTest) + +#include "tst_datasyncsettingsaccessor.moc" diff --git a/tests/auto/mvvmdatasynccore/mvvmdatasynccore.pro b/tests/auto/mvvmdatasynccore/mvvmdatasynccore.pro new file mode 100644 index 0000000..d480243 --- /dev/null +++ b/tests/auto/mvvmdatasynccore/mvvmdatasynccore.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + datasyncsettingsaccessor diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 00ff531..f9516e3 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS += \ - qmlsettingsgenerator + qmlsettingsgenerator \ + qmlmvvmcore equals(MSVC_VER, 14.0): SUBDIRS -= qmlsettingsgenerator diff --git a/tests/auto/qml/qmlmvvmcore/qmlmvvmcore.pro b/tests/auto/qml/qmlmvvmcore/qmlmvvmcore.pro new file mode 100644 index 0000000..739f4a3 --- /dev/null +++ b/tests/auto/qml/qmlmvvmcore/qmlmvvmcore.pro @@ -0,0 +1,16 @@ +TEMPLATE = app + +QT += testlib mvvmcore qml +CONFIG += qmltestcase console +CONFIG -= app_bundle + +TARGET = tst_qmlmvvmcore + +SOURCES += \ + tst_qmlmvvmcore.cpp + +DISTFILES += \ + tst_qmlmvvmcore.qml + +importFiles.path = . +DEPLOYMENT += importFiles diff --git a/tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.cpp b/tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.cpp new file mode 100644 index 0000000..fcd7ccb --- /dev/null +++ b/tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.cpp @@ -0,0 +1,4 @@ +#include +#include + +QUICK_TEST_MAIN(qmlmvvmcore) diff --git a/tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.qml b/tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.qml new file mode 100644 index 0000000..43dde45 --- /dev/null +++ b/tests/auto/qml/qmlmvvmcore/tst_qmlmvvmcore.qml @@ -0,0 +1,61 @@ +import QtQuick 2.10 +import de.skycoder42.QtMvvm.Core 1.1 +import QtTest 1.1 + +Item { + id: root + + TestCase { + name: "Binding" + + QtObject { + id: obj + + property int prop1: 42 + property int prop2: 0 + } + + MvvmBinding { + id: bind + viewModel: obj + view: obj + viewModelProperty: "prop1" + viewProperty: "prop2" + type: MvvmBinding.SingleInit + } + + function test_1_SingleInit() { + verify(bind.isValid()); + compare(obj.prop1, 42); + compare(obj.prop2, 42); + obj.prop1 = 24; + compare(obj.prop2, 42); + obj.prop2 = 44; + compare(obj.prop1, 24); + } + + function test_2_OneWayToView() { + bind.type = MvvmBinding.OneWayToView + obj.prop1 = 33; + compare(obj.prop2, 33); + obj.prop2 = 44; + compare(obj.prop1, 33); + } + + function test_3_OneWayToViewModel() { + bind.type = MvvmBinding.OneWayToViewModel + obj.prop2 = 45; + compare(obj.prop1, 45); + obj.prop1 = 22; + compare(obj.prop2, 45); + } + + function test_4_TwoWay() { + bind.type = MvvmBinding.TwoWay + obj.prop1 = 78; + compare(obj.prop2, 78); + obj.prop2 = 87; + compare(obj.prop1, 87); + } + } +} diff --git a/tests/auto/settings.xml b/tests/auto/settings.xml deleted file mode 100644 index 9ca8d0b..0000000 --- a/tests/auto/settings.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - /absolute/include/path.xml - ../relative/include/path.xml - - /absolute/include/path.xml - ../relative/include/path.xml -
- /absolute/include/path.xml - ../relative/include/path.xml - - /absolute/include/path.xml - ../relative/include/path.xml - - prop - attrib - sample - Please do check me - - 42 - 42 - - - 42 - - elem 1 - elem 2 - - - baum - 42 - - - - - - -
-
- - - diff --git a/tests/shared/tst_isettingsaccessor.h b/tests/shared/tst_isettingsaccessor.h index 7371dcb..6ca0e7d 100644 --- a/tests/shared/tst_isettingsaccessor.h +++ b/tests/shared/tst_isettingsaccessor.h @@ -10,7 +10,8 @@ class ISettingsAccessorTest : public QObject Q_OBJECT protected: - QtMvvm::ISettingsAccessor *accessor = nullptr; + QtMvvm::ISettingsAccessor *first = nullptr; + QtMvvm::ISettingsAccessor *second = nullptr; virtual QtMvvm::ISettingsAccessor *createFirst() = 0; virtual QtMvvm::ISettingsAccessor *createSecond() = 0; @@ -18,23 +19,23 @@ protected: private Q_SLOTS: void testAccessorValid() { - accessor = createFirst(); - QVERIFY(accessor); + first = createFirst(); + QVERIFY(first); } void testSimpleOperations() { - QSignalSpy changedSpy{accessor, &QtMvvm::ISettingsAccessor::entryChanged}; - QSignalSpy removedSpy{accessor, &QtMvvm::ISettingsAccessor::entryRemoved}; + QSignalSpy changedSpy{first, &QtMvvm::ISettingsAccessor::entryChanged}; + QSignalSpy removedSpy{first, &QtMvvm::ISettingsAccessor::entryRemoved}; auto key = QStringLiteral("test/key"); - QVERIFY(!accessor->contains(key)); - QCOMPARE(accessor->load(key, 24).toInt(), 24); + QVERIFY(!first->contains(key)); + QCOMPARE(first->load(key, 24).toInt(), 24); QVERIFY(changedSpy.isEmpty()); QVERIFY(removedSpy.isEmpty()); - accessor->save(key, 42); - QVERIFY(accessor->contains(key)); - QCOMPARE(accessor->load(key, 24).toInt(), 42); + first->save(key, 42); + QVERIFY(first->contains(key)); + QCOMPARE(first->load(key, 24).toInt(), 42); if(changedSpy.isEmpty()) QVERIFY(changedSpy.wait()); QCOMPARE(changedSpy.size(), 1); @@ -43,9 +44,9 @@ private Q_SLOTS: QCOMPARE(changeEvent[1].toInt(), 42); QVERIFY(removedSpy.isEmpty()); - accessor->remove(key); - QVERIFY(!accessor->contains(key)); - QCOMPARE(accessor->load(key, 24).toInt(), 24); + first->remove(key); + QVERIFY(!first->contains(key)); + QCOMPARE(first->load(key, 24).toInt(), 24); if(removedSpy.isEmpty()) QVERIFY(removedSpy.wait()); QCOMPARE(removedSpy.size(), 1); @@ -59,13 +60,13 @@ private Q_SLOTS: auto key2 = QStringLiteral("group/key/subkey"); auto key3 = QStringLiteral("group/key/subgroup/subkey"); - accessor->save(key0, true); - accessor->save(key1, true); - accessor->save(key2, true); - accessor->save(key3, true); + first->save(key0, true); + first->save(key1, true); + first->save(key2, true); + first->save(key3, true); - QSignalSpy removedSpy{accessor, &QtMvvm::ISettingsAccessor::entryRemoved}; - accessor->remove(key1); + QSignalSpy removedSpy{first, &QtMvvm::ISettingsAccessor::entryRemoved}; + first->remove(key1); while(removedSpy.size() < 3) QVERIFY(removedSpy.wait()); @@ -83,14 +84,14 @@ private Q_SLOTS: } void testSync() { - auto second = createSecond(); + second = createSecond(); QVERIFY(second); QSignalSpy changedSpy{second, &QtMvvm::ISettingsAccessor::entryChanged}; - QSignalSpy removedSpy{accessor, &QtMvvm::ISettingsAccessor::entryRemoved}; + QSignalSpy removedSpy{first, &QtMvvm::ISettingsAccessor::entryRemoved}; auto key = QStringLiteral("sync/key"); - accessor->save(key, 13); - accessor->sync(); + first->save(key, 13); + first->sync(); second->sync(); if(!testSyncChangeSignals()) QEXPECT_FAIL("", "The testes accessor does not support notifying changes over multiple instances", Continue); @@ -100,13 +101,13 @@ private Q_SLOTS: QCOMPARE(changedSpy.size(), 1); auto changeEvent = changedSpy.takeFirst(); QCOMPARE(changeEvent[0].toString(), key); - QCOMPARE(changeEvent[1].toInt(), 42); + QCOMPARE(changeEvent[1].toInt(), 13); } QCOMPARE(second->load(key, 24).toInt(), 13); second->remove(key); second->sync(); - accessor->sync(); + first->sync(); if(!testSyncChangeSignals()) QEXPECT_FAIL("", "The testes accessor does not support notifying changes over multiple instances", Continue); if(removedSpy.isEmpty()) @@ -115,7 +116,7 @@ private Q_SLOTS: QCOMPARE(removedSpy.size(), 1); QCOMPARE(removedSpy.takeFirst()[0].toString(), key); } - QCOMPARE(accessor->load(key, 24).toInt(), 24); + QCOMPARE(first->load(key, 24).toInt(), 24); } };