Internal
Public Access
Wire up CTest and add unit test coverage for ProfileRepository
Adds a Qt6::Test-based unit test target (tests/test_profile_repository.cpp, 21 cases), gated behind an ORBITHUB_BUILD_TESTS option that no-ops gracefully if Qt6::Test isn't available, so it can't break app-only builds. Covers profile CRUD, validation rules, search/sort, tag normalization, and folder handling, each against an isolated temporary SQLite file (new ProfileRepository(databasePathOverride) constructor overload added for exactly this). Caught and fixed a real bug along the way: normalizedTags()'s result was bound directly without the nonNullTrimmed() null-guard every other field already uses, so creating a profile with no tags at all hit the `tags NOT NULL` constraint and silently failed -- including via the Import Profiles feature for any export where a profile has no tags key. Partial progress on #1 (RdpSessionBackend/SshSessionBackend state-machine coverage still open -- much larger lift, needs a testability pass on those backends first). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,11 @@
|
||||
#include <QVariant>
|
||||
#include <QStringList>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace {
|
||||
std::atomic<int> g_testConnectionCounter{0};
|
||||
|
||||
QString buildDatabasePath()
|
||||
{
|
||||
QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
@@ -176,7 +180,7 @@ void bindProfileFields(QSqlQuery& query, const Profile& profile)
|
||||
: QStringLiteral("Negotiate"));
|
||||
query.addBindValue(isRdp ? normalizedRdpPerformanceProfile(profile.rdpPerformanceProfile)
|
||||
: QStringLiteral("Balanced"));
|
||||
query.addBindValue(normalizedTags(profile.tags));
|
||||
query.addBindValue(nonNullTrimmed(normalizedTags(profile.tags)));
|
||||
}
|
||||
|
||||
Profile profileFromQuery(const QSqlQuery& query)
|
||||
@@ -259,6 +263,16 @@ ProfileRepository::ProfileRepository() : m_connectionName(QStringLiteral("orbith
|
||||
}
|
||||
}
|
||||
|
||||
ProfileRepository::ProfileRepository(const QString& databasePathOverride)
|
||||
: m_connectionName(QStringLiteral("orbithub_test_%1")
|
||||
.arg(g_testConnectionCounter.fetch_add(1))),
|
||||
m_databasePathOverride(databasePathOverride)
|
||||
{
|
||||
if (!initializeDatabase()) {
|
||||
QSqlDatabase::removeDatabase(m_connectionName);
|
||||
}
|
||||
}
|
||||
|
||||
ProfileRepository::~ProfileRepository()
|
||||
{
|
||||
if (QSqlDatabase::contains(m_connectionName)) {
|
||||
@@ -485,7 +499,8 @@ bool ProfileRepository::deleteProfile(qint64 id) const
|
||||
bool ProfileRepository::initializeDatabase()
|
||||
{
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName);
|
||||
database.setDatabaseName(buildDatabasePath());
|
||||
database.setDatabaseName(
|
||||
m_databasePathOverride.isEmpty() ? buildDatabasePath() : m_databasePathOverride);
|
||||
|
||||
if (!database.open()) {
|
||||
m_initError = database.lastError().text();
|
||||
|
||||
@@ -35,6 +35,9 @@ class ProfileRepository
|
||||
{
|
||||
public:
|
||||
ProfileRepository();
|
||||
// databasePathOverride lets tests point the repository at an isolated,
|
||||
// disposable SQLite file instead of the real app-data location.
|
||||
explicit ProfileRepository(const QString& databasePathOverride);
|
||||
~ProfileRepository();
|
||||
|
||||
QString initError() const;
|
||||
@@ -51,6 +54,7 @@ public:
|
||||
|
||||
private:
|
||||
QString m_connectionName;
|
||||
QString m_databasePathOverride;
|
||||
QString m_initError;
|
||||
mutable QString m_lastError;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user