Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,332 @@
|
||||
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 contacts (table Personne).
|
||||
/// Aucune base réelle, aucun HFSQL : uniquement des objets en mémoire.
|
||||
/// </summary>
|
||||
public class BatikContactMapperTests
|
||||
{
|
||||
// ---- 1. Contact Batik minimal -------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_Minimal_MapsWithoutExceptionAndKeepsNoFabricatedValue()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow { PEPKID = 1 };
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, result.SourceVersion);
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.Nom);
|
||||
Assert.Null(result.Value.Prenom);
|
||||
Assert.Null(result.Value.Civilite);
|
||||
Assert.Empty(result.Value.Roles);
|
||||
Assert.Null(result.Value.Coordonnees);
|
||||
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. Contact Batik complet -------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_Full_MapsAllCanonicalProperties()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PEPKID = 42,
|
||||
PEIDCivilite = 2,
|
||||
PENom = "Dupont",
|
||||
PEPrenom = "Jean",
|
||||
PEIDRole = 3,
|
||||
PETelFixe = "0472000000",
|
||||
PETelMobile = "0600000000",
|
||||
PEEmail = "jean.dupont@ville-lyon.fr",
|
||||
PEFax = "0472000001",
|
||||
PEIDClient = 10,
|
||||
PEIDAdressePrincipale = 20,
|
||||
PENote = "Contact principal",
|
||||
PEActif = true,
|
||||
PEUsageInterne = false,
|
||||
PEInfoSupp = "Disponible en journée",
|
||||
Archive = true,
|
||||
PEIDImport = "IMP-B-42"
|
||||
};
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[2] = new() { PAPKID = 2, PACode = "C", PAValeur = "1", PALibelle = "M." },
|
||||
[3] = new() { PAPKID = 3, PACode = "R", PAValeur = "1", PALibelle = "Contact principal" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row, referenceRows);
|
||||
|
||||
Contact contact = result.Value;
|
||||
Assert.Equal("M.", contact.Civilite!.Label);
|
||||
Assert.Equal(2, contact.Civilite!.LegacyId);
|
||||
Assert.Equal("Dupont", contact.Nom);
|
||||
Assert.Equal("Jean", contact.Prenom);
|
||||
Assert.Equal("Jean Dupont", contact.NomAffiche);
|
||||
|
||||
Assert.Single(contact.Roles);
|
||||
Assert.Equal("Contact principal", contact.Roles[0].Label);
|
||||
Assert.Equal(3, contact.Roles[0].LegacyId);
|
||||
|
||||
Assert.Equal("jean.dupont@ville-lyon.fr", contact.Coordonnees!.Email);
|
||||
Assert.Equal("0472000000", contact.Coordonnees!.Phone);
|
||||
Assert.Equal("0600000000", contact.Coordonnees!.Mobile);
|
||||
Assert.Equal("0472000001", contact.Coordonnees!.Fax);
|
||||
|
||||
Assert.True(contact.Actif);
|
||||
Assert.True(contact.EstArchive);
|
||||
Assert.Equal("Disponible en journée", contact.InformationsSupplementaires);
|
||||
|
||||
Assert.Equal(42, contact.SourceReference!.NumericId);
|
||||
Assert.Equal("IMP-B-42", contact.SourceReference!.ImportId);
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, contact.SourceReference!.Source);
|
||||
}
|
||||
|
||||
// ---- 3. Coordonnées nulles ----------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_EmptyCoordinates_ProducesNullCoordonnees()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PEPKID = 5,
|
||||
PENom = "Martin",
|
||||
PEEmail = " ",
|
||||
PETelFixe = "",
|
||||
PETelMobile = null,
|
||||
PEFax = "\t"
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.Coordonnees);
|
||||
Assert.Null(result.Value.Prenom);
|
||||
Assert.Equal("Martin", result.Value.Nom);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_PartialCoordinates_KeepsOnlyProvidedValues()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PEPKID = 6,
|
||||
PEEmail = "m@exemple.fr",
|
||||
PETelFixe = null,
|
||||
PETelMobile = "0600000000",
|
||||
PEFax = ""
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value.Coordonnees);
|
||||
Assert.Equal("m@exemple.fr", result.Value.Coordonnees!.Email);
|
||||
Assert.Null(result.Value.Coordonnees!.Phone);
|
||||
Assert.Equal("0600000000", result.Value.Coordonnees!.Mobile);
|
||||
Assert.Null(result.Value.Coordonnees!.Fax);
|
||||
}
|
||||
|
||||
// ---- 4. Conservation de l'identifiant source ----------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_SourceIdentifier_IsPreservedWithoutFabricatedGuid()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow { PEPKID = 1234, PEIDImport = "IMP-B" };
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.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);
|
||||
}
|
||||
|
||||
// ---- 5. Aucune exception sur les chaînes vides ----------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_EmptyOrNullStrings_NeverThrow()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PENom = "",
|
||||
PEPrenom = " ",
|
||||
PEEmail = "",
|
||||
PETelFixe = null,
|
||||
PETelMobile = " ",
|
||||
PEFax = "",
|
||||
PENote = "",
|
||||
PEInfoSupp = " ",
|
||||
PEIDImport = ""
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.Nom);
|
||||
Assert.Null(result.Value.Prenom);
|
||||
Assert.Null(result.Value.Coordonnees);
|
||||
Assert.Null(result.Value.InformationsSupplementaires);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_DefaultRow_NeverThrows()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow();
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.SourceReference!.NumericId);
|
||||
Assert.False(result.Value.Actif);
|
||||
Assert.False(result.Value.EstArchive);
|
||||
}
|
||||
|
||||
// ---- 6. Absence de noms physiques HFSQL dans le domaine canonique --------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_CanonicalDomain_DoesNotExposeHfSqlNames()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PEPKID = 40,
|
||||
PEIDCivilite = 2,
|
||||
PENom = "Dupont",
|
||||
PEPrenom = "Jean",
|
||||
PEIDRole = 3,
|
||||
PEEmail = "j@exemple.fr",
|
||||
PETelFixe = "01",
|
||||
PETelMobile = "06",
|
||||
PEFax = "02",
|
||||
PEIDClient = 10,
|
||||
PEIDAdressePrincipale = 20,
|
||||
PENote = "note",
|
||||
PEActif = true,
|
||||
PEUsageInterne = true,
|
||||
PEInfoSupp = "info",
|
||||
Archive = false,
|
||||
PEIDImport = "IMP-40"
|
||||
};
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[2] = new() { PAPKID = 2, PACode = "C", PAValeur = "1", PALibelle = "M." },
|
||||
[3] = new() { PAPKID = 3, PACode = "R", PAValeur = "1", PALibelle = "Rôle" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row, referenceRows);
|
||||
Contact contact = result.Value;
|
||||
|
||||
string[] forbidden =
|
||||
[
|
||||
"PE_", "CL_", "AD_", "PA_", "PKID", "HfSql", "HFSQL", "GUID"
|
||||
];
|
||||
|
||||
AssertHasNoPhysicalNames(contact, forbidden);
|
||||
|
||||
if (contact.Coordonnees is not null)
|
||||
{
|
||||
AssertHasNoPhysicalNames(contact.Coordonnees, forbidden);
|
||||
}
|
||||
|
||||
if (contact.SourceReference is not null)
|
||||
{
|
||||
AssertHasNoPhysicalNames(contact.SourceReference, forbidden);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Référentiels non résolus --------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_UnresolvedCiviliteAndRole_KeepsLegacyIdAndWarns()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PEPKID = 7,
|
||||
PEIDCivilite = 77,
|
||||
PEIDRole = 88
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value.Civilite);
|
||||
Assert.Equal(77, result.Value.Civilite!.LegacyId);
|
||||
Assert.Equal(string.Empty, result.Value.Civilite!.Label);
|
||||
|
||||
Assert.Single(result.Value.Roles);
|
||||
Assert.Equal(88, result.Value.Roles[0].LegacyId);
|
||||
|
||||
Assert.Contains(result.Warnings, w => w.Contains("PE_IDCivilite", StringComparison.Ordinal)
|
||||
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
|
||||
Assert.Contains(result.Warnings, w => w.Contains("PE_IDRole", StringComparison.Ordinal)
|
||||
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_ZeroCiviliteAndRole_ProducesNoReference()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow { PEPKID = 8, PEIDCivilite = 0, PEIDRole = 0 };
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.Civilite);
|
||||
Assert.Empty(result.Value.Roles);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
// ---- Rubriques sans équivalent --------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void ContactBatik_FieldsWithoutCanonicalEquivalent_AreReportedAsIgnored()
|
||||
{
|
||||
var row = new BatikModels.PersonneRow
|
||||
{
|
||||
PEPKID = 9,
|
||||
PEIDClient = 10,
|
||||
PEIDAdressePrincipale = 20,
|
||||
PENote = "note",
|
||||
PEUsageInterne = true,
|
||||
ModifDate = new DateTime(2024, 1, 1),
|
||||
CreationDate = new DateTime(2023, 1, 1),
|
||||
DateArchivage = new DateTime(2024, 6, 1)
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Contact> result = BatikMappers.BatikContactMapper.Map(row);
|
||||
|
||||
Assert.Contains(result.IgnoredFields, f => f == "PE_IDClient");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "PE_IDAdressePrincipale");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "PE_Note");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "PE_UsageInterne");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "ModifDate");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "CreationDate");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "DateArchivage");
|
||||
Assert.Null(result.Value.ClientId);
|
||||
Assert.Empty(result.Value.SiteIds);
|
||||
}
|
||||
|
||||
// ---- 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