using ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment; using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems; using ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Repositories; namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests; /// /// Artifact-deploy queries on DeploymentManagerRepository. Retention purge for /// rows (review 2026-10-21 /// 08/G2): one row is written per Deploy Artifacts run and nothing reads them back, so they /// must share the terminal deployment-record retention window. /// public sealed class DeploymentManagerArtifactRepositoryTests : IDisposable { private readonly ScadaBridgeDbContext _context = SqliteTestHelper.CreateInMemoryContext(); private readonly DeploymentManagerRepository _repository; /// Initializes the repository over a fresh in-memory SQLite context. public DeploymentManagerArtifactRepositoryTests() { _repository = new DeploymentManagerRepository(_context); } /// Releases the in-memory database. public void Dispose() => _context.Dispose(); private async Task SeedAsync(DateTimeOffset deployedAt) { await _repository.AddSystemArtifactDeploymentAsync( new SystemArtifactDeploymentRecord("Artifacts", "admin") { DeployedAt = deployedAt }); await _repository.SaveChangesAsync(); } /// Only rows older than the cutoff are deleted, in bounded batches. /// A task that represents the asynchronous operation. [Fact] public async Task Purge_DeletesOnlyRowsOlderThanCutoff_InBoundedBatches() { var now = DateTimeOffset.UtcNow; await SeedAsync(now.AddDays(-400)); await SeedAsync(now.AddDays(-380)); await SeedAsync(now.AddDays(-370)); await SeedAsync(now.AddDays(-1)); var cutoff = now.AddDays(-365); Assert.Equal(2, await _repository.PurgeSystemArtifactDeploymentRecordsAsync(cutoff, batchSize: 2)); Assert.Equal(1, await _repository.PurgeSystemArtifactDeploymentRecordsAsync(cutoff, batchSize: 2)); Assert.Equal(0, await _repository.PurgeSystemArtifactDeploymentRecordsAsync(cutoff, batchSize: 2)); var remaining = await _repository.GetAllSystemArtifactDeploymentsAsync(); var survivor = Assert.Single(remaining); Assert.True(survivor.DeployedAt > cutoff); } /// /// review 2026-10-21 04/P7: the artifact-deploy method read returns every system's methods /// in one untracked query. /// /// A task that represents the asynchronous operation. [Fact] public async Task GetAllExternalSystemMethods_ReturnsEverySystemsMethods_Untracked() { var a = new ExternalSystemDefinition("A", "https://a.test", "ApiKey"); var b = new ExternalSystemDefinition("B", "https://b.test", "ApiKey"); _context.AddRange(a, b); await _context.SaveChangesAsync(); _context.AddRange( new ExternalSystemMethod("A1", "GET", "/a1") { ExternalSystemDefinitionId = a.Id }, new ExternalSystemMethod("B1", "GET", "/b1") { ExternalSystemDefinitionId = b.Id }, new ExternalSystemMethod("B2", "POST", "/b2") { ExternalSystemDefinitionId = b.Id }); await _context.SaveChangesAsync(); _context.ChangeTracker.Clear(); var methods = await _repository.GetAllExternalSystemMethodsAsync(); Assert.Equal(3, methods.Count); Assert.Equal(2, methods.Count(m => m.ExternalSystemDefinitionId == b.Id)); Assert.Empty(_context.ChangeTracker.Entries()); } }