356 lines
12 KiB
C#
356 lines
12 KiB
C#
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));
|
|
}
|
|
}
|
|
}
|