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