diff --git a/.gitignore b/.gitignore
index 6b57d56ca2..273f0b183c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ src/bitcoin-wallet
src/test/fuzz/fuzz
src/test/test_bitcoin
src/qt/test/test_bitcoin-qt
+src/qml/test/test_bitcoin-qt
# autoreconf
Makefile.in
@@ -52,6 +53,7 @@ src/qml/models/moc_*.cpp
src/qt/forms/ui_*.h
src/qt/test/moc*.cpp
+src/qml/test/moc*.cpp
src/qt/bitcoin-qt.config
src/qt/bitcoin-qt.creator
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index 2d56708716..a7602e3f09 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -108,7 +108,7 @@ dnl BITCOIN_QT_CONFIGURE([MINIMUM-VERSION])
dnl
dnl Outputs: See _BITCOIN_QT_FIND_LIBS
dnl Outputs: Sets variables for all qt-related tools.
-dnl Outputs: bitcoin_enable_qt, bitcoin_enable_qt_dbus, bitcoin_enable_qt_test
+dnl Outputs: bitcoin_enable_qt, bitcoin_enable_qt_dbus, bitcoin_enable_qt_test, bitcoin_enable_qml_test
AC_DEFUN([BITCOIN_QT_CONFIGURE],[
qt_version=">= $1"
qt_lib_prefix="Qt5"
@@ -320,6 +320,10 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
if test "$have_qt_test" = "no"; then
bitcoin_enable_qt_test=no
fi
+ bitcoin_enable_qml_test=yes
+ if test "$have_quick_test" = "no" || test "$bitcoin_cv_static_qt" = "yes"; then
+ bitcoin_enable_qml_test=no
+ fi
bitcoin_enable_qt_dbus=no
if test "$use_dbus" != "no" && test "$have_qt_dbus" = "yes"; then
bitcoin_enable_qt_dbus=yes
@@ -348,6 +352,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
AC_SUBST(QT_LDFLAGS)
AC_SUBST(QT_DBUS_INCLUDES)
AC_SUBST(QT_TEST_INCLUDES)
+ AC_SUBST(QT_QMLTEST_INCLUDES)
AC_SUBST(QT_SELECT, qt5)
AC_SUBST(MOC_DEFS)
])
@@ -438,7 +443,7 @@ dnl _BITCOIN_QT_FIND_LIBS
dnl ---------------------
dnl
dnl Outputs: All necessary QT_* variables are set.
-dnl Outputs: have_qt_test and have_qt_dbus are set (if applicable) to yes|no.
+dnl Outputs: have_qt_test, have_quick_test, and have_qt_dbus are set (if applicable) to yes|no.
AC_DEFUN([_BITCOIN_QT_FIND_LIBS],[
BITCOIN_QT_CHECK([
PKG_CHECK_MODULES([QT_CORE], [${qt_lib_prefix}Core${qt_lib_suffix} $qt_version], [QT_INCLUDES="$QT_CORE_CFLAGS $QT_INCLUDES" QT_LIBS="$QT_CORE_LIBS $QT_LIBS"],
@@ -481,6 +486,10 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS],[
PKG_CHECK_MODULES([QT_QUICKCONTROLS], [${qt_lib_prefix}QuickControls2${qt_lib_suffix} $qt_version], [QT_INCLUDES="$QT_QUICKCONTROLS_CFLAGS $QT_INCLUDES" QT_LIBS="$QT_QUICKCONTROLS_LIBS $QT_LIBS"],
[BITCOIN_QT_FAIL([${qt_lib_prefix}QuickControls2${qt_lib_suffix} $qt_version not found])])
])
+ BITCOIN_QT_CHECK([
+ PKG_CHECK_MODULES([QT_QUICKTEST], [${qt_lib_prefix}QuickTest${qt_lib_suffix} $qt_version], [QT_QMLTEST_INCLUDES="$QT_QUICKTEST_CFLAGS"; have_quick_test=yes], [have_quick_test=no])
+ ])
+
AC_DEFINE([USE_QML], [1], [Define to 1 to use QML-based GUI])
fi
])
diff --git a/ci/test/00_setup_env_mac_native.sh b/ci/test/00_setup_env_mac_native.sh
index c9f65bf397..709229c524 100755
--- a/ci/test/00_setup_env_mac_native.sh
+++ b/ci/test/00_setup_env_mac_native.sh
@@ -9,7 +9,7 @@ export LC_ALL=C.UTF-8
export HOST=x86_64-apple-darwin
export PIP_PACKAGES="zmq"
export GOAL="install"
-export BITCOIN_CONFIG="--with-gui --with-miniupnpc --with-natpmp --enable-reduce-exports"
+export BITCOIN_CONFIG="--with-gui --with-miniupnpc --with-natpmp --enable-reduce-exports CXXFLAGS=-Wno-shadow-field"
export CI_OS_NAME="macos"
export NO_DEPENDS=1
export OSX_SDK=""
diff --git a/configure.ac b/configure.ac
index c26c04cf79..31ec4eae5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1314,6 +1314,7 @@ if test "$enable_fuzz" = "yes"; then
build_bitcoin_libs=no
bitcoin_enable_qt=no
bitcoin_enable_qt_test=no
+ bitcoin_enable_qml_test=no
bitcoin_enable_qt_dbus=no
use_bench=no
use_tests=no
@@ -1327,7 +1328,7 @@ if test "$enable_fuzz" = "yes"; then
else
BITCOIN_QT_INIT
- dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
+ dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qml_test, $bitcoin_enable_qt_dbus
BITCOIN_QT_CONFIGURE([5.11.3])
dnl Keep a copy of the original $QT_INCLUDES and use it when invoking qt's moc
@@ -1764,8 +1765,9 @@ fi
dnl these are only used when qt is enabled
BUILD_TEST_QT=""
+BUILD_TEST_QML=""
if test "$use_qml" != "no"; then
- use_gui_tests=no
+ bitcoin_enable_qt_test=no
fi
if test "$bitcoin_enable_qt" != "no"; then
dnl enable dbus support
@@ -1801,6 +1803,14 @@ if test "$bitcoin_enable_qt" != "no"; then
else
AC_MSG_RESULT([no])
fi
+
+ AC_MSG_CHECKING([whether to build qml/test_bitcoin-qt])
+ if test "$use_qml$use_gui_tests$bitcoin_enable_qml_test" = "yesyesyes"; then
+ AC_MSG_RESULT([yes])
+ BUILD_TEST_QML="yes"
+ else
+ AC_MSG_RESULT([no])
+ fi
fi
AC_MSG_CHECKING([whether to build test_bitcoin])
@@ -1840,6 +1850,7 @@ AM_CONDITIONAL([ENABLE_FUZZ], [test "$enable_fuzz" = "yes"])
AM_CONDITIONAL([ENABLE_FUZZ_BINARY], [test "$enable_fuzz_binary" = "yes"])
AM_CONDITIONAL([ENABLE_QT], [test "$bitcoin_enable_qt" = "yes"])
AM_CONDITIONAL([ENABLE_QT_TESTS], [test "$BUILD_TEST_QT" = "yes"])
+AM_CONDITIONAL([ENABLE_QML_TESTS], [test "$BUILD_TEST_QML" = "yes"])
AM_CONDITIONAL([ENABLE_BENCH], [test "$use_bench" = "yes"])
AM_CONDITIONAL([USE_QRCODE], [test "$use_qr" = "yes"])
AM_CONDITIONAL([USE_LCOV], [test "$use_lcov" = "yes"])
diff --git a/src/Makefile.am b/src/Makefile.am
index feed4a0061..e3cbd90046 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1147,4 +1147,8 @@ if ENABLE_QT_TESTS
include Makefile.qttest.include
endif
+if ENABLE_QML_TESTS
+include Makefile.qmltest.include
+endif
+
include Makefile.univalue.include
diff --git a/src/Makefile.qmltest.include b/src/Makefile.qmltest.include
new file mode 100644
index 0000000000..2fc56e6d24
--- /dev/null
+++ b/src/Makefile.qmltest.include
@@ -0,0 +1,33 @@
+# Copyright (c) 2023 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+bin_PROGRAMS += qml/test/test_bitcoin-qt
+
+TEST_QML_MOC_CPP = qml/test/moc_setup.cpp
+
+TEST_QML_H = qml/test/setup.h qml/test/testimageprovider.h
+
+qml_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) \
+ $(QT_INCLUDES) $(QT_QMLTEST_INCLUDES) $(BOOST_CPPFLAGS)
+
+qml_test_test_bitcoin_qt_SOURCES = \
+ qml/bitcoin_qml.qrc \
+ qml/test/setup.cpp \
+ qml/test/testimageprovider.cpp \
+ $(TEST_QML_H)
+
+nodist_qml_test_test_bitcoin_qt_SOURCES = $(TEST_QML_MOC_CPP) $(QML_QRC_CPP)
+
+qml_test_test_bitcoin_qt_LDADD = $(QT_LIBS) $(QT_QUICKTEST_LIBS)
+qml_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
+qml_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
+
+CLEAN_BITCOIN_QML_TEST = $(TEST_QML_MOC_CPP)
+
+CLEANFILES += $(CLEAN_BITCOIN_QML_TEST)
+
+test_bitcoin_qt_qml: qml/test/test_bitcoin-qt$(EXEEXT)
+
+test_bitcoin_qt_qml_clean: FORCE
+ rm -f $(CLEAN_BITCOIN_QML_TEST) $(qml_test_test_bitcoin_qt_OBJECTS)
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index ba032ee58f..3d6c148c89 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -390,6 +390,7 @@ QML_RES_QML = \
qml/pages/onboarding/OnboardingStorageAmount.qml \
qml/pages/onboarding/OnboardingStorageLocation.qml \
qml/pages/onboarding/OnboardingStrengthen.qml \
+ qml/pages/onboarding/OnboardingWizard.qml \
qml/pages/settings/SettingsAbout.qml \
qml/pages/settings/SettingsBlockClockDisplayMode.qml \
qml/pages/settings/SettingsConnection.qml \
diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc
index 44e0448884..d2caac3cf7 100644
--- a/src/qml/bitcoin_qml.qrc
+++ b/src/qml/bitcoin_qml.qrc
@@ -51,6 +51,7 @@
pages/onboarding/OnboardingStorageAmount.qml
pages/onboarding/OnboardingStorageLocation.qml
pages/onboarding/OnboardingStrengthen.qml
+ pages/onboarding/OnboardingWizard.qml
pages/settings/SettingsAbout.qml
pages/settings/SettingsBlockClockDisplayMode.qml
pages/settings/SettingsConnection.qml
diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml
index dd1fa76bab..1bfaf1bc92 100644
--- a/src/qml/controls/ContinueButton.qml
+++ b/src/qml/controls/ContinueButton.qml
@@ -9,6 +9,7 @@ import org.bitcoincore.qt 1.0
Button {
id: root
hoverEnabled: AppMode.isDesktop
+ objectName: "continueButton"
contentItem: CoreText {
text: parent.text
bold: true
diff --git a/src/qml/pages/main.qml b/src/qml/pages/main.qml
index 99f84fe35c..e2a89b73c8 100644
--- a/src/qml/pages/main.qml
+++ b/src/qml/pages/main.qml
@@ -54,18 +54,7 @@ ApplicationWindow {
Component {
id: onboardingWizard
- SwipeView {
- id: swipeView
- property bool finished: false
- interactive: false
-
- OnboardingCover {}
- OnboardingStrengthen {}
- OnboardingBlockclock {}
- OnboardingStorageLocation {}
- OnboardingStorageAmount {}
- OnboardingConnection {}
-
+ OnboardingWizard {
onFinishedChanged: main.push(node)
}
}
diff --git a/src/qml/pages/onboarding/OnboardingBlockclock.qml b/src/qml/pages/onboarding/OnboardingBlockclock.qml
index 91950fa9c3..1f99a34caa 100644
--- a/src/qml/pages/onboarding/OnboardingBlockclock.qml
+++ b/src/qml/pages/onboarding/OnboardingBlockclock.qml
@@ -8,6 +8,7 @@ import QtQuick.Layouts 1.15
import "../../controls"
InformationPage {
+ objectName: "onboardingBlockClock"
navLeftDetail: NavButton {
iconSource: "image://images/caret-left"
text: qsTr("Back")
diff --git a/src/qml/pages/onboarding/OnboardingConnection.qml b/src/qml/pages/onboarding/OnboardingConnection.qml
index d5c5b5875c..3cc834653d 100644
--- a/src/qml/pages/onboarding/OnboardingConnection.qml
+++ b/src/qml/pages/onboarding/OnboardingConnection.qml
@@ -11,6 +11,7 @@ import "../settings"
Page {
background: null
+ objectName: "onboardingConnection"
clip: true
SwipeView {
id: connections
diff --git a/src/qml/pages/onboarding/OnboardingCover.qml b/src/qml/pages/onboarding/OnboardingCover.qml
index 2a7dcbd237..48151d2340 100644
--- a/src/qml/pages/onboarding/OnboardingCover.qml
+++ b/src/qml/pages/onboarding/OnboardingCover.qml
@@ -12,6 +12,7 @@ import "../settings"
Page {
background: null
clip: true
+ objectName: "onboardingCover"
SwipeView {
id: introductions
anchors.fill: parent
diff --git a/src/qml/pages/onboarding/OnboardingStorageAmount.qml b/src/qml/pages/onboarding/OnboardingStorageAmount.qml
index e4cdf06e20..04d0afa8fb 100644
--- a/src/qml/pages/onboarding/OnboardingStorageAmount.qml
+++ b/src/qml/pages/onboarding/OnboardingStorageAmount.qml
@@ -10,6 +10,7 @@ import "../../components"
import "../settings"
Page {
+ objectName: "onboardingStorageAmount"
background: null
clip: true
SwipeView {
diff --git a/src/qml/pages/onboarding/OnboardingStorageLocation.qml b/src/qml/pages/onboarding/OnboardingStorageLocation.qml
index b2c3aa1e00..1d2e7d7088 100644
--- a/src/qml/pages/onboarding/OnboardingStorageLocation.qml
+++ b/src/qml/pages/onboarding/OnboardingStorageLocation.qml
@@ -10,6 +10,7 @@ import "../../controls"
import "../../components"
InformationPage {
+ objectName: "onboardingStorageLocation"
navLeftDetail: NavButton {
iconSource: "image://images/caret-left"
text: qsTr("Back")
diff --git a/src/qml/pages/onboarding/OnboardingStrengthen.qml b/src/qml/pages/onboarding/OnboardingStrengthen.qml
index df4b803c71..27a4a6704a 100644
--- a/src/qml/pages/onboarding/OnboardingStrengthen.qml
+++ b/src/qml/pages/onboarding/OnboardingStrengthen.qml
@@ -8,6 +8,7 @@ import QtQuick.Layouts 1.15
import "../../controls"
InformationPage {
+ objectName: "onboardingStrengthen"
navLeftDetail: NavButton {
iconSource: "image://images/caret-left"
text: qsTr("Back")
diff --git a/src/qml/pages/onboarding/OnboardingWizard.qml b/src/qml/pages/onboarding/OnboardingWizard.qml
new file mode 100644
index 0000000000..ac07332a61
--- /dev/null
+++ b/src/qml/pages/onboarding/OnboardingWizard.qml
@@ -0,0 +1,19 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+SwipeView {
+ id: swipeView
+ property bool finished: false
+ interactive: false
+
+ OnboardingCover {}
+ OnboardingStrengthen {}
+ OnboardingBlockclock {}
+ OnboardingStorageLocation {}
+ OnboardingStorageAmount {}
+ OnboardingConnection {}
+}
diff --git a/src/qml/test/org/bitcoincore/qt/AppMode.qml b/src/qml/test/org/bitcoincore/qt/AppMode.qml
new file mode 100644
index 0000000000..6a96a929b3
--- /dev/null
+++ b/src/qml/test/org/bitcoincore/qt/AppMode.qml
@@ -0,0 +1,16 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+pragma Singleton
+import QtQuick 2.15
+
+Item {
+ property bool isDesktop: true
+ property bool isMobile: false
+ enum Mode {
+ DESKTOP,
+ MOBILE
+ }
+ property string state: "MOBILE"
+}
diff --git a/src/qml/test/org/bitcoincore/qt/qmldir b/src/qml/test/org/bitcoincore/qt/qmldir
new file mode 100644
index 0000000000..a608a4b706
--- /dev/null
+++ b/src/qml/test/org/bitcoincore/qt/qmldir
@@ -0,0 +1,6 @@
+# Copyright (c) 2023 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+module org.bitcoincore.qt
+singleton AppMode 1.0 AppMode.qml
diff --git a/src/qml/test/setup.cpp b/src/qml/test/setup.cpp
new file mode 100644
index 0000000000..3144a82e88
--- /dev/null
+++ b/src/qml/test/setup.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include
+
+#if defined(HAVE_CONFIG_H)
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+void Setup::qmlEngineAvailable(QQmlEngine * engine) {
+ engine->addImageProvider(QStringLiteral("images"), new TestImageProvider());
+}
+
+QUICK_TEST_MAIN_WITH_SETUP(onboarding, Setup)
diff --git a/src/qml/test/setup.h b/src/qml/test/setup.h
new file mode 100644
index 0000000000..77b9757f12
--- /dev/null
+++ b/src/qml/test/setup.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_QML_TEST_SETUP_H
+#define BITCOIN_QML_TEST_SETUP_H
+
+#include
+#include
+
+class Setup : public QObject
+{
+ Q_OBJECT
+
+public:
+ Setup() = default;
+ ~Setup() = default;
+
+public Q_SLOTS:
+ void qmlEngineAvailable(QQmlEngine * engine);
+};
+
+#endif // BITCOIN_QML_TEST_SETUP_H
diff --git a/src/qml/test/testimageprovider.cpp b/src/qml/test/testimageprovider.cpp
new file mode 100644
index 0000000000..484450ffcd
--- /dev/null
+++ b/src/qml/test/testimageprovider.cpp
@@ -0,0 +1,110 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+TestImageProvider::TestImageProvider()
+ : QQuickImageProvider{QQuickImageProvider::Pixmap}
+{
+}
+
+QPixmap TestImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requested_size)
+{
+ if (!size || !requested_size.isValid()) {
+ return {};
+ }
+
+ if (id == "arrow-down") {
+ *size = requested_size;
+ return QIcon(":/icons/arrow-down").pixmap(requested_size);
+ }
+
+ if (id == "arrow-up") {
+ *size = requested_size;
+ return QIcon(":/icons/arrow-up").pixmap(requested_size);
+ }
+
+ if (id == "bitcoin-circle") {
+ *size = requested_size;
+ return QIcon(":/icons/bitcoin-circle").pixmap(requested_size);
+ }
+
+ if (id == "blocktime-dark") {
+ *size = requested_size;
+ return QIcon(":/icons/blocktime-dark").pixmap(requested_size);
+ }
+
+ if (id == "blocktime-light") {
+ *size = requested_size;
+ return QIcon(":/icons/blocktime-light").pixmap(requested_size);
+ }
+
+ if (id == "app") {
+ *size = requested_size;
+ return QIcon(":/icons/bitcoin").pixmap(requested_size);
+ }
+
+ if (id == "caret-left") {
+ *size = requested_size;
+ return QIcon(":/icons/caret-left").pixmap(requested_size);
+ }
+
+ if (id == "caret-right") {
+ *size = requested_size;
+ return QIcon(":/icons/caret-right").pixmap(requested_size);
+ }
+
+ if (id == "check") {
+ *size = requested_size;
+ return QIcon(":/icons/check").pixmap(requested_size);
+ }
+
+ if (id == "cross") {
+ *size = requested_size;
+ return QIcon(":/icons/cross").pixmap(requested_size);
+ }
+
+ if (id == "export") {
+ *size = requested_size;
+ return QIcon(":/icons/export").pixmap(requested_size);
+ }
+
+ if (id == "gear") {
+ *size = requested_size;
+ return QIcon(":/icons/gear").pixmap(requested_size);
+ }
+
+ if (id == "info") {
+ *size = requested_size;
+ return QIcon(":/icons/info").pixmap(requested_size);
+ }
+
+ if (id == "network-dark") {
+ *size = requested_size;
+ return QIcon(":/icons/network-dark").pixmap(requested_size);
+ }
+
+ if (id == "network-light") {
+ *size = requested_size;
+ return QIcon(":/icons/network-light").pixmap(requested_size);
+ }
+
+ if (id == "storage-dark") {
+ *size = requested_size;
+ return QIcon(":/icons/storage-dark").pixmap(requested_size);
+ }
+
+ if (id == "storage-light") {
+ *size = requested_size;
+ return QIcon(":/icons/storage-light").pixmap(requested_size);
+ }
+
+ return {};
+}
diff --git a/src/qml/test/testimageprovider.h b/src/qml/test/testimageprovider.h
new file mode 100644
index 0000000000..922a0ef891
--- /dev/null
+++ b/src/qml/test/testimageprovider.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QML_TEST_TESTIMAGEPROVIDER_H
+#define BITCOIN_QML_TEST_TESTIMAGEPROVIDER_H
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+class QSize;
+class QString;
+QT_END_NAMESPACE
+
+class TestImageProvider : public QQuickImageProvider
+{
+public:
+ explicit TestImageProvider();
+
+ QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requested_size) override;
+
+};
+
+#endif // BITCOIN_QML_TEST_TESTIMAGEPROVIDER_H
diff --git a/src/qml/test/tst_onboarding.qml b/src/qml/test/tst_onboarding.qml
new file mode 100644
index 0000000000..e2a9e66ad0
--- /dev/null
+++ b/src/qml/test/tst_onboarding.qml
@@ -0,0 +1,64 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import QtQuick 2.15
+import QtTest 1.15
+import "../controls"
+import "../pages/onboarding"
+
+Rectangle {
+ id: root
+ width: 640
+ height: 665
+ color: Theme.color.background
+
+ OnboardingWizard {
+ id: onboardingWizard
+ anchors.fill: parent
+ }
+
+ TestCase {
+ id: onboardingFlow
+ when: windowShown
+
+ function test_all_continue_buttons() {
+ verify(onboardingWizard.currentIndex == 0)
+
+ var cover = findChild(onboardingWizard, "onboardingCover")
+ verify(cover, onboardingWizard.currentItem)
+ mouseClick(findChild(cover, "continueButton"))
+ verify(onboardingWizard.currentIndex == 1)
+ wait(200)
+
+ var strengthen = findChild(onboardingWizard, "onboardingStrengthen")
+ verify(strengthen, onboardingWizard.currentItem)
+ mouseClick(findChild(strengthen, "continueButton"))
+ verify(onboardingWizard.currentIndex == 2)
+ wait(200)
+
+ var blockClock = findChild(onboardingWizard, "onboardingBlockClock")
+ verify(blockClock, onboardingWizard.currentItem)
+ mouseClick(findChild(blockClock, "continueButton"))
+ verify(onboardingWizard.currentIndex == 3)
+ wait(200)
+
+ var storageLocation = findChild(onboardingWizard, "onboardingStorageLocation")
+ verify(storageLocation, onboardingWizard.currentItem)
+ mouseClick(findChild(storageLocation, "continueButton"))
+ verify(onboardingWizard.currentIndex == 4)
+ wait(200)
+
+ var storageAmount = findChild(onboardingWizard, "onboardingStorageAmount")
+ verify(storageAmount, onboardingWizard.currentItem)
+ mouseClick(findChild(storageAmount, "continueButton"))
+ verify(onboardingWizard.currentIndex == 5)
+ wait(200)
+
+ var connection = findChild(onboardingWizard, "onboardingConnection")
+ verify(connection, onboardingWizard.currentItem)
+ mouseClick(findChild(connection, "continueButton"))
+ verify(onboardingWizard.finished)
+ }
+ }
+}