#include "ScopedTestAccount.h" #include #include #include #include #include #include #include #include namespace Testing = Status::Testing; namespace Onboarding = Status::Onboarding; namespace Accounts = Status::StatusGo::Accounts; namespace fs = std::filesystem; namespace Status::Testing { ScopedTestAccount::ScopedTestAccount(const std::string& tempTestSubfolderName, const QString& accountName, const QString& accountPassword) : m_fusedTestFolder{std::make_unique(tempTestSubfolderName)} , m_accountName(accountName) , m_accountPassword(accountPassword) { int argc = 1; std::string appName{"test"}; char* args[] = {appName.data()}; m_app = std::make_unique(argc, reinterpret_cast(args)); m_dataDirPath = m_fusedTestFolder->tempFolder() / Constants::statusGoDataDirName; fs::create_directory(m_dataDirPath); // Setup accounts auto accountsService = std::make_shared(); auto result = accountsService->init(m_dataDirPath); if(!result) { throw std::runtime_error("ScopedTestAccount - Failed to create temporary test account"); } // TODO refactor and merge account creation events with login into Onboarding controller // // Create Login early to register and not miss onLoggedIn event signal from setupAccountAndLogin // // Beware, smartpointer is a requirement m_onboarding = Helpers::makeSharedQObject(accountsService); if(m_onboarding->getOpenedAccounts().size() != 0) { throw std::runtime_error("ScopedTestAccount - already have opened account"); } int accountLoggedInCount = 0; QObject::connect(m_onboarding.get(), &Onboarding::OnboardingController::accountLoggedIn, m_app.get(), [&accountLoggedInCount]() { accountLoggedInCount++; }); bool accountLoggedInError = false; QObject::connect(m_onboarding.get(), &Onboarding::OnboardingController::accountLoginError, m_app.get(), [&accountLoggedInError]() { accountLoggedInError = true; }); // Create Accounts auto genAccounts = accountsService->generatedAccounts(); if(genAccounts.size() == 0) { throw std::runtime_error("ScopedTestAccount - missing generated accounts"); } if(accountsService->isFirstTimeAccountLogin()) { throw std::runtime_error("ScopedTestAccount - Service::isFirstTimeAccountLogin returned true"); } if(!accountsService->setupAccountAndLogin(genAccounts[0].id, m_accountPassword, m_accountName)) { throw std::runtime_error("ScopedTestAccount - Service::setupAccountAndLogin failed"); } if(!accountsService->isFirstTimeAccountLogin()) { throw std::runtime_error("ScopedTestAccount - Service::isFirstTimeAccountLogin returned false"); } if(!accountsService->getLoggedInAccount().isValid()) { throw std::runtime_error("ScopedTestAccount - newly created account is not valid"); } if(accountsService->getLoggedInAccount().name != accountName) { throw std::runtime_error("ScopedTestAccount - newly created account has a wrong name"); } processMessages(2000, [accountLoggedInCount]() { return accountLoggedInCount == 0; }); if(accountLoggedInError) { throw std::runtime_error("ScopedTestAccount - account loggedin error"); } if(accountLoggedInCount != 1) { throw std::runtime_error("ScopedTestAccount - missing confirmation of account creation"); } } ScopedTestAccount::~ScopedTestAccount() { const auto rootAccount = m_onboarding->accountsService()->getLoggedInAccount(); m_onboarding->accountsService()->deleteMultiAccount(rootAccount); } void ScopedTestAccount::processMessages(size_t maxWaitTimeMillis, std::function shouldWaitUntilTimeout) { using namespace std::chrono_literals; std::chrono::milliseconds maxWaitTime{maxWaitTimeMillis}; auto iterationSleepTime = 2ms; auto remainingIterations = maxWaitTime / iterationSleepTime; while(remainingIterations-- > 0 && shouldWaitUntilTimeout()) { QCoreApplication::sendPostedEvents(); std::this_thread::sleep_for(iterationSleepTime); } // Provide chance to exit slot processing after we set the condition that might trigger shouldWaitUntilTimeout to false std::this_thread::sleep_for(iterationSleepTime); } void ScopedTestAccount::logOut() { if(Status::StatusGo::Accounts::logout().containsError()) { throw std::runtime_error("ScopedTestAccount - failed logging out"); } } Accounts::ChatOrWalletAccount ScopedTestAccount::firstChatAccount() { auto accounts = Accounts::getAccounts(); auto chatIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isChat; }); if(chatIt == accounts.end()) { throw std::runtime_error("ScopedTestAccount::chatAccount: account not found"); } return *chatIt; } Accounts::ChatOrWalletAccount ScopedTestAccount::firstWalletAccount() { auto accounts = Accounts::getAccounts(); auto walletIt = std::find_if(accounts.begin(), accounts.end(), [](const auto& a) { return a.isWallet; }); if(walletIt == accounts.end()) { throw std::runtime_error("ScopedTestAccount::firstWalletAccount: account not found"); } return *walletIt; } const Onboarding::MultiAccount& ScopedTestAccount::loggedInAccount() const { return m_onboarding->accountsService()->getLoggedInAccount(); } Onboarding::OnboardingController* ScopedTestAccount::onboardingController() const { return m_onboarding.get(); } const std::filesystem::path& ScopedTestAccount::fusedTestFolder() const { return m_fusedTestFolder->tempFolder(); } const std::filesystem::path& ScopedTestAccount::testDataDir() const { return m_dataDirPath; } } // namespace Status::Testing