blob: 31c3fb99460e583fcbb3777faa5006515211fd17 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <private/qquickimage_p.h>
#include <private/qquickanimatedimage_p.h>
#include <QSignalSpy>
#include <QtQml/qqmlcontext.h>
#include "../../shared/testhttpserver.h"
#include "../../shared/util.h"
Q_DECLARE_METATYPE(QQuickImageBase::Status)
template <typename T> static T evaluate(QObject *scope, const QString &expression)
{
QQmlExpression expr(qmlContext(scope), scope, expression);
QVariant result = expr.evaluate();
if (expr.hasError())
qWarning() << expr.error().toString();
return result.value<T>();
}
template <> void evaluate<void>(QObject *scope, const QString &expression)
{
QQmlExpression expr(qmlContext(scope), scope, expression);
expr.evaluate();
if (expr.hasError())
qWarning() << expr.error().toString();
}
class tst_qquickanimatedimage : public QQmlDataTest
{
Q_OBJECT
public:
tst_qquickanimatedimage() {}
private slots:
void cleanup();
void play();
void pause();
void stopped();
void setFrame();
void frameCount();
void mirror_running();
void mirror_notRunning();
void mirror_notRunning_data();
void remote();
void remote_data();
void sourceSize();
void sourceSizeChanges();
void sourceSizeChanges_intermediate();
void sourceSizeReadOnly();
void invalidSource();
void qtbug_16520();
void progressAndStatusChanges();
void playingAndPausedChanges();
void noCaching();
void sourceChangesOnFrameChanged();
void currentFrame();
};
void tst_qquickanimatedimage::cleanup()
{
QQuickWindow window;
window.releaseResources();
}
void tst_qquickanimatedimage::play()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stickman.qml"));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QVERIFY(anim->isPlaying());
delete anim;
}
void tst_qquickanimatedimage::pause()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stickmanpause.qml"));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QTRY_VERIFY(anim->isPaused());
QTRY_VERIFY(anim->isPlaying());
delete anim;
}
void tst_qquickanimatedimage::stopped()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stickmanstopped.qml"));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QTRY_VERIFY(!anim->isPlaying());
QCOMPARE(anim->currentFrame(), 0);
delete anim;
}
void tst_qquickanimatedimage::setFrame()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stickmanpause.qml"));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QVERIFY(anim->isPlaying());
QCOMPARE(anim->currentFrame(), 2);
delete anim;
}
void tst_qquickanimatedimage::frameCount()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("colors.qml"));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QVERIFY(anim->isPlaying());
QCOMPARE(anim->frameCount(), 3);
QSignalSpy frameCountChangedSpy(anim, &QQuickAnimatedImage::frameCountChanged);
const QUrl origSource = anim->source();
anim->setSource(QUrl());
QCOMPARE(anim->frameCount(), 0);
QCOMPARE(frameCountChangedSpy.count(), 1);
anim->setSource(origSource);
QCOMPARE(anim->frameCount(), 3);
QCOMPARE(frameCountChangedSpy.count(), 2);
delete anim;
}
void tst_qquickanimatedimage::mirror_running()
{
// test where mirror is set to true after animation has started
QQuickView window;
window.setSource(testFileUrl("hearts.qml"));
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
QVERIFY(anim);
int width = anim->property("width").toInt();
QCOMPARE(anim->frameCount(), 2);
QCOMPARE(anim->currentFrame(), 0);
QImage frame0 = window.grabWindow();
anim->setCurrentFrame(1);
QCOMPARE(anim->currentFrame(), 1);
QImage frame1 = window.grabWindow();
anim->setCurrentFrame(0);
QSignalSpy spy(anim, SIGNAL(frameChanged()));
QVERIFY(spy.isValid());
anim->setPlaying(true);
QTRY_VERIFY(spy.count() == 1); spy.clear();
anim->setMirror(true);
QCOMPARE(anim->currentFrame(), 1);
QImage frame1_flipped = window.grabWindow();
QTRY_VERIFY(spy.count() == 1); spy.clear();
QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
QImage frame0_flipped = window.grabWindow();
QTransform transform;
transform.translate(width, 0).scale(-1, 1.0);
QImage frame0_expected = frame0.transformed(transform);
QImage frame1_expected = frame1.transformed(transform);
if (window.devicePixelRatio() != 1.0 && window.rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
QSKIP("QTBUG-53823");
QCOMPARE(frame0_flipped, frame0_expected);
if (window.devicePixelRatio() != 1.0 && window.rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
QSKIP("QTBUG-53823");
QCOMPARE(frame1_flipped, frame1_expected);
delete anim;
}
void tst_qquickanimatedimage::mirror_notRunning()
{
QFETCH(QUrl, fileUrl);
QQuickView window;
window.setSource(fileUrl);
window.show();
QTRY_VERIFY(window.isExposed());
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
QVERIFY(anim);
int width = anim->property("width").toInt();
QImage screenshot = window.grabWindow();
QTransform transform;
transform.translate(width, 0).scale(-1, 1.0);
QImage expected = screenshot.transformed(transform);
int frame = anim->currentFrame();
bool playing = anim->isPlaying();
bool paused = anim->isPaused();
anim->setProperty("mirror", true);
screenshot = window.grabWindow();
screenshot.save("screen.png");
if (window.devicePixelRatio() != 1.0 && window.rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
QSKIP("QTBUG-53823");
QCOMPARE(screenshot, expected);
// mirroring should not change the current frame or playing status
QCOMPARE(anim->currentFrame(), frame);
QCOMPARE(anim->isPlaying(), playing);
QCOMPARE(anim->isPaused(), paused);
delete anim;
}
void tst_qquickanimatedimage::mirror_notRunning_data()
{
QTest::addColumn<QUrl>("fileUrl");
QTest::newRow("paused") << testFileUrl("stickmanpause.qml");
QTest::newRow("stopped") << testFileUrl("stickmanstopped.qml");
}
void tst_qquickanimatedimage::remote_data()
{
QTest::addColumn<QString>("fileName");
QTest::addColumn<bool>("paused");
QTest::newRow("playing") << "stickman.qml" << false;
QTest::newRow("paused") << "stickmanpause.qml" << true;
}
void tst_qquickanimatedimage::remote()
{
QFETCH(QString, fileName);
QFETCH(bool, paused);
ThreadedTestHTTPServer server(dataDirectory());
QQmlEngine engine;
QQmlComponent component(&engine, server.url(fileName));
QTRY_VERIFY(component.isReady());
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QTRY_VERIFY(anim->isPlaying());
if (paused) {
QTRY_VERIFY(anim->isPaused());
QCOMPARE(anim->currentFrame(), 2);
}
QVERIFY(anim->status() != QQuickAnimatedImage::Error);
delete anim;
}
void tst_qquickanimatedimage::sourceSize()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stickmanscaled.qml"));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QCOMPARE(anim->width(),240.0);
QCOMPARE(anim->height(),180.0);
QCOMPARE(anim->sourceSize(),QSize(160,120));
delete anim;
}
void tst_qquickanimatedimage::sourceSizeReadOnly()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stickmanerror1.qml"));
QVERIFY(component.isError());
QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
}
void tst_qquickanimatedimage::invalidSource()
{
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile("relative"));
QVERIFY(component.isReady());
QTest::ignoreMessage(QtWarningMsg, "file:relative:2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
QVERIFY(anim->isPlaying());
QVERIFY(!anim->isPaused());
QCOMPARE(anim->currentFrame(), 0);
QCOMPARE(anim->frameCount(), 0);
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Error);
delete anim;
}
void tst_qquickanimatedimage::sourceSizeChanges()
{
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nAnimatedImage { source: srcImage }", QUrl::fromLocalFile(""));
QTRY_VERIFY(component.isReady());
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", "");
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage*>(component.create());
QVERIFY(anim != nullptr);
QSignalSpy sourceSizeSpy(anim, SIGNAL(sourceSizeChanged()));
// Local
ctxt->setContextProperty("srcImage", QUrl(""));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
QTRY_COMPARE(sourceSizeSpy.count(), 0);
ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 1);
ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 1);
ctxt->setContextProperty("srcImage", testFileUrl("hearts_copy.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 1);
ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 2);
ctxt->setContextProperty("srcImage", QUrl(""));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
QTRY_COMPARE(sourceSizeSpy.count(), 3);
// Remote
ctxt->setContextProperty("srcImage", server.url("/hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 4);
ctxt->setContextProperty("srcImage", server.url("/hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 4);
ctxt->setContextProperty("srcImage", server.url("/hearts_copy.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 4);
ctxt->setContextProperty("srcImage", server.url("/colors.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(sourceSizeSpy.count(), 5);
ctxt->setContextProperty("srcImage", QUrl(""));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
QTRY_COMPARE(sourceSizeSpy.count(), 6);
delete anim;
}
void tst_qquickanimatedimage::sourceSizeChanges_intermediate()
{
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nAnimatedImage { readonly property int testWidth: status === AnimatedImage.Ready ? sourceSize.width : -1; source: srcImage }", QUrl::fromLocalFile(""));
QTRY_VERIFY(component.isReady());
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", "");
QScopedPointer<QQuickAnimatedImage> anim(qobject_cast<QQuickAnimatedImage*>(component.create()));
QVERIFY(anim != nullptr);
ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(anim->property("testWidth").toInt(), anim->sourceSize().width());
ctxt->setContextProperty("srcImage", testFileUrl("hearts_copy.gif"));
QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
QTRY_COMPARE(anim->property("testWidth").toInt(), anim->sourceSize().width());
}
void tst_qquickanimatedimage::qtbug_16520()
{
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug-16520.qml"));
QTRY_VERIFY(component.isReady());
QQuickRectangle *root = qobject_cast<QQuickRectangle *>(component.create());
QVERIFY(root);
QQuickAnimatedImage *anim = root->findChild<QQuickAnimatedImage*>("anim");
QVERIFY(anim != nullptr);
anim->setProperty("source", server.urlString("/stickman.gif"));
QTRY_COMPARE(anim->opacity(), qreal(0));
QTRY_COMPARE(anim->opacity(), qreal(1));
delete anim;
delete root;
}
void tst_qquickanimatedimage::progressAndStatusChanges()
{
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
qRegisterMetaType<QQuickImageBase::Status>();
QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(QUrl)));
QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
// Same image
ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
QTRY_COMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 0);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 0);
// Loading local file
ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
QTRY_COMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 1);
QTRY_COMPARE(progressSpy.count(), 0);
QTRY_COMPARE(statusSpy.count(), 1);
// Loading remote file
ctxt->setContextProperty("srcImage", server.url("/stickman.gif"));
QTRY_COMPARE(obj->status(), QQuickImage::Loading);
QTRY_COMPARE(obj->progress(), 0.0);
QTRY_COMPARE(obj->status(), QQuickImage::Ready);
QTRY_COMPARE(obj->progress(), 1.0);
QTRY_COMPARE(sourceSpy.count(), 2);
QTRY_VERIFY(progressSpy.count() > 1);
QTRY_COMPARE(statusSpy.count(), 3);
ctxt->setContextProperty("srcImage", "");
QTRY_COMPARE(obj->status(), QQuickImage::Null);
QTRY_COMPARE(obj->progress(), 0.0);
QTRY_COMPARE(sourceSpy.count(), 3);
QTRY_VERIFY(progressSpy.count() > 2);
QTRY_COMPARE(statusSpy.count(), 4);
delete obj;
}
void tst_qquickanimatedimage::playingAndPausedChanges()
{
QQmlEngine engine;
QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("srcImage", QUrl(""));
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickAnimatedImage *obj = qobject_cast<QQuickAnimatedImage*>(component.create());
QVERIFY(obj != nullptr);
QCOMPARE(obj->status(), QQuickAnimatedImage::Null);
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QSignalSpy playingSpy(obj, SIGNAL(playingChanged()));
QSignalSpy pausedSpy(obj, SIGNAL(pausedChanged()));
// initial state
obj->setProperty("playing", true);
obj->setProperty("paused", false);
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 0);
QTRY_COMPARE(pausedSpy.count(), 0);
obj->setProperty("playing", false);
obj->setProperty("paused", true);
QTRY_VERIFY(!obj->isPlaying());
QTRY_VERIFY(obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 1);
QTRY_COMPARE(pausedSpy.count(), 1);
obj->setProperty("playing", true);
obj->setProperty("paused", false);
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 2);
QTRY_COMPARE(pausedSpy.count(), 2);
ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 2);
QTRY_COMPARE(pausedSpy.count(), 2);
obj->setProperty("paused", true);
QTRY_VERIFY(obj->isPlaying());
QTRY_VERIFY(obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 2);
QTRY_COMPARE(pausedSpy.count(), 3);
obj->setProperty("playing", false);
QTRY_VERIFY(!obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 3);
QTRY_COMPARE(pausedSpy.count(), 4);
obj->setProperty("playing", true);
// Cannot animate this image, playing will be false
ctxt->setContextProperty("srcImage", testFileUrl("green.png"));
QTRY_VERIFY(!obj->isPlaying());
QTRY_VERIFY(!obj->isPaused());
QTRY_COMPARE(playingSpy.count(), 5);
QTRY_COMPARE(pausedSpy.count(), 4);
delete obj;
}
void tst_qquickanimatedimage::noCaching()
{
QQuickView window, window_nocache;
window.setSource(testFileUrl("colors.qml"));
window_nocache.setSource(testFileUrl("colors_nocache.qml"));
window.show();
window_nocache.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QVERIFY(QTest::qWaitForWindowExposed(&window_nocache));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
QVERIFY(anim);
QQuickAnimatedImage *anim_nocache = qobject_cast<QQuickAnimatedImage *>(window_nocache.rootObject());
QVERIFY(anim_nocache);
QCOMPARE(anim->frameCount(), anim_nocache->frameCount());
// colors.gif only has 3 frames so this should be fast
for (int loops = 0; loops <= 2; ++loops) {
for (int frame = 0; frame < anim->frameCount(); ++frame) {
anim->setCurrentFrame(frame);
anim_nocache->setCurrentFrame(frame);
QImage image_cache = window.grabWindow();
QImage image_nocache = window_nocache.grabWindow();
QCOMPARE(image_cache, image_nocache);
}
}
}
void tst_qquickanimatedimage::sourceChangesOnFrameChanged()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("colors.qml"));
QVector<QQuickAnimatedImage*> images;
// Run multiple animations in parallel, this should be fast
for (int loops = 0; loops < 25; ++loops) {
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
// QTBUG-67427: this should not produce a segfault
QObject::connect(anim,
&QQuickAnimatedImage::frameChanged,
[this, anim]() { anim->setSource(testFileUrl("hearts.gif")); });
QVERIFY(anim);
QVERIFY(anim->isPlaying());
images.append(anim);
}
for (auto *anim : images)
QTRY_COMPARE(anim->source(), testFileUrl("hearts.gif"));
qDeleteAll(images);
}
void tst_qquickanimatedimage::currentFrame()
{
QQuickView window;
window.setSource(testFileUrl("currentframe.qml"));
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject());
QVERIFY(anim);
QSignalSpy frameChangedSpy(anim, SIGNAL(frameChanged()));
QSignalSpy currentFrameChangedSpy(anim, SIGNAL(currentFrameChanged()));
anim->setCurrentFrame(1);
QCOMPARE(anim->currentFrame(), 1);
QCOMPARE(frameChangedSpy.count(), 1);
QCOMPARE(currentFrameChangedSpy.count(), 1);
QCOMPARE(anim->property("currentFrameChangeCount"), 1);
QCOMPARE(anim->property("frameChangeCount"), 1);
evaluate<void>(anim, "scriptedSetCurrentFrame(2)");
QCOMPARE(anim->currentFrame(), 2);
QCOMPARE(frameChangedSpy.count(), 2);
QCOMPARE(currentFrameChangedSpy.count(), 2);
QCOMPARE(anim->property("currentFrameChangeCount"), 2);
QCOMPARE(anim->property("frameChangeCount"), 2);
}
QTEST_MAIN(tst_qquickanimatedimage)
#include "tst_qquickanimatedimage.moc"