Revision control

Copy as Markdown

// Copyright (C) 2016 Ford Motor Company
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QtQuick/QQuickItem>
#include <QtStateMachineQml/private/signaltransition_p.h>
#include <QtStateMachineQml/private/timeouttransition_p.h>
#include <QtStateMachineQml/private/statemachine_p.h>
#include <QtStateMachineQml/private/finalstate_p.h>
#include <QtStateMachineQml/private/state_p.h>
#include <QtQml/qqmlscriptstring.h>
#include <QTest>
#include <QtTest/private/qpropertytesthelper_p.h>
#include "../../shared/util.h"
#include "../../shared/bindableqmlutils.h"
class tst_qqmlstatemachine : public QQmlDataTest
{
Q_OBJECT
public:
tst_qqmlstatemachine();
private slots:
void tst_cppObjectSignal();
void tst_bindings();
};
class CppObject : public QObject
{
Q_OBJECT
Q_PROPERTY(ObjectState objectState READ objectState WRITE setObjectState NOTIFY objectStateChanged)
public:
enum ObjectState {
State0,
State1,
State2
};
Q_ENUM(ObjectState)
public:
CppObject() {}
ObjectState objectState() const { return m_objectState; }
void setObjectState(ObjectState objectState) { m_objectState = objectState; emit objectStateChanged();}
signals:
void objectStateChanged();
void mySignal(int signalState);
private:
ObjectState m_objectState = State0;
};
tst_qqmlstatemachine::tst_qqmlstatemachine()
{
QVERIFY(-1 != qmlRegisterUncreatableType<CppObject>("CppObjectEnum", 1, 0, "CppObject", QString()));
}
void tst_qqmlstatemachine::tst_cppObjectSignal()
{
CppObject cppObject;
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("cppsignal.qml"));
QVERIFY2(!component.isError(), qPrintable(component.errorString()));
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("_cppObject", &cppObject);
QScopedPointer<QObject> rootObject(component.create());
QVERIFY(rootObject != nullptr);
// wait for state machine to start
QTRY_VERIFY(rootObject->property("running").toBool());
// emit signal from cpp
emit cppObject.mySignal(CppObject::State1);
// check if the signal was propagated
QTRY_COMPARE(cppObject.objectState(), CppObject::State1);
// emit signal from cpp
emit cppObject.mySignal(CppObject::State2);
// check if the signal was propagated
QTRY_COMPARE(cppObject.objectState(), CppObject::State2);
// wait for state machine to finish
QTRY_VERIFY(!rootObject->property("running").toBool());
}
void tst_qqmlstatemachine::tst_bindings()
{
SignalTransition signalTransition;
// Generating QQmlScriptString requires proper qml context setup, and here we
// use same the element that we are testing to create the testing material
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("signaltransition.qml"));
std::unique_ptr<QObject> obj(component.create());
SignalTransition *st1 = qobject_cast<SignalTransition*>(obj->findChild<QObject*>("st1"));
SignalTransition *st2 = qobject_cast<SignalTransition*>(obj->findChild<QObject*>("st2"));
QVERIFY(st1 && st2 && (st1->guard() != st2->guard()));
// -- SignalTransition::guard
QTestPrivate::testReadWritePropertyBasics<SignalTransition, QQmlScriptString>(
signalTransition, st1->guard(), st2->guard(), "guard");
if (QTest::currentTestFailed()) {
qWarning() << "SignalTransition::guard bindable test failed.";
return;
}
// -- SignalTransition::signal
// We use QML to create the test material (QJSValues that contain valid methods)
QVariant signal1;
QVariant signal2;
QMetaObject::invokeMethod(obj.get(), "getSignal1", Q_RETURN_ARG(QVariant, signal1));
QMetaObject::invokeMethod(obj.get(), "getSignal2", Q_RETURN_ARG(QVariant, signal2));
// The setter needs an active engine, so we use a helper component to create
// a helper instance for testing binding loops.
QQmlComponent helperComponent(&engine, testFileUrl("signaltransitionhelper.qml"));
// QJSValue does not implement operator== so we supply own comparator
QTestPrivate::testReadWritePropertyBasics<SignalTransition, QJSValue>(
*st1, signal1.value<QJSValue>(), signal2.value<QJSValue>(), "signal",
[](QJSValue d1, QJSValue d2) { return d1.strictlyEquals(d2); },
[](const QJSValue &val) { return QTest::toString(val); },
[&helperComponent]() {
return std::unique_ptr<SignalTransition>(
qobject_cast<SignalTransition*>(helperComponent.create()));
});
if (QTest::currentTestFailed()) {
qWarning() << "SignalTransition::signal bindable test failed.";
return;
}
// -- TimeoutTransition::timeout
TimeoutTransition timeoutTransition;
QCOMPARE(timeoutTransition.timeout(), 1000); // the initialvalue
int timeout1{100};
int timeout2{200};
QTestPrivate::testReadWritePropertyBasics<TimeoutTransition, int>(
timeoutTransition, timeout1, timeout2, "timeout");
if (QTest::currentTestFailed()) {
qWarning() << "TimeoutTransition::timeout bindable test failed.";
return;
}
// -- FinalState::children
FinalState finalState;
QObject object1;
QObject object2;
testManipulableQmlListBasics<FinalState, QObject*>(
finalState, &object1, &object2, "children");
// -- State::children
State state;
testManipulableQmlListBasics<State, QObject*>(
state, &object1, &object2, "children");
// -- StateMachine::children
StateMachine stateMachine;
testManipulableQmlListBasics<StateMachine, QObject*>(
stateMachine, &object1, &object2, "children");
}
QTEST_MAIN(tst_qqmlstatemachine)
#include "tst_qqmlstatemachine.moc"