/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** 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, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "../../shared/util.h" class tst_qquickbehaviors : public QQmlDataTest { Q_OBJECT public: tst_qquickbehaviors() {} private slots: void init() { qApp->processEvents(); } //work around animation timer bug (QTBUG-22865) void simpleBehavior(); void scriptTriggered(); void cppTriggered(); void loop(); void colorBehavior(); void parentBehavior(); void replaceBinding(); //void transitionOverrides(); void group(); void valueType(); void emptyBehavior(); void explicitSelection(); void nonSelectingBehavior(); void reassignedAnimation(); void disabled(); void dontStart(); void startup(); void groupedPropertyCrash(); void runningTrue(); void sameValue(); void delayedRegistration(); void startOnCompleted(); void multipleChangesToValueType(); }; void tst_qquickbehaviors::simpleBehavior() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("simple.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); QTRY_VERIFY(qobject_cast(rect->findChild("MyBehavior"))->animation()); QQuickItemPrivate::get(rect)->setState("moved"); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() > 0); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() < 200); //i.e. the behavior has been triggered delete rect; } void tst_qquickbehaviors::scriptTriggered() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("scripttrigger.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); rect->setColor(QColor("red")); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() > 0); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() < 200); //i.e. the behavior has been triggered delete rect; } void tst_qquickbehaviors::cppTriggered() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("cpptrigger.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); QQuickRectangle *innerRect = qobject_cast(rect->findChild("MyRect")); QTRY_VERIFY(innerRect); innerRect->setProperty("x", 200); QTRY_VERIFY(innerRect->x() > 0); QTRY_VERIFY(innerRect->x() < 200); //i.e. the behavior has been triggered delete rect; } void tst_qquickbehaviors::loop() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("loop.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); //don't crash QQuickItemPrivate::get(rect)->setState("moved"); delete rect; } void tst_qquickbehaviors::colorBehavior() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("color.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); QQuickItemPrivate::get(rect)->setState("red"); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->color() != QColor("red")); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->color() != QColor("green")); //i.e. the behavior has been triggered delete rect; } void tst_qquickbehaviors::parentBehavior() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("parent.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); QQuickItemPrivate::get(rect)->setState("reparented"); QTRY_VERIFY(rect->findChild("MyRect")->parentItem() != rect->findChild("NewParent")); QTRY_VERIFY(rect->findChild("MyRect")->parentItem() == rect->findChild("NewParent")); delete rect; } void tst_qquickbehaviors::replaceBinding() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("binding.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); QQuickItemPrivate::get(rect)->setState("moved"); QQuickRectangle *innerRect = qobject_cast(rect->findChild("MyRect")); QTRY_VERIFY(innerRect); QTRY_VERIFY(innerRect->x() > 0); QTRY_VERIFY(innerRect->x() < 200); //i.e. the behavior has been triggered QTRY_COMPARE(innerRect->x(), (qreal)200); rect->setProperty("basex", 10); QTRY_COMPARE(innerRect->x(), (qreal)200); rect->setProperty("movedx", 210); QTRY_COMPARE(innerRect->x(), (qreal)210); QQuickItemPrivate::get(rect)->setState(""); QTRY_VERIFY(innerRect->x() > 10); QTRY_VERIFY(innerRect->x() < 210); //i.e. the behavior has been triggered QTRY_COMPARE(innerRect->x(), (qreal)10); rect->setProperty("movedx", 200); QTRY_COMPARE(innerRect->x(), (qreal)10); rect->setProperty("basex", 20); QTRY_COMPARE(innerRect->x(), (qreal)20); delete rect; } void tst_qquickbehaviors::group() { /* XXX TODO Create a test element for this case. { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("groupProperty.qml"))); QQuickRectangle *rect = qobject_cast(c.create()); qDebug() << c.errorString(); QTRY_VERIFY(rect); QQuickItemPrivate::get(rect)->setState("moved"); //QTest::qWait(200); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() > 0); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() < 200); //i.e. the behavior has been triggered delete rect; } */ { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("groupProperty2.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QTRY_VERIFY(rect); QQuickItemPrivate::get(rect)->setState("moved"); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->border()->width() > 0); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->border()->width() < 4); //i.e. the behavior has been triggered delete rect; } } void tst_qquickbehaviors::valueType() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("valueType.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); //QTBUG-20827 QCOMPARE(rect->color(), QColor::fromRgb(255,0,255)); delete rect; } void tst_qquickbehaviors::emptyBehavior() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("empty.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickItemPrivate::get(rect)->setState("moved"); qreal x = qobject_cast(rect->findChild("MyRect"))->x(); QCOMPARE(x, qreal(200)); //should change immediately delete rect; } void tst_qquickbehaviors::explicitSelection() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("explicit.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickItemPrivate::get(rect)->setState("moved"); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() > 0); QTRY_VERIFY(qobject_cast(rect->findChild("MyRect"))->x() < 200); //i.e. the behavior has been triggered delete rect; } void tst_qquickbehaviors::nonSelectingBehavior() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("nonSelecting2.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickItemPrivate::get(rect)->setState("moved"); qreal x = qobject_cast(rect->findChild("MyRect"))->x(); QCOMPARE(x, qreal(200)); //should change immediately delete rect; } void tst_qquickbehaviors::reassignedAnimation() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("reassignedAnimation.qml")); QString warning = testFileUrl("reassignedAnimation.qml").toString() + ":9:9: QML Behavior: Cannot change the animation assigned to a Behavior."; QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QCOMPARE(qobject_cast( rect->findChild("MyBehavior")->animation())->duration(), 200); delete rect; } void tst_qquickbehaviors::disabled() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("disabled.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QCOMPARE(rect->findChild("MyBehavior")->enabled(), false); QQuickItemPrivate::get(rect)->setState("moved"); qreal x = qobject_cast(rect->findChild("MyRect"))->x(); QCOMPARE(x, qreal(200)); //should change immediately delete rect; } void tst_qquickbehaviors::dontStart() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("dontStart.qml")); QString warning = c.url().toString() + ":13:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes."; QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickAbstractAnimation *myAnim = rect->findChild("MyAnim"); QVERIFY(myAnim && !myAnim->qtAnimation()); delete rect; } void tst_qquickbehaviors::startup() { { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("startup.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickRectangle *innerRect = rect->findChild("innerRect"); QVERIFY(innerRect); QCOMPARE(innerRect->x(), qreal(100)); //should be set immediately delete rect; } { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("startup2.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickRectangle *innerRect = rect->findChild("innerRect"); QVERIFY(innerRect); QQuickText *text = rect->findChild(); QVERIFY(text); QCOMPARE(innerRect->x(), text->width()); //should be set immediately delete rect; } } //QTBUG-10799 void tst_qquickbehaviors::groupedPropertyCrash() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("groupedPropertyCrash.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); //don't crash delete rect; } //QTBUG-5491 void tst_qquickbehaviors::runningTrue() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("runningTrue.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickAbstractAnimation *animation = rect->findChild("rotAnim"); QVERIFY(animation); QSignalSpy runningSpy(animation, SIGNAL(runningChanged(bool))); rect->setProperty("myValue", 180); QTRY_VERIFY(runningSpy.count() > 0); delete rect; } //QTBUG-12295 void tst_qquickbehaviors::sameValue() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("qtbug12295.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect); QQuickRectangle *target = rect->findChild("myRect"); QVERIFY(target); target->setX(100); QCOMPARE(target->x(), qreal(100)); target->setProperty("x", 0); QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100)); QTRY_VERIFY(target->x() == qreal(0)); //make sure Behavior has finished. target->setX(100); QCOMPARE(target->x(), qreal(100)); //this is the main point of the test -- the behavior needs to be triggered again //even though we set 0 twice in a row. target->setProperty("x", 0); QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100)); delete rect; } //QTBUG-18362 void tst_qquickbehaviors::delayedRegistration() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("delayedRegistration.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect != 0); QQuickItem *innerRect = rect->property("myItem").value(); QVERIFY(innerRect != 0); QCOMPARE(innerRect->property("x").toInt(), int(0)); QTRY_COMPARE(innerRect->property("x").toInt(), int(100)); } //QTBUG-22555 void tst_qquickbehaviors::startOnCompleted() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("startOnCompleted.qml")); QQuickRectangle *rect = qobject_cast(c.create()); QVERIFY(rect != 0); QQuickItem *innerRect = rect->findChild(); QVERIFY(innerRect != 0); QCOMPARE(innerRect->property("x").toInt(), int(0)); QTRY_COMPARE(innerRect->property("x").toInt(), int(100)); delete rect; } //QTBUG-25139 void tst_qquickbehaviors::multipleChangesToValueType() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("multipleChangesToValueType.qml")); QScopedPointer rect(qobject_cast(c.create())); QVERIFY(rect != 0); QQuickText *text = rect->findChild(); QVERIFY(text != 0); QFont value; value.setPointSize(24); QCOMPARE(text->property("font").value(), value); QVERIFY(QMetaObject::invokeMethod(rect.data(), "updateFontProperties")); value.setItalic(true); value.setWeight(QFont::Bold); QCOMPARE(text->property("font").value(), value); value.setPointSize(48); QTRY_COMPARE(text->property("font").value(), value); } QTEST_MAIN(tst_qquickbehaviors) #include "tst_qquickbehaviors.moc"