using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using SQLInsight.Core.Data; using SQLInsight.Core.Instances; using SQLInsight.Repository; namespace SQLInsight.IntegrationTests; /// The configuration page and its change log, from stored snapshots. [Collection(SqlServerTestGroup.Name)] [Trait("Category", "Integration")] public class ConfigurationPageTests(SqlServerFixture sql) : IAsyncLifetime { private readonly string _database = "SQLInsightConfig_" + Guid.NewGuid().ToString("N")[..8]; private InsightRepository _repository = null!; private int _instanceId; public async Task InitializeAsync() { await sql.ExecuteAsSaAsync($"CREATE DATABASE [{_database}];"); _repository = new InsightRepository(sql.DatabaseConnectionString(_database)); await _repository.MigrateAsync(); var info = new InstanceInfo { ServerName = "AX01", Version = SqlServerVersion.Parse("16.0.4135.4"), ProductLevel = "RTM", Edition = "Standard Edition", EngineEdition = EngineEdition.Standard, }; _instanceId = await _repository.UpsertInstanceAsync(@"AX01\AX30", info, "SqlClient", false, DateTimeOffset.UtcNow); } public async Task DisposeAsync() => await sql.ExecuteAsSaAsync($"ALTER DATABASE [{_database}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [{_database}];"); [Fact] public async Task Page_shows_the_setup_non_default_options_and_the_change_log() { var now = DateTimeOffset.UtcNow; await _repository.SaveCollectedAsync(_instanceId, "configuration", new ConfigurationSnapshot { CapturedAt = now, Options = [new ConfigurationOption("max degree of parallelism", 1, 1), new ConfigurationOption("cost threshold for parallelism", 5, 5)], }); await _repository.SaveCollectedAsync(_instanceId, "instance-config", new InstanceConfigurationSnapshot { CapturedAt = now, Collation = "Danish_Norwegian_CI_AS", ServicesAvailable = true, Services = [new ServiceInfo("SQL Server (AX30)", @"KUNDE\svc-ax30", "Automatic", "Running", true)], InstantFileInitialization = true, MemoryModel = "LOCK_PAGES", TempdbFiles = [new TempdbFile("tempdev", "ROWS", 1024, "64 MB", "ubegrænset")], Changes = [new ConfigurationChange(ConfigurationFingerprint.SpConfigure, "max degree of parallelism", "0", "1", now)], }); var changes = await _repository.GetConfigurationChangesAsync(_instanceId, now.AddDays(-1), now.AddMinutes(1)); await using var factory = new WebApplicationFactory().WithWebHostBuilder(b => { b.UseEnvironment("Development"); b.UseSetting("SQLInsight:Repository:ConnectionString", sql.DatabaseConnectionString(_database)); b.UseSetting("SQLInsight:Web:Authentication", "None"); }); var name = Uri.EscapeDataString(@"AX01\AX30"); var html = await factory.CreateClient().GetStringAsync($"/instanser/{name}/konfiguration"); var instancePage = await factory.CreateClient().GetStringAsync($"/instanser/{name}"); var change = Assert.Single(changes); Assert.Equal(("0", "1"), (change.OldValue, change.NewValue)); Assert.Contains("Danish_Norwegian_CI_AS", html, StringComparison.Ordinal); Assert.Contains(@"KUNDE\svc-ax30", html, StringComparison.Ordinal); Assert.Contains("Lock Pages in Memory", html, StringComparison.Ordinal); Assert.Contains("Ændringslog", html, StringComparison.Ordinal); Assert.Contains("max degree of parallelism", html, StringComparison.Ordinal); // non-default (1 vs 0) and in the log Assert.DoesNotContain("cost threshold for parallelism", html, StringComparison.Ordinal); // default: not listed Assert.Contains($"/instanser/{name}/konfiguration", instancePage, StringComparison.Ordinal); } }