Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
using Omika.Core.Compatibility;
|
||||
using Omika.Core.Domain.Entities.Clients;
|
||||
using Omika.Core.Domain.ValueObjects;
|
||||
using Omika.Data.Mapping.Common;
|
||||
using BatikModels = Omika.Data.HfSql.Models.Batik;
|
||||
using BatikMappers = Omika.Data.Mapping.Batik;
|
||||
|
||||
namespace Omika.Tests.Mapping;
|
||||
|
||||
/// <summary>
|
||||
/// Tests unitaires du mapper Batik → canonique des sites (table Lieu).
|
||||
/// Aucune base réelle, aucun HFSQL : uniquement des objets en mémoire.
|
||||
/// </summary>
|
||||
public class BatikSiteMapperTests
|
||||
{
|
||||
// ---- 1. Site Batik minimal -------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_Minimal_MapsWithoutExceptionAndKeepsNoFabricatedValue()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 1 };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, result.SourceVersion);
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.Code);
|
||||
Assert.Null(result.Value.Type);
|
||||
Assert.Null(result.Value.Adresse);
|
||||
Assert.Null(result.Value.InformationsComplementaires);
|
||||
Assert.False(result.Value.EstArchive);
|
||||
Assert.NotNull(result.Value.SourceReference);
|
||||
Assert.Equal(1, result.Value.SourceReference!.NumericId);
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, result.Value.SourceReference!.Source);
|
||||
Assert.Null(result.Value.SourceReference!.EntityGuid);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
// ---- 2. Site Batik complet -------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_Full_MapsAllCanonicalProperties()
|
||||
{
|
||||
var row = new BatikModels.LieuRow
|
||||
{
|
||||
LIPKID = 42,
|
||||
LICodeLieu = "S-001",
|
||||
LIIDType = 2,
|
||||
LINote = "Site principal",
|
||||
Archive = true,
|
||||
LIIDImport = "IMP-B-42"
|
||||
};
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[2] = new() { PAPKID = 2, PACode = "T", PAValeur = "1", PALibelle = "Immeuble" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row, referenceRows);
|
||||
|
||||
Site site = result.Value;
|
||||
Assert.Equal("S-001", site.Code);
|
||||
Assert.Equal("Immeuble", site.Type!.Label);
|
||||
Assert.Equal(2, site.Type!.LegacyId);
|
||||
Assert.Equal("T", site.Type!.Code);
|
||||
Assert.Equal("Site principal", site.InformationsComplementaires);
|
||||
Assert.True(site.EstArchive);
|
||||
|
||||
Assert.Equal(42, site.SourceReference!.NumericId);
|
||||
Assert.Equal("IMP-B-42", site.SourceReference!.ImportId);
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, site.SourceReference!.Source);
|
||||
}
|
||||
|
||||
// ---- 3. Conservation de l'identifiant source ----------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_SourceIdentifier_IsPreservedWithoutFabricatedGuid()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 1234, LIIDImport = "IMP-B" };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value.SourceReference);
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, result.Value.SourceReference!.Source);
|
||||
Assert.Equal(1234, result.Value.SourceReference!.NumericId);
|
||||
Assert.Equal("IMP-B", result.Value.SourceReference!.ImportId);
|
||||
Assert.Equal("1234", result.Value.SourceReference!.PublicIdentifier);
|
||||
Assert.Null(result.Value.SourceReference!.EntityGuid);
|
||||
Assert.Null(result.Value.SourceReference!.PhysicalGuid);
|
||||
}
|
||||
|
||||
// ---- 4. Type de site ----------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_Type_IsResolvedFromLegacyId()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 5, LIIDType = 7 };
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[7] = new() { PAPKID = 7, PACode = "T", PAValeur = "2", PALibelle = "Maison Indiv." }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row, referenceRows);
|
||||
|
||||
Assert.NotNull(result.Value.Type);
|
||||
Assert.Equal("Maison Indiv.", result.Value.Type!.Label);
|
||||
Assert.Equal(7, result.Value.Type!.LegacyId);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_UnresolvedType_KeepsLegacyIdAndWarns()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 6, LIIDType = 77 };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value.Type);
|
||||
Assert.Equal(77, result.Value.Type!.LegacyId);
|
||||
Assert.Equal(string.Empty, result.Value.Type!.Label);
|
||||
Assert.Contains(result.Warnings, w => w.Contains("LI_IDType", StringComparison.Ordinal)
|
||||
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_ZeroType_ProducesNoReference()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 8, LIIDType = 0 };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.Type);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
// ---- 5. Informations d'accès --------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_AccessInformation_CodeAccesBadgeInterphone_Mapped()
|
||||
{
|
||||
var row = new BatikModels.LieuRow
|
||||
{
|
||||
LIPKID = 9,
|
||||
LICodeAcces = "Code 1234",
|
||||
LIBadge = true,
|
||||
LIInterphone = true
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Equal("Code 1234", result.Value.CodeAcces);
|
||||
Assert.True(result.Value.Badge);
|
||||
Assert.True(result.Value.Interphone);
|
||||
Assert.DoesNotContain(result.IgnoredFields, f => f == "LI_CodeAcces");
|
||||
Assert.DoesNotContain(result.IgnoredFields, f => f == "LI_Badge");
|
||||
Assert.DoesNotContain(result.IgnoredFields, f => f == "LI_Interphone");
|
||||
}
|
||||
|
||||
// ---- 6. Blocage sans équivalent métier ----------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_Blocage_IsReportedAsIgnored()
|
||||
{
|
||||
var row = new BatikModels.LieuRow
|
||||
{
|
||||
LIPKID = 10,
|
||||
LIBlocage = true,
|
||||
LIRaisonBlocage = "Travaux en cours"
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Contains(result.IgnoredFields, f => f == "LI_Blocage");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "LI_RaisonBlocage");
|
||||
}
|
||||
|
||||
// ---- 7. Adresse déjà chargée en mémoire ---------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_Adresse_IsMappedFromInMemoryDictionary()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 11, LIIDAdresse = 20 };
|
||||
|
||||
var adresses = new Dictionary<long, BatikModels.AdresseRow>
|
||||
{
|
||||
[20] = new() { ADPKID = 20, ADEtiquette = "Siège", ADLigne1 = "1 place de la Comédie", ADVille = "Lyon", ADCodePostal = "69001" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row, adresses: adresses);
|
||||
|
||||
Assert.NotNull(result.Value.Adresse);
|
||||
Assert.Equal("1 place de la Comédie", result.Value.Adresse!.Line1);
|
||||
Assert.Equal("69001", result.Value.Adresse!.PostalCode);
|
||||
Assert.Equal("Lyon", result.Value.Adresse!.City);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_NoAdresse_WhenNothingProvided()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 12, LIIDAdresse = 0 };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.Adresse);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_UnresolvedAdresse_WarnsAndProducesNull()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 13, LIIDAdresse = 99 };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.Adresse);
|
||||
Assert.Contains(result.Warnings, w => w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
// ---- 8. Relations différées ----------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_Relations_AreLeftForLaterAssembly()
|
||||
{
|
||||
var row = new BatikModels.LieuRow { LIPKID = 14, LIIDClientPrincipal = 30 };
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.ClientId);
|
||||
Assert.Empty(result.Value.ContactIds);
|
||||
Assert.Contains(result.IgnoredFields, f => f == "LI_IDClientPrincipal");
|
||||
}
|
||||
|
||||
// ---- 9. Aucune exception sur les chaînes vides ---------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_EmptyOrNullStrings_NeverThrow()
|
||||
{
|
||||
var row = new BatikModels.LieuRow
|
||||
{
|
||||
LICodeLieu = "",
|
||||
LINote = " ",
|
||||
LIIDImport = "",
|
||||
LICodeAcces = " ",
|
||||
LIRaisonBlocage = "",
|
||||
LIRepertoireDocs = " "
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.Code);
|
||||
Assert.Null(result.Value.InformationsComplementaires);
|
||||
Assert.Null(result.Value.SourceReference!.ImportId);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_DefaultRow_NeverThrows()
|
||||
{
|
||||
var row = new BatikModels.LieuRow();
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.SourceReference!.NumericId);
|
||||
Assert.False(result.Value.EstArchive);
|
||||
}
|
||||
|
||||
// ---- 10. Champs ignorés et warnings attendus -----------------------------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_FieldsWithoutCanonicalEquivalent_AreReportedAsIgnored()
|
||||
{
|
||||
var row = new BatikModels.LieuRow
|
||||
{
|
||||
LIPKID = 15,
|
||||
LIRepertoireDocs = "docs/site",
|
||||
DateArchivage = new DateTime(2024, 6, 1),
|
||||
ModifDate = new DateTime(2024, 1, 1),
|
||||
CreationDate = new DateTime(2023, 1, 1)
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row);
|
||||
|
||||
Assert.Contains(result.IgnoredFields, f => f == "LI_RepertoireDocs");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "DateArchivage");
|
||||
Assert.Equal(new DateTime(2024, 1, 1), result.Value.DateModification);
|
||||
Assert.Contains(result.IgnoredFields, f => f == "CreationDate");
|
||||
}
|
||||
|
||||
// ---- 11. Absence de noms physiques HFSQL dans le domaine canonique -------------
|
||||
|
||||
[Fact]
|
||||
public void SiteBatik_CanonicalDomain_DoesNotExposeHfSqlNames()
|
||||
{
|
||||
var row = new BatikModels.LieuRow
|
||||
{
|
||||
LIPKID = 40,
|
||||
LICodeLieu = "S-040",
|
||||
LIIDType = 2,
|
||||
LINote = "note",
|
||||
Archive = false,
|
||||
LIIDImport = "IMP-40",
|
||||
LIIDAdresse = 20,
|
||||
LIIDClientPrincipal = 30,
|
||||
LICodeAcces = "code",
|
||||
LIBadge = true,
|
||||
LIInterphone = true,
|
||||
LIBlocage = true,
|
||||
LIRaisonBlocage = "raison",
|
||||
LIRepertoireDocs = "docs"
|
||||
};
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[2] = new() { PAPKID = 2, PACode = "T", PAValeur = "1", PALibelle = "Immeuble" }
|
||||
};
|
||||
|
||||
var adresses = new Dictionary<long, BatikModels.AdresseRow>
|
||||
{
|
||||
[20] = new() { ADPKID = 20, ADLigne1 = "1 rue de la Paix", ADVille = "Lyon", ADCodePostal = "69001" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Site> result = BatikMappers.BatikSiteMapper.Map(row, referenceRows, adresses);
|
||||
Site site = result.Value;
|
||||
|
||||
string[] forbidden =
|
||||
[
|
||||
"LI_", "AD_", "PA_", "PKID", "HfSql", "HFSQL", "GUID"
|
||||
];
|
||||
|
||||
AssertHasNoPhysicalNames(site, forbidden);
|
||||
|
||||
if (site.Adresse is not null)
|
||||
{
|
||||
AssertHasNoPhysicalNames(site.Adresse, forbidden);
|
||||
}
|
||||
|
||||
if (site.SourceReference is not null)
|
||||
{
|
||||
AssertHasNoPhysicalNames(site.SourceReference, forbidden);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Helper ---------------------------------------------------------------------
|
||||
|
||||
private static void AssertHasNoPhysicalNames(object value, string[] forbidden)
|
||||
{
|
||||
foreach (var property in value.GetType().GetProperties())
|
||||
{
|
||||
Assert.DoesNotContain(forbidden, f => property.Name.Contains(f, StringComparison.Ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user