using Microsoft.Extensions.DependencyInjection; using Omika.Core.Interfaces; using Omika.Data; using Omika.Data.Repositories; using Omika.Data.Repositories.Batik; using Omika.Data.Repositories.Omika; namespace Omika.Tests.Repositories; /// /// Tests du point d'accès unique aux paramètres applicatifs du client /// (table ParametreApplication). /// /// Vérifie qu'il n'existe PAS deux systèmes parallèles : les repositories /// documents consomment la même abstraction que le service de bootstrap au lieu /// de dupliquer leur propre lecture SQL. /// public class ApplicationParameterRepositoryTests { [Fact] public void AddOmikaData_RegistersBatikApplicationParameterRepositoryAsScoped() { var services = new ServiceCollection(); services.AddOmikaData(); var descriptor = services.Single(d => d.ServiceType == typeof(BatikApplicationParameterRepository)); Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); } [Fact] public void AddOmikaData_RegistersOmikaApplicationParameterRepositoryAsScoped() { var services = new ServiceCollection(); services.AddOmikaData(); var descriptor = services.Single(d => d.ServiceType == typeof(OmikaApplicationParameterRepository)); Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); } [Fact] public void AddOmikaData_IApplicationParameterRepositoryPointsToAdaptive() { var services = new ServiceCollection(); services.AddOmikaData(); var descriptor = services.Single(d => d.ServiceType == typeof(IApplicationParameterRepository)); Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); Assert.Equal(typeof(AdaptiveApplicationParameterRepository), descriptor.ImplementationType); } [Fact] public void AddOmikaData_PhysicalRepositoriesDoNotDependOnTheAbstraction() { // Les implémentations Batik/Omika ne doivent pas dépendre de // IApplicationParameterRepository : la sélection du schéma est le rôle de // l'adaptatif, il ne doit pas y avoir de résolution récursive. foreach (Type implementation in new[] { typeof(BatikApplicationParameterRepository), typeof(OmikaApplicationParameterRepository) }) { var constructor = Assert.Single(implementation.GetConstructors()); Assert.DoesNotContain( constructor.GetParameters(), p => p.ParameterType == typeof(IApplicationParameterRepository)); } } [Theory] [InlineData(typeof(BatikDocumentRepository))] [InlineData(typeof(OmikaDocumentRepository))] public void DocumentRepositories_UtilisentLePointDAccesUnique(Type repositoryType) { // Les repositories documents lisent les paramètres applicatifs // (racine et format des répertoires de documents) via l'abstraction // commune : plus aucune lecture ParametreApplication dupliquée. var constructor = Assert.Single(repositoryType.GetConstructors()); Assert.Contains( constructor.GetParameters(), p => p.ParameterType == typeof(IApplicationParameterRepository)); } [Fact] public void AucuneLectureParametreApplicationHorsDuRepositoryDedie() { // Garde-fou anti-architecture-parallèle : la seule requête SQL sur // ParametreApplication doit vivre dans le repository dédié. string racine = TrouverRacineSources(); string[] fichiers = Directory.GetFiles(Path.Combine(racine, "src"), "*.cs", SearchOption.AllDirectories); var fautifs = new List(); foreach (string fichier in fichiers) { if (fichier.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}") || fichier.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")) { continue; } string contenu = File.ReadAllText(fichier); if (!contenu.Contains("FROM ParametreApplication", StringComparison.Ordinal)) { continue; } string nom = Path.GetFileName(fichier); if (nom is not ("BatikApplicationParameterRepository.cs" or "OmikaApplicationParameterRepository.cs")) { fautifs.Add(nom); } } Assert.True( fautifs.Count == 0, $"Lecture directe de ParametreApplication hors du repository dédié : {string.Join(", ", fautifs)}"); } private static string TrouverRacineSources() { var repertoire = new DirectoryInfo(AppContext.BaseDirectory); while (repertoire is not null && !Directory.Exists(Path.Combine(repertoire.FullName, "src"))) { repertoire = repertoire.Parent; } Assert.NotNull(repertoire); return repertoire!.FullName; } }