diff --git a/src/accountadapter.cpp b/src/accountadapter.cpp
index eb3f1395e66f82b39bbe4d8d022a1278353d851f..e39c39deccdd267d135eb7c055d54d3c3af2de4e 100644
--- a/src/accountadapter.cpp
+++ b/src/accountadapter.cpp
@@ -36,11 +36,7 @@ AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
 {
     QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, accSrcModel_.get(), "AccountListModel");
     QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, accModel_.get(), "CurrentAccountFilterModel");
-}
 
-void
-AccountAdapter::safeInit()
-{
     connect(&lrcInstance_->accountModel(),
             &NewAccountModel::accountStatusChanged,
             this,
@@ -52,6 +48,10 @@ AccountAdapter::safeInit()
             &AccountAdapter::accountStatusChanged);
 }
 
+void
+AccountAdapter::safeInit()
+{}
+
 NewAccountModel*
 AccountAdapter::getModel()
 {
@@ -76,19 +76,27 @@ AccountAdapter::changeAccount(int row)
 void
 AccountAdapter::connectFailure()
 {
-    Utils::oneShotConnect(&lrcInstance_->accountModel(),
-                          &lrc::api::NewAccountModel::accountRemoved,
-                          [this](const QString& accountId) {
-                              Q_UNUSED(accountId);
-                              Q_EMIT reportFailure();
-                          });
+    Utils::oneShotConnect(
+        &lrcInstance_->accountModel(),
+        &lrc::api::NewAccountModel::accountRemoved,
+        [this](const QString& accountId) {
+            Q_UNUSED(accountId);
+            Q_EMIT accountCreationFailed();
+            Q_EMIT reportFailure();
+        },
+        &lrcInstance_->accountModel(),
+        &lrc::api::NewAccountModel::accountAdded);
 
-    Utils::oneShotConnect(&lrcInstance_->accountModel(),
-                          &lrc::api::NewAccountModel::invalidAccountDetected,
-                          [this](const QString& accountId) {
-                              Q_UNUSED(accountId);
-                              Q_EMIT reportFailure();
-                          });
+    Utils::oneShotConnect(
+        &lrcInstance_->accountModel(),
+        &lrc::api::NewAccountModel::invalidAccountDetected,
+        [this](const QString& accountId) {
+            Q_UNUSED(accountId);
+            Q_EMIT accountCreationFailed();
+            Q_EMIT reportFailure();
+        },
+        &lrcInstance_->accountModel(),
+        &lrc::api::NewAccountModel::accountAdded);
 }
 
 void
@@ -100,6 +108,14 @@ AccountAdapter::createJamiAccount(QString registeredName,
         &lrcInstance_->accountModel(),
         &lrc::api::NewAccountModel::accountAdded,
         [this, registeredName, settings, isCreating](const QString& accountId) {
+            Utils::oneShotConnect(&lrcInstance_->accountModel(),
+                                  &lrc::api::NewAccountModel::accountDetailsChanged,
+                                  [this](const QString& accountId) {
+                                      Q_UNUSED(accountId);
+                                      // For testing purpose
+                                      Q_EMIT accountConfigFinalized();
+                                  });
+
             auto confProps = lrcInstance_->accountModel().getAccountConfig(accountId);
 #ifdef Q_OS_WIN
             confProps.Ringtone.ringtonePath = Utils::GetRingtonePath();
@@ -132,7 +148,9 @@ AccountAdapter::createJamiAccount(QString registeredName,
                                     lrcInstance_->accountModel().getAccountList().indexOf(
                                         accountId));
             }
-        });
+        },
+        this,
+        &AccountAdapter::accountCreationFailed);
 
     connectFailure();
 
@@ -149,27 +167,35 @@ AccountAdapter::createJamiAccount(QString registeredName,
 void
 AccountAdapter::createSIPAccount(const QVariantMap& settings)
 {
-    Utils::oneShotConnect(&lrcInstance_->accountModel(),
-                          &lrc::api::NewAccountModel::accountAdded,
-                          [this, settings](const QString& accountId) {
-                              auto confProps = lrcInstance_->accountModel().getAccountConfig(
-                                  accountId);
-                              // set SIP details
-                              confProps.hostname = settings["hostname"].toString();
-                              confProps.username = settings["username"].toString();
-                              confProps.password = settings["password"].toString();
-                              confProps.routeset = settings["proxy"].toString();
+    Utils::oneShotConnect(
+        &lrcInstance_->accountModel(),
+        &lrc::api::NewAccountModel::accountAdded,
+        [this, settings](const QString& accountId) {
+            Utils::oneShotConnect(&lrcInstance_->accountModel(),
+                                  &lrc::api::NewAccountModel::accountDetailsChanged,
+                                  [this](const QString& accountId) {
+                                      Q_UNUSED(accountId);
+                                      // For testing purpose
+                                      Q_EMIT accountConfigFinalized();
+                                  });
+
+            auto confProps = lrcInstance_->accountModel().getAccountConfig(accountId);
+            // set SIP details
+            confProps.hostname = settings["hostname"].toString();
+            confProps.username = settings["username"].toString();
+            confProps.password = settings["password"].toString();
+            confProps.routeset = settings["proxy"].toString();
 #ifdef Q_OS_WIN
-                              confProps.Ringtone.ringtonePath = Utils::GetRingtonePath();
+            confProps.Ringtone.ringtonePath = Utils::GetRingtonePath();
 #endif
-                              lrcInstance_->accountModel().setAccountConfig(accountId, confProps);
+            lrcInstance_->accountModel().setAccountConfig(accountId, confProps);
 
-                              Q_EMIT lrcInstance_->accountListChanged();
-                              Q_EMIT accountAdded(accountId,
-                                                  lrcInstance_->accountModel()
-                                                      .getAccountList()
-                                                      .indexOf(accountId));
-                          });
+            Q_EMIT lrcInstance_->accountListChanged();
+            Q_EMIT accountAdded(accountId,
+                                lrcInstance_->accountModel().getAccountList().indexOf(accountId));
+        },
+        this,
+        &AccountAdapter::accountCreationFailed);
 
     connectFailure();
 
@@ -187,25 +213,33 @@ AccountAdapter::createSIPAccount(const QVariantMap& settings)
 void
 AccountAdapter::createJAMSAccount(const QVariantMap& settings)
 {
-    Utils::oneShotConnect(&lrcInstance_->accountModel(),
-                          &lrc::api::NewAccountModel::accountAdded,
-                          [this](const QString& accountId) {
-                              if (!lrcInstance_->accountModel().getAccountList().size())
-                                  return;
+    Utils::oneShotConnect(
+        &lrcInstance_->accountModel(),
+        &lrc::api::NewAccountModel::accountAdded,
+        [this](const QString& accountId) {
+            if (!lrcInstance_->accountModel().getAccountList().size())
+                return;
+
+            Utils::oneShotConnect(&lrcInstance_->accountModel(),
+                                  &lrc::api::NewAccountModel::accountDetailsChanged,
+                                  [this](const QString& accountId) {
+                                      Q_UNUSED(accountId);
+                                      // For testing purpose
+                                      Q_EMIT accountConfigFinalized();
+                                  });
 
-                              auto confProps = lrcInstance_->accountModel().getAccountConfig(
-                                  accountId);
+            auto confProps = lrcInstance_->accountModel().getAccountConfig(accountId);
 #ifdef Q_OS_WIN
-                              confProps.Ringtone.ringtonePath = Utils::GetRingtonePath();
+            confProps.Ringtone.ringtonePath = Utils::GetRingtonePath();
 #endif
-                              lrcInstance_->accountModel().setAccountConfig(accountId, confProps);
+            lrcInstance_->accountModel().setAccountConfig(accountId, confProps);
 
-                              Q_EMIT accountAdded(accountId,
-                                                  lrcInstance_->accountModel()
-                                                      .getAccountList()
-                                                      .indexOf(accountId));
-                              Q_EMIT lrcInstance_->accountListChanged();
-                          });
+            Q_EMIT accountAdded(accountId,
+                                lrcInstance_->accountModel().getAccountList().indexOf(accountId));
+            Q_EMIT lrcInstance_->accountListChanged();
+        },
+        this,
+        &AccountAdapter::accountCreationFailed);
 
     connectFailure();
 
@@ -219,6 +253,14 @@ AccountAdapter::createJAMSAccount(const QVariantMap& settings)
 void
 AccountAdapter::deleteCurrentAccount()
 {
+    Utils::oneShotConnect(&lrcInstance_->accountModel(),
+                          &lrc::api::NewAccountModel::accountRemoved,
+                          [this](const QString& accountId) {
+                              Q_UNUSED(accountId);
+                              // For testing purpose
+                              Q_EMIT accountRemoved();
+                          });
+
     lrcInstance_->accountModel().removeAccount(lrcInstance_->get_currentAccountId());
     Q_EMIT lrcInstance_->accountListChanged();
 }
diff --git a/src/accountadapter.h b/src/accountadapter.h
index f4f8e2280fb8473e272b36438d451c710bef5631..313b2ad0de9a94c00911f101039a7828298ddf34 100644
--- a/src/accountadapter.h
+++ b/src/accountadapter.h
@@ -95,7 +95,10 @@ Q_SIGNALS:
 
     // Send report failure to QML to make it show the right UI state .
     void reportFailure();
+    void accountCreationFailed();
     void accountAdded(QString accountId, int index);
+    void accountRemoved();
+    void accountConfigFinalized();
 
 private:
     // Implement what to do when account creation fails.
diff --git a/src/qtutils.h b/src/qtutils.h
index 1ec3101fd26a193a7591cf9ca92f82f9481ea5f8..f42a929df83f0391db648b6e360fa4ac76b67d9d 100644
--- a/src/qtutils.h
+++ b/src/qtutils.h
@@ -74,6 +74,37 @@ oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
     });
 }
 
+template<typename Func1, typename Func2, typename Func3>
+void
+oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
+               Func1 signal,
+               Func2 slot,
+               const typename QtPrivate::FunctionPointer<Func3>::Object* interrupter,
+               Func3 interrupterSignal)
+{
+    QMetaObject::Connection* const connection = new QMetaObject::Connection;
+    QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection;
+    QMetaObject::Connection* const interruptConnection = new QMetaObject::Connection;
+
+    auto disconnectFunc = [connection, disconnectConnection, interruptConnection] {
+        if (connection) {
+            QObject::disconnect(*connection);
+            delete connection;
+        }
+        if (disconnectConnection) {
+            QObject::disconnect(*disconnectConnection);
+            delete disconnectConnection;
+        }
+        if (interruptConnection) {
+            QObject::disconnect(*interruptConnection);
+            delete interruptConnection;
+        }
+    };
+    *connection = QObject::connect(sender, signal, slot);
+    *disconnectConnection = QObject::connect(sender, signal, disconnectFunc);
+    *interruptConnection = QObject::connect(interrupter, interrupterSignal, disconnectFunc);
+}
+
 template<typename Func1, typename Func2>
 void
 oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
diff --git a/src/wizardview/WizardView.qml b/src/wizardview/WizardView.qml
index ef726f0441deb51d1cf11471d7ebc2aa43940b73..01fd8848c9e4d31cdbe8722d617ba46edc1562cb 100644
--- a/src/wizardview/WizardView.qml
+++ b/src/wizardview/WizardView.qml
@@ -47,16 +47,11 @@ Rectangle {
         function onReportFailure() {
             var errorMessage = JamiStrings.errorCreateAccount
 
-            switch(controlPanelStackView.currentIndex) {
-            case importFromDevicePage.stackLayoutIndex:
-                importFromDevicePage.errorOccured(errorMessage)
-                break
-            case importFromBackupPage.stackLayoutIndex:
-                importFromBackupPage.errorOccured(errorMessage)
-                break
-            case connectToAccountManagerPage.stackLayoutIndex:
-                connectToAccountManagerPage.errorOccured(errorMessage)
-                break
+            for (var i = 0; i < controlPanelStackView.children.length; i++) {
+                if (i === controlPanelStackView.currentIndex) {
+                    controlPanelStackView.children[i].errorOccured(errorMessage)
+                    return
+                }
             }
         }
     }
@@ -85,6 +80,8 @@ Rectangle {
         StackLayout {
             id: controlPanelStackView
 
+            objectName: "controlPanelStackView"
+
             function setPage(obj) {
                 for (var i in this.children) {
                     if (this.children[i] === obj) {
@@ -101,6 +98,8 @@ Rectangle {
             WelcomePage {
                 id: welcomePage
 
+                objectName: "welcomePage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
 
                 onScrollToBottom: {
@@ -112,42 +111,56 @@ Rectangle {
             CreateAccountPage {
                 id: createAccountPage
 
+                objectName: "createAccountPage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
             ProfilePage {
                 id: profilePage
 
+                objectName: "profilePage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
             BackupKeyPage {
                 id: backupKeysPage
 
+                objectName: "backupKeysPage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
             ImportFromDevicePage {
                 id: importFromDevicePage
 
+                objectName: "importFromDevicePage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
             ImportFromBackupPage {
                 id: importFromBackupPage
 
+                objectName: "importFromBackupPage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
             ConnectToAccountManagerPage {
                 id: connectToAccountManagerPage
 
+                objectName: "connectToAccountManagerPage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
             CreateSIPAccountPage {
                 id: createSIPAccountPage
 
+                objectName: "createSIPAccountPage"
+
                 onShowThisPage: controlPanelStackView.setPage(this)
             }
 
diff --git a/src/wizardview/components/CreateAccountPage.qml b/src/wizardview/components/CreateAccountPage.qml
index 9156aceb492473cab8ba2c90b3c2ed2ca75bd7e4..843f430d2a05a65dadac20755aa13c55d589147e 100644
--- a/src/wizardview/components/CreateAccountPage.qml
+++ b/src/wizardview/components/CreateAccountPage.qml
@@ -76,11 +76,15 @@ Rectangle {
     StackLayout {
         id: createAccountStack
 
+        objectName: "createAccountStack"
+
         anchors.fill: parent
 
         Rectangle {
             id: nameRegistrationPage
 
+            objectName: "nameRegistrationPage"
+
             property int stackIndex: 0
 
             color: JamiTheme.backgroundColor
@@ -118,6 +122,8 @@ Rectangle {
                 UsernameLineEdit {
                     id: usernameEdit
 
+                    objectName: "usernameEdit"
+
                     Layout.topMargin: 15
                     Layout.preferredHeight: fieldLayoutHeight
                     Layout.preferredWidth:  chooseUsernameButton.width
@@ -205,6 +211,8 @@ Rectangle {
         Rectangle {
             id: passwordSetupPage
 
+            objectName: "passwordSetupPage"
+
             property int stackIndex: 1
 
             color: JamiTheme.backgroundColor
@@ -234,6 +242,8 @@ Rectangle {
                     Switch {
                         id: passwordSwitch
 
+                        objectName: "passwordSwitch"
+
                         Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
                         Layout.leftMargin: -JamiTheme.wizardViewPageLayoutSpacing
                         Layout.topMargin: 5
@@ -250,6 +260,8 @@ Rectangle {
                 MaterialLineEdit {
                     id: passwordEdit
 
+                    objectName: "passwordEdit"
+
                     Layout.preferredHeight: fieldLayoutHeight
                     Layout.preferredWidth: createAccountButton.width
                     Layout.alignment: Qt.AlignHCenter
@@ -267,6 +279,8 @@ Rectangle {
                 MaterialLineEdit {
                     id: passwordConfirmEdit
 
+                    objectName: "passwordConfirmEdit"
+
                     Layout.preferredHeight: fieldLayoutHeight
                     Layout.preferredWidth: createAccountButton.width
                     Layout.alignment: Qt.AlignHCenter
@@ -294,6 +308,8 @@ Rectangle {
                 MaterialButton {
                     id: createAccountButton
 
+                    objectName: "createAccountButton"
+
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: preferredWidth
                     Layout.preferredHeight: preferredHeight
diff --git a/src/wizardview/components/CreateSIPAccountPage.qml b/src/wizardview/components/CreateSIPAccountPage.qml
index c8bdb197d2047794d22aae88060fd7e4317ddcfd..d60b0bf0ff59e7676eecc45980604f5466dd5e26 100644
--- a/src/wizardview/components/CreateSIPAccountPage.qml
+++ b/src/wizardview/components/CreateSIPAccountPage.qml
@@ -38,7 +38,6 @@ Rectangle {
         sipPasswordEdit.clear()
         sipServernameEdit.clear()
         sipProxyEdit.clear()
-        sipUsernameEdit.clear()
     }
 
     Connections {
@@ -87,6 +86,8 @@ Rectangle {
         MaterialLineEdit {
             id: sipServernameEdit
 
+            objectName: "sipServernameEdit"
+
             Layout.alignment: Qt.AlignCenter
             Layout.preferredHeight: fieldLayoutHeight
             Layout.preferredWidth: createAccountButton.width
@@ -102,6 +103,8 @@ Rectangle {
         MaterialLineEdit {
             id: sipProxyEdit
 
+            objectName: "sipProxyEdit"
+
             Layout.alignment: Qt.AlignCenter
             Layout.preferredHeight: fieldLayoutHeight
             Layout.preferredWidth: createAccountButton.width
@@ -115,6 +118,8 @@ Rectangle {
         MaterialLineEdit {
             id: sipUsernameEdit
 
+            objectName: "sipUsernameEdit"
+
             Layout.alignment: Qt.AlignCenter
             Layout.preferredHeight: fieldLayoutHeight
             Layout.preferredWidth: createAccountButton.width
@@ -128,6 +133,8 @@ Rectangle {
         MaterialLineEdit {
             id: sipPasswordEdit
 
+            objectName: "sipPasswordEdit"
+
             Layout.alignment: Qt.AlignCenter
             Layout.preferredHeight: fieldLayoutHeight
             Layout.preferredWidth: createAccountButton.width
@@ -142,6 +149,8 @@ Rectangle {
         MaterialButton {
             id: createAccountButton
 
+            objectName: "createAccountButton"
+
             Layout.alignment: Qt.AlignCenter
             Layout.bottomMargin: JamiTheme.wizardViewPageBackButtonMargins
             Layout.preferredWidth: preferredWidth
diff --git a/src/wizardview/components/ImportFromBackupPage.qml b/src/wizardview/components/ImportFromBackupPage.qml
index d53d508097aa3e7f0e5d0c97338b7d763e355ac9..6ff248bf01f17f9c772ec914ef40fac9efafb6aa 100644
--- a/src/wizardview/components/ImportFromBackupPage.qml
+++ b/src/wizardview/components/ImportFromBackupPage.qml
@@ -145,6 +145,8 @@ Rectangle {
         MaterialLineEdit {
             id: passwordFromBackupEdit
 
+            objectName: "passwordFromBackupEdit"
+
             Layout.preferredHeight: fieldLayoutHeight
             Layout.preferredWidth: connectBtn.width
             Layout.alignment: Qt.AlignCenter
@@ -165,6 +167,8 @@ Rectangle {
         SpinnerButton {
             id: connectBtn
 
+            objectName: "connectBtn"
+
             Layout.alignment: Qt.AlignCenter
             Layout.bottomMargin: errorLabel.visible ? 0 : JamiTheme.wizardViewPageBackButtonMargins
             Layout.preferredWidth: preferredWidth
@@ -195,6 +199,8 @@ Rectangle {
         Label {
             id: errorLabel
 
+            objectName: "errorLabel"
+
             Layout.alignment: Qt.AlignCenter
             Layout.bottomMargin: JamiTheme.wizardViewPageBackButtonMargins
 
diff --git a/src/wizardview/components/ProfilePage.qml b/src/wizardview/components/ProfilePage.qml
index e02be77d3f6a25af699c668f685f6c39d787f428..7d9e061512cdae2fe4db1612007d8d26ce3d4ef2 100644
--- a/src/wizardview/components/ProfilePage.qml
+++ b/src/wizardview/components/ProfilePage.qml
@@ -113,6 +113,8 @@ Rectangle {
         MaterialLineEdit {
             id: aliasEdit
 
+            objectName: "aliasEdit"
+
             property string lastFirstChar
 
             Layout.preferredHeight: fieldLayoutHeight
@@ -152,6 +154,8 @@ Rectangle {
         SpinnerButton {
             id: saveProfileBtn
 
+            objectName: "saveProfileBtn"
+
             Layout.alignment: Qt.AlignCenter
             Layout.preferredWidth: preferredWidth
             Layout.preferredHeight: preferredHeight
diff --git a/tests/qml/resources.qrc b/tests/qml/resources.qrc
index 4d1385ab826e746d807d2a6458d23581001b8c94..ea2093b3f337078f1c3f43669ce2082150e2e0bf 100644
--- a/tests/qml/resources.qrc
+++ b/tests/qml/resources.qrc
@@ -7,5 +7,6 @@
         <file>src/resources/gz_test.gz</file>
         <file>src/resources/png_test.png</file>
         <file>src/tst_FilesToSendContainer.qml</file>
+        <file>src/tst_WizardView.qml</file>
     </qresource>
 </RCC>
diff --git a/tests/qml/src/resources/gz_test.gz b/tests/qml/src/resources/gz_test.gz
index 8b4c8049773fe094ffeb57e3ff1fc9c014c980fa..53789aa1a37e3bc8e1d8e3827e7639ef43f7eda6 100644
Binary files a/tests/qml/src/resources/gz_test.gz and b/tests/qml/src/resources/gz_test.gz differ
diff --git a/tests/qml/src/tst_FilesToSendContainer.qml b/tests/qml/src/tst_FilesToSendContainer.qml
index a0f0c6bfa46b1fdfb875013a69f9274bc3098cc8..ac09e87a6595b38b566a0d9a3e4691a6db864919 100644
--- a/tests/qml/src/tst_FilesToSendContainer.qml
+++ b/tests/qml/src/tst_FilesToSendContainer.qml
@@ -26,7 +26,6 @@ import net.jami.Models 1.0
 import net.jami.Constants 1.0
 
 import "qrc:/src/mainview/components"
-import"../../../src/mainview/components"
 
 ColumnLayout {
     id: root
diff --git a/tests/qml/src/tst_MessageWebViewFooter.qml b/tests/qml/src/tst_MessageWebViewFooter.qml
index f05ec45847c153a153596ce6be528e0d5b20cebc..915948d3cc625d553ee4ef32e2dd07100d26850e 100644
--- a/tests/qml/src/tst_MessageWebViewFooter.qml
+++ b/tests/qml/src/tst_MessageWebViewFooter.qml
@@ -26,7 +26,6 @@ import net.jami.Models 1.0
 import net.jami.Constants 1.0
 
 import "qrc:/src/mainview/components"
-import"../../../src/mainview/components"
 
 ColumnLayout {
     id: root
diff --git a/tests/qml/src/tst_WizardView.qml b/tests/qml/src/tst_WizardView.qml
new file mode 100644
index 0000000000000000000000000000000000000000..0f7d8314ef40668662cfcf9c4cb34f070c061952
--- /dev/null
+++ b/tests/qml/src/tst_WizardView.qml
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2021 by Savoir-faire Linux
+ * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import QtQuick 2.14
+import QtTest 1.2
+
+import net.jami.Adapters 1.0
+import net.jami.Models 1.0
+import net.jami.Constants 1.0
+import net.jami.Enums 1.0
+
+import "qrc:/src/wizardview"
+
+WizardView {
+    id: uut
+
+    SignalSpy {
+        id: spyAccountIsReady
+
+        target: WizardViewStepModel
+        signalName: "accountIsReady"
+    }
+
+    SignalSpy {
+        id: spyAccountIsRemoved
+
+        target: AccountAdapter
+        signalName: "accountRemoved"
+    }
+
+    SignalSpy {
+        id: spyAccountStatusChanged
+
+        target: AccountAdapter
+        signalName: "accountStatusChanged"
+    }
+
+    SignalSpy {
+        id: spyAccountConfigFinalized
+
+        target: AccountAdapter
+        signalName: "accountConfigFinalized"
+    }
+
+    SignalSpy {
+        id: spyReportFailure
+
+        target: AccountAdapter
+        signalName: "reportFailure"
+    }
+
+    TestCase {
+        name: "WelcomePage to different account creation page and return back"
+        when: windowShown
+
+        function test_welcomePageStepInStepOut() {
+            var controlPanelStackView = findChild(uut, "controlPanelStackView")
+
+            var welcomePage = findChild(uut, "welcomePage")
+            var createAccountPage = findChild(uut, "createAccountPage")
+            var importFromDevicePage = findChild(uut, "importFromDevicePage")
+            var importFromBackupPage = findChild(uut, "importFromBackupPage")
+            var connectToAccountManagerPage = findChild(uut, "connectToAccountManagerPage")
+            var createSIPAccountPage = findChild(uut, "createSIPAccountPage")
+
+            // WelcomePage initially
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to createAccount page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateJamiAccount)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    createAccountPage)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to CreateRendezVous page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateRendezVous)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    createAccountPage)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to CreateRendezVous page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.ImportFromDevice)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    importFromDevicePage)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to ImportFromBackup page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.ImportFromBackup)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    importFromBackupPage)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to ConnectToAccountManager page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.ConnectToAccountManager)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    connectToAccountManagerPage)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to CreateSipAccount page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateSipAccount)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    createSIPAccountPage)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+        }
+
+        function test_createAccountPageStepInStepOut() {
+            var controlPanelStackView = findChild(uut, "controlPanelStackView")
+            var welcomePage = findChild(uut, "welcomePage")
+            var createAccountPage = findChild(uut, "createAccountPage")
+
+            var createAccountStack = findChild(createAccountPage, "createAccountStack")
+            var passwordSetupPage = findChild(createAccountPage, "passwordSetupPage")
+            var nameRegistrationPage = findChild(createAccountPage, "nameRegistrationPage")
+
+            // WelcomePage initially
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to createAccount page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateJamiAccount)
+            compare(createAccountPage.isRendezVous, false)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    createAccountPage)
+            compare(createAccountStack.currentIndex, nameRegistrationPage.stackIndex)
+
+            // Go to passwordSetup page
+            WizardViewStepModel.nextStep()
+            compare(createAccountStack.currentIndex, passwordSetupPage.stackIndex)
+
+            // Back
+            WizardViewStepModel.previousStep()
+            compare(createAccountStack.currentIndex, nameRegistrationPage.stackIndex)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to CreateRendezVous page (createAccount)
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateRendezVous)
+            compare(createAccountPage.isRendezVous, true)
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    createAccountPage)
+            compare(createAccountStack.currentIndex, nameRegistrationPage.stackIndex)
+
+            // Go to passwordSetup page
+            WizardViewStepModel.nextStep()
+            compare(createAccountStack.currentIndex, passwordSetupPage.stackIndex)
+
+            // Back
+            WizardViewStepModel.previousStep()
+            compare(createAccountStack.currentIndex, nameRegistrationPage.stackIndex)
+            WizardViewStepModel.previousStep()
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+        }
+    }
+
+    TestCase {
+        name: "Create Jami account ui flow (no registered name)"
+        when: windowShown
+
+        function test_createJamiAccountUiFlow() {
+            spyAccountIsReady.clear()
+            spyAccountIsRemoved.clear()
+            spyAccountStatusChanged.clear()
+            spyAccountConfigFinalized.clear()
+
+            var controlPanelStackView = findChild(uut, "controlPanelStackView")
+
+            var welcomePage = findChild(uut, "welcomePage")
+            var createAccountPage = findChild(uut, "createAccountPage")
+            var profilePage = findChild(uut, "profilePage")
+            var backupKeysPage = findChild(uut, "backupKeysPage")
+
+            var usernameEdit = findChild(createAccountPage, "usernameEdit")
+            var createAccountStack = findChild(createAccountPage, "createAccountStack")
+            var passwordSwitch = findChild(createAccountPage, "passwordSwitch")
+            var passwordEdit = findChild(createAccountPage, "passwordEdit")
+            var passwordConfirmEdit = findChild(createAccountPage, "passwordConfirmEdit")
+            var createAccountButton = findChild(createAccountPage, "createAccountButton")
+
+            var aliasEdit = findChild(profilePage, "aliasEdit")
+            var saveProfileBtn = findChild(profilePage, "saveProfileBtn")
+
+            var password  = "test110"
+            var aliasText = "test101"
+
+            // WelcomePage initially
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to createAccount page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateJamiAccount)
+            compare(createAccountStack.currentIndex, 0)
+            compare(usernameEdit.focus, true)
+
+            // Go to set up password page
+            WizardViewStepModel.nextStep()
+            compare(createAccountStack.currentIndex, 1)
+            passwordSwitch.checked = true
+            compare(passwordEdit.focus, true)
+            passwordEdit.text = password
+            passwordConfirmEdit.text = password
+            createAccountButton.clicked()
+
+            // Wait until the account creation is finished
+            spyAccountIsReady.wait()
+            compare(spyAccountIsReady.count, 1)
+
+            // Now we are in profile page
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    profilePage)
+            compare(aliasEdit.focus, true)
+
+            spyAccountConfigFinalized.wait()
+            compare(spyAccountConfigFinalized.count, 1)
+
+            aliasEdit.text = aliasText
+            saveProfileBtn.clicked()
+
+            var showBackup = (WizardViewStepModel.accountCreationOption ===
+                              WizardViewStepModel.AccountCreationOption.CreateJamiAccount
+                              || WizardViewStepModel.accountCreationOption ===
+                              WizardViewStepModel.AccountCreationOption.CreateRendezVous)
+                              && !AppSettingsManager.getValue(Settings.NeverShowMeAgain)
+            if (showBackup) {
+                compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                        backupKeysPage)
+                WizardViewStepModel.nextStep()
+            }
+
+            // Check alias text
+            compare(SettingsAdapter.getCurrentAccount_Profile_Info_Alias(), aliasText)
+
+            spyAccountStatusChanged.clear()
+
+            // Check if password is set
+            compare(AccountAdapter.savePassword(LRCInstance.currentAccountId, password, "test"),
+                    true)
+
+            // Wait until the account status change is finished
+            spyAccountStatusChanged.wait()
+            verify(spyAccountStatusChanged.count >= 1)
+
+            AccountAdapter.deleteCurrentAccount()
+
+            // Wait until the account removal is finished
+            spyAccountIsRemoved.wait()
+            compare(spyAccountIsRemoved.count, 1)
+        }
+
+        function test_createRendezVousAccountUiFlow() {
+            spyAccountIsReady.clear()
+            spyAccountIsRemoved.clear()
+            spyAccountStatusChanged.clear()
+            spyAccountConfigFinalized.clear()
+
+            var controlPanelStackView = findChild(uut, "controlPanelStackView")
+
+            var welcomePage = findChild(uut, "welcomePage")
+            var createAccountPage = findChild(uut, "createAccountPage")
+            var profilePage = findChild(uut, "profilePage")
+            var backupKeysPage = findChild(uut, "backupKeysPage")
+
+            var usernameEdit = findChild(createAccountPage, "usernameEdit")
+            var createAccountStack = findChild(createAccountPage, "createAccountStack")
+            var passwordSwitch = findChild(createAccountPage, "passwordSwitch")
+            var passwordEdit = findChild(createAccountPage, "passwordEdit")
+            var passwordConfirmEdit = findChild(createAccountPage, "passwordConfirmEdit")
+            var createAccountButton = findChild(createAccountPage, "createAccountButton")
+
+            var aliasEdit = findChild(profilePage, "aliasEdit")
+            var saveProfileBtn = findChild(profilePage, "saveProfileBtn")
+
+            var password  = "test110"
+            var aliasText = "test101"
+
+            // WelcomePage initially
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to createRendezVous page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateRendezVous)
+            compare(createAccountStack.currentIndex, 0)
+            compare(usernameEdit.focus, true)
+
+            // Go to set up password page
+            WizardViewStepModel.nextStep()
+            compare(createAccountStack.currentIndex, 1)
+            passwordSwitch.checked = true
+            compare(passwordEdit.focus, true)
+            passwordEdit.text = password
+            passwordConfirmEdit.text = password
+            createAccountButton.clicked()
+
+            // Wait until the account creation is finished
+            spyAccountIsReady.wait()
+            compare(spyAccountIsReady.count, 1)
+
+            // Now we are in profile page
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    profilePage)
+            compare(aliasEdit.focus, true)
+
+            spyAccountConfigFinalized.wait()
+            compare(spyAccountConfigFinalized.count, 1)
+
+            // Check if it is a RendezVous acc
+            compare(SettingsAdapter.getAccountConfig_RendezVous(), true)
+
+            aliasEdit.text = aliasText
+            saveProfileBtn.clicked()
+
+            var showBackup = (WizardViewStepModel.accountCreationOption ===
+                              WizardViewStepModel.AccountCreationOption.CreateJamiAccount
+                              || WizardViewStepModel.accountCreationOption ===
+                              WizardViewStepModel.AccountCreationOption.CreateRendezVous)
+                              && !AppSettingsManager.getValue(Settings.NeverShowMeAgain)
+            if (showBackup) {
+                compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                        backupKeysPage)
+                WizardViewStepModel.nextStep()
+            }
+
+            // Check alias text
+            compare(SettingsAdapter.getCurrentAccount_Profile_Info_Alias(), aliasText)
+
+            spyAccountStatusChanged.clear()
+
+            // Check if password is set
+            compare(AccountAdapter.savePassword(LRCInstance.currentAccountId, password, "test"),
+                    true)
+
+            // Wait until the account status change is finished
+            spyAccountStatusChanged.wait()
+            verify(spyAccountStatusChanged.count >= 1)
+
+            AccountAdapter.deleteCurrentAccount()
+
+            // Wait until the account removal is finished
+            spyAccountIsRemoved.wait()
+            compare(spyAccountIsRemoved.count, 1)
+        }
+    }
+
+    TestCase {
+        name: "Create Sip account ui flow"
+        when: windowShown
+
+        function test_createSipAccountUiFlow() {
+            spyAccountIsReady.clear()
+            spyAccountIsRemoved.clear()
+            spyAccountStatusChanged.clear()
+            spyAccountConfigFinalized.clear()
+
+            var controlPanelStackView = findChild(uut, "controlPanelStackView")
+
+            var welcomePage = findChild(uut, "welcomePage")
+            var createSIPAccountPage = findChild(uut, "createSIPAccountPage")
+            var profilePage = findChild(uut, "profilePage")
+
+            var sipUsernameEdit = findChild(createSIPAccountPage, "sipUsernameEdit")
+            var sipPasswordEdit = findChild(createSIPAccountPage, "sipPasswordEdit")
+            var sipServernameEdit = findChild(createSIPAccountPage, "sipServernameEdit")
+            var sipProxyEdit = findChild(createSIPAccountPage, "sipProxyEdit")
+            var createAccountButton = findChild(createSIPAccountPage, "createAccountButton")
+
+            var saveProfileBtn = findChild(profilePage, "saveProfileBtn")
+
+            // WelcomePage initially
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to createSipAccount page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.CreateSipAccount)
+            compare(sipServernameEdit.focus, true)
+
+            // Set up paras
+            var userName = "testUserName"
+            var serverName = "testServerName"
+            var password = "testPassword"
+            var proxy = "testProxy"
+
+            sipUsernameEdit.text = userName
+            sipPasswordEdit.text = password
+            sipServernameEdit.text = serverName
+            sipProxyEdit.text = proxy
+
+            createAccountButton.clicked()
+
+            // Wait until the account creation is finished
+            spyAccountIsReady.wait()
+            compare(spyAccountIsReady.count, 1)
+
+            // Now we are in profile page
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    profilePage)
+
+            spyAccountConfigFinalized.wait()
+            compare(spyAccountConfigFinalized.count, 1)
+
+            // Check if paras match with setup
+            compare(SettingsAdapter.getAccountConfig_RouteSet(), proxy)
+            compare(SettingsAdapter.getAccountConfig_Username(), userName)
+            compare(SettingsAdapter.getAccountConfig_Hostname(), serverName)
+            compare(SettingsAdapter.getAccountConfig_Password(), password)
+
+            WizardViewStepModel.nextStep()
+
+            AccountAdapter.deleteCurrentAccount()
+
+            // Wait until the account removal is finished
+            spyAccountIsRemoved.wait()
+            compare(spyAccountIsRemoved.count, 1)
+        }
+    }
+
+    TestCase {
+        name: "Create Jami account from backup ui flow"
+        when: windowShown
+
+        function test_createJamiAccountFromBackupUiFlow() {
+            spyAccountIsReady.clear()
+            spyAccountIsRemoved.clear()
+            spyAccountConfigFinalized.clear()
+            spyReportFailure.clear()
+
+            var controlPanelStackView = findChild(uut, "controlPanelStackView")
+
+            var welcomePage = findChild(uut, "welcomePage")
+            var importFromBackupPage = findChild(uut, "importFromBackupPage")
+            var profilePage = findChild(uut, "profilePage")
+
+            var passwordFromBackupEdit = findChild(importFromBackupPage, "passwordFromBackupEdit")
+            var connectBtn = findChild(importFromBackupPage, "connectBtn")
+            var errorLabel = findChild(importFromBackupPage, "errorLabel")
+
+            // WelcomePage initially
+            compare(controlPanelStackView.children[controlPanelStackView.currentIndex],
+                    welcomePage)
+
+            // Go to importFromBackup page
+            WizardViewStepModel.startAccountCreationFlow(
+                        WizardViewStepModel.AccountCreationOption.ImportFromBackup)
+            compare(passwordFromBackupEdit.focus, true)
+
+            var fileName = "gz_test.gz"
+            var password = "qqq"
+            importFromBackupPage.filePath = UtilsAdapter.toFileAbsolutepath(
+                        "tests/qml/src/resources/gz_test.gz") + "/" + fileName
+
+            compare(connectBtn.enabled, true)
+
+            // Create without password
+            connectBtn.clicked()
+            spyReportFailure.wait()
+            verify(spyReportFailure.count >= 1)
+
+            compare(importFromBackupPage.errorText, JamiStrings.errorCreateAccount)
+            compare(errorLabel.visible, true)
+
+            // Recreate with password
+            passwordFromBackupEdit.text = password
+            connectBtn.clicked()
+
+            // Wait until the account creation is finished
+            spyAccountIsReady.wait()
+            compare(spyAccountIsReady.count, 1)
+            spyAccountConfigFinalized.wait()
+            compare(spyAccountConfigFinalized.count, 1)
+
+            WizardViewStepModel.nextStep()
+
+            AccountAdapter.deleteCurrentAccount()
+
+            // Wait until the account removal is finished
+            spyAccountIsRemoved.wait()
+            compare(spyAccountIsRemoved.count, 1)
+        }
+    }
+}