23QQuickItem *QQuickVisualTestUtils::findVisibleChild(QQuickItem *parent,
const QString &objectName)
25 QQuickItem *item =
nullptr;
26 QList<QQuickItem*> items = parent->findChildren<QQuickItem*>(objectName);
27 for (
int i = 0; i < items.size(); ++i) {
28 if (items.at(i)->isVisible() && !QQuickItemPrivate::get(items.at(i))->culled) {
107 forEachStep(steps, [&](qreal progress) {
108 QQuickTest::pointerMove(mPointingDevice, mWindow, 0, lerpPoints(mFrom, pos, progress));
109 QTest::qWait(delayInMilliseconds);
147 auto maybeSaveImagesForDebugging = [ia, ib](QDebug &debug) {
148 if (!lcCompareImages().isDebugEnabled())
151 const QDir saveDir(QCoreApplication::applicationDirPath());
152 QString imageFileNamePrefix = QString::fromUtf8(
"%1-%2").arg(
153 QString::fromUtf8(QTest::currentAppName()),
154 QString::fromUtf8(QTest::currentTestFunction()));
155 if (QTest::currentDataTag())
156 imageFileNamePrefix.append(QStringLiteral(
"-") + QString::fromUtf8(QTest::currentDataTag()));
158 const QString actualImageFilePath = saveDir.filePath(imageFileNamePrefix + QLatin1String(
"-actual.png"));
159 const bool actualImageSaved = ia.save(actualImageFilePath);
160 if (!actualImageSaved)
161 qWarning() <<
"Failed to save actual image to" << actualImageFilePath;
163 const QString expectedImageFilePath = saveDir.filePath(imageFileNamePrefix + QLatin1String(
"-expected.png"));
164 const bool expectedImageSaved = ib.save(expectedImageFilePath);
165 if (!expectedImageSaved)
166 qWarning() <<
"Failed to save expected image to" << expectedImageFilePath;
168 if (actualImageSaved && expectedImageSaved) {
169 debug.noquote() <<
"\nActual image saved to:" << actualImageFilePath;
170 debug <<
"\nExpected image saved to:" << expectedImageFilePath;
174 if (ia.size() != ib.size()) {
175 QDebug debug(errorMessage);
176 debug <<
"Images are of different size:" << ia.size() << ib.size()
177 <<
"DPR:" << ia.devicePixelRatio() << ib.devicePixelRatio();
178 maybeSaveImagesForDebugging(debug);
181 if (ia.format() != ib.format()) {
182 QDebug debug(errorMessage);
183 debug <<
"Images are of different formats:" << ia.format() << ib.format();
184 maybeSaveImagesForDebugging(debug);
187 if (ia.depth() != 32) {
188 QDebug debug(errorMessage);
189 debug <<
"This function only supports bit depths of 32 - depth of images is:" << ia.depth();
190 maybeSaveImagesForDebugging(debug);
196 const int tolerance = 5;
197 for (
int y=0; y<h; ++y) {
198 const uint *as= (
const uint *) ia.constScanLine(y);
199 const uint *bs= (
const uint *) ib.constScanLine(y);
200 for (
int x=0; x<w; ++x) {
205 if ((a & 0xff000000) != (b & 0xff000000)
206 || qAbs(qRed(a) - qRed(b)) > tolerance
207 || qAbs(qGreen(a) - qGreen(b)) > tolerance
208 || qAbs(qBlue(a) - qBlue(b)) > tolerance) {
209 QDebug debug(errorMessage);
210 debug <<
"Mismatch at:" << x << y <<
':'
211 << Qt::hex << Qt::showbase << a << b;
212 maybeSaveImagesForDebugging(debug);
229QQuickItem *QQuickVisualTestUtils::findViewDelegateItem(QQuickItemView *itemView,
int index, FindViewDelegateItemFlags flags)
251QQuickVisualTestUtils::QQuickApplicationHelper::QQuickApplicationHelper(QQmlDataTest *testCase,
252 const QString &testFilePath,
const QVariantMap &initialProperties,
const QStringList &qmlImportPaths)
254 for (
const auto &path : qmlImportPaths)
255 engine.addImportPath(path);
257 QQmlComponent component(&engine);
259 component.loadUrl(testCase->testFileUrl(testFilePath));
260 QVERIFY2(component.isReady(), qPrintable(component.errorString()));
261 QObject *rootObject = component.createWithInitialProperties(initialProperties);
262 cleanup.reset(rootObject);
263 if (component.isError() || !rootObject) {
264 errorMessage = QString::fromUtf8(
"Failed to create window: %1").arg(component.errorString()).toUtf8();
268 window = qobject_cast<QQuickWindow*>(rootObject);
270 errorMessage = QString::fromUtf8(
"Root object %1 must be a QQuickWindow subclass").arg(QDebug::toString(window)).toUtf8();
274 if (window->isVisible()) {
275 errorMessage = QString::fromUtf8(
"Expected window not to be visible, but it is").toUtf8();