using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using RpgRoller.Hosting; using RpgRoller.Data; namespace RpgRoller.Tests; public sealed class HostingCoverageTests { [Fact] public void AddRpgRollerCore_WithInMemoryConnectionString_RegistersCoreServices() { var services = new ServiceCollection(); var configuration = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { ["ConnectionStrings:RpgRoller"] = "Data Source=:memory:" }) .Build(); var environment = new TestWebHostEnvironment { ContentRootPath = Path.GetTempPath() }; services.AddRpgRollerCore(configuration, environment); Assert.Contains(services, d => d.ServiceType == typeof(RpgRoller.Services.IGameService)); Assert.Contains(services, d => d.ServiceType == typeof(RpgRoller.Services.IDiceRoller)); } [Fact] public void SqliteSchemaUpgrader_MigratesLegacySchema() { var dbPath = Path.Combine(Path.GetTempPath(), $"rpgroller-legacy-upgrade-{Guid.NewGuid():N}.db"); var connectionString = $"Data Source={dbPath}"; using (var connection = new SqliteConnection(connectionString)) { connection.Open(); using var command = connection.CreateCommand(); command.CommandText = """ CREATE TABLE "Users" ( "Id" TEXT NOT NULL CONSTRAINT "PK_Users" PRIMARY KEY, "Username" TEXT NOT NULL, "UsernameNormalized" TEXT NOT NULL, "PasswordHash" TEXT NOT NULL, "DisplayName" TEXT NOT NULL, "ActiveCharacterId" TEXT NULL ); CREATE TABLE "Sessions" ( "Token" TEXT NOT NULL CONSTRAINT "PK_Sessions" PRIMARY KEY, "UserId" TEXT NOT NULL, "CreatedAtUtc" TEXT NOT NULL ); CREATE TABLE "Campaigns" ( "Id" TEXT NOT NULL CONSTRAINT "PK_Campaigns" PRIMARY KEY, "GmUserId" TEXT NOT NULL, "Name" TEXT NOT NULL, "Ruleset" TEXT NOT NULL, "Version" INTEGER NOT NULL ); CREATE TABLE "Characters" ( "Id" TEXT NOT NULL CONSTRAINT "PK_Characters" PRIMARY KEY, "OwnerUserId" TEXT NOT NULL, "CampaignId" TEXT NOT NULL, "Name" TEXT NOT NULL ); CREATE TABLE "Skills" ( "Id" TEXT NOT NULL CONSTRAINT "PK_Skills" PRIMARY KEY, "CharacterId" TEXT NOT NULL, "Name" TEXT NOT NULL, "DiceRollDefinition" TEXT NOT NULL ); CREATE TABLE "RollLogEntries" ( "Id" TEXT NOT NULL CONSTRAINT "PK_RollLogEntries" PRIMARY KEY, "CampaignId" TEXT NOT NULL, "CharacterId" TEXT NOT NULL, "SkillId" TEXT NOT NULL, "RollerUserId" TEXT NOT NULL, "Visibility" TEXT NOT NULL, "Result" INTEGER NOT NULL, "Breakdown" TEXT NOT NULL, "TimestampUtc" TEXT NOT NULL ); """; _ = command.ExecuteNonQuery(); } var options = new DbContextOptionsBuilder() .UseSqlite(connectionString) .Options; using (var db = new RpgRollerDbContext(options)) { SqliteSchemaUpgrader.ApplyPendingChanges(db); } using var verifyConnection = new SqliteConnection(connectionString); verifyConnection.Open(); using var tableInfoCommand = verifyConnection.CreateCommand(); tableInfoCommand.CommandText = "PRAGMA table_info('Skills');"; using var tableInfoReader = tableInfoCommand.ExecuteReader(); var columns = new HashSet(StringComparer.OrdinalIgnoreCase); while (tableInfoReader.Read()) { columns.Add(tableInfoReader.GetString(1)); } Assert.Contains("WildDice", columns); Assert.Contains("AllowFumble", columns); using var rollTableInfoCommand = verifyConnection.CreateCommand(); rollTableInfoCommand.CommandText = "PRAGMA table_info('RollLogEntries');"; using var rollTableInfoReader = rollTableInfoCommand.ExecuteReader(); var rollColumns = new HashSet(StringComparer.OrdinalIgnoreCase); while (rollTableInfoReader.Read()) { rollColumns.Add(rollTableInfoReader.GetString(1)); } Assert.Contains("Dice", rollColumns); using var historyCommand = verifyConnection.CreateCommand(); historyCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260226084000_InitialSchema';"; var historyCount = Convert.ToInt32(historyCommand.ExecuteScalar()); Assert.Equal(1, historyCount); using var modelSyncHistoryCommand = verifyConnection.CreateCommand(); modelSyncHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260226090000_ModelSync';"; var modelSyncHistoryCount = Convert.ToInt32(modelSyncHistoryCommand.ExecuteScalar()); Assert.Equal(1, modelSyncHistoryCount); using var rollDiceHistoryCommand = verifyConnection.CreateCommand(); rollDiceHistoryCommand.CommandText = "SELECT COUNT(*) FROM \"__EFMigrationsHistory\" WHERE \"MigrationId\" = '20260226100000_AddRollLogDice';"; var rollDiceHistoryCount = Convert.ToInt32(rollDiceHistoryCommand.ExecuteScalar()); Assert.Equal(1, rollDiceHistoryCount); } }