using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using SQLInsight.Agent.Hub; using SQLInsight.Hub.Data; using SQLInsight.Repository; namespace SQLInsight.IntegrationTests; /// A support case from SQLInsight Web, through the agent to the hub and its status back again. [Collection(SqlServerTestGroup.Name)] [Trait("Category", "Integration")] public class HubSupportEndToEndTests(SqlServerFixture sql, HubFixture hub) : IClassFixture, IAsyncLifetime { private readonly string _database = "SQLInsightSupE2E_" + Guid.NewGuid().ToString("N")[..8]; private InsightRepository _repository = null!; public async Task InitializeAsync() { await sql.ExecuteAsSaAsync($"CREATE DATABASE [{_database}];"); _repository = new InsightRepository(sql.DatabaseConnectionString(_database)); await _repository.MigrateAsync(); } public Task DisposeAsync() => sql.ExecuteAsSaAsync($"ALTER DATABASE [{_database}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [{_database}];"); private sealed class TestServerClients(Func create) : IHttpClientFactory { public HttpClient CreateClient(string name) => create(); } private HubSyncService Sync(string license) { var options = Options.Create(new HubOptions { Enabled = true, Url = new Uri("http://localhost/"), License = license }); options.Value.TrustedKeys[HubFixture.KeyId] = hub.PublicKey; return new HubSyncService(options, _repository, new TestServerClients(() => hub.Factory.CreateClient()), TimeProvider.System, NullLogger.Instance); } [Fact] public async Task Case_filed_in_web_gets_a_number_and_its_closing_comes_back() { var customer = $"Support E2E {Guid.NewGuid():N}"[..28]; var license = hub.License(customer); await _repository.AddSupportRequestAsync(new NewSupportRequest(Guid.NewGuid(), "Langsom backup", "Siden mandag", "Anna", "anna@kunde.dk", null, "KUNDE\\anna"), DateTimeOffset.UtcNow); await Sync(license).RunOnceAsync(CancellationToken.None); var filed = Assert.Single(await _repository.GetSupportCasesAsync()); Assert.Equal(("SUP-000001", SupportCaseStatus.Open), (filed.Reference, filed.Status)); await using (var scope = hub.Factory.Services.CreateAsyncScope()) { var db = scope.ServiceProvider.GetRequiredService(); var stored = await db.SupportCases.SingleAsync(c => c.Customer!.Name == customer); stored.IsOpen = false; stored.ClosedAt = DateTime.UtcNow; await db.SaveChangesAsync(); } await Sync(license).RunOnceAsync(CancellationToken.None); var closed = Assert.Single(await _repository.GetSupportCasesAsync()); Assert.Equal(SupportCaseStatus.Closed, closed.Status); Assert.NotNull(closed.ClosedAt); } [Fact] public async Task Request_the_license_does_not_cover_is_given_up() { var customer = $"Community {Guid.NewGuid():N}"[..24]; await _repository.AddSupportRequestAsync(new NewSupportRequest(Guid.NewGuid(), "Hjælp", null, "Anna", "anna@kunde.dk", null, null), DateTimeOffset.UtcNow); var sync = Sync(hub.License(customer)); await sync.SyncSupportCasesAsync(hub.Factory.CreateClient(), new HubOptions { Url = new Uri("http://localhost/"), License = hub.License(customer, SQLInsight.Licensing.LicensePlan.Community) }, CancellationToken.None); var failed = Assert.Single(await _repository.GetSupportCasesAsync()); Assert.Equal(SupportCaseStatus.Failed, failed.Status); Assert.Contains("403", failed.LastError, StringComparison.Ordinal); } }