using System.Reflection; using Omika.Core.Contracts.Common; namespace Omika.Tests.Architecture; /// /// Aucun contrat public ne doit contenir de nom de rubrique HFSQL, de préfixe /// physique (CL_, IN_, PL_, RDV_, DC_…) ni de nom de table de base. /// public class PublicContractsMustNotContainHfSqlNamesTests { private static readonly string[] ForbiddenFragments = [ "CL_", "IN_", "PL_", "RDV_", "AD_Ligne", "DC_", "PKID", "IDType", "CleType", "IDStatut", "CleStatut", "RDP_GUID", "PL_PKID", "RDP_", "HfSql", "HFSQL" ]; private static readonly string[] ForbiddenTableNames = [ "Planning_RDV", "RDV_Planning", "RDV_Personne", "RDV_Collaborateur", "RDV_Contact", "AccesEtDroit", "CategorieAcces", "RubriquesDocument" ]; /// /// Noms interdits en tant que nom de propriété complet (et non sous-chaîne, /// pour ne pas rejeter des mots métier français comme « Comptable »). /// private static readonly string[] ForbiddenExactPropertyNames = [ "Table", "Row" ]; private static IEnumerable GetContractTypes() => typeof(PagedResult<>).Assembly .GetTypes() .Where(t => t.IsPublic) .Where(t => t.Namespace?.StartsWith("Omika.Core.Contracts", StringComparison.Ordinal) == true) .Where(t => !t.IsGenericTypeDefinition || t.Name.Contains("PagedResult", StringComparison.Ordinal)); private static IEnumerable GetPublicPropertyNames(Type type) => type .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Select(p => p.Name); [Fact] public void NoContractType_HasPhysicalTableOrPrefixInItsName() { foreach (Type type in GetContractTypes()) { foreach (string forbidden in ForbiddenTableNames.Concat(ForbiddenFragments)) { Assert.False( type.Name.Contains(forbidden, StringComparison.OrdinalIgnoreCase), $"Le type de contrat « {type.FullName} » contient la référence physique « {forbidden} »."); } } } [Fact] public void NoContractProperty_HasPhysicalPrefixOrRubricName() { foreach (Type type in GetContractTypes()) { foreach (string propertyName in GetPublicPropertyNames(type)) { // Vérification des fragments de rubrique / noms de table. foreach (string forbidden in ForbiddenTableNames.Concat(ForbiddenFragments)) { Assert.False( propertyName.Contains(forbidden, StringComparison.OrdinalIgnoreCase), $"Le contrat « {type.FullName}.{propertyName} » contient la référence physique « {forbidden} »."); } // Vérification des noms interdits uniquement en nom complet, // afin d'éviter les faux positifs (« Comptable » contient « Table »). Assert.DoesNotContain( ForbiddenExactPropertyNames, name => string.Equals(name, propertyName, StringComparison.OrdinalIgnoreCase)); } } } [Fact] public void Contracts_DoNotExposeOmikaDataTypes() { foreach (Type type in GetContractTypes()) { foreach (PropertyInfo property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { string propertyTypeName = property.PropertyType.Name; Assert.False( propertyTypeName.Contains("Row", StringComparison.OrdinalIgnoreCase) && propertyTypeName.EndsWith("Row", StringComparison.OrdinalIgnoreCase), $"Le contrat « {type.FullName}.{property.Name} » expose un type physique « {propertyTypeName} »."); } } } }