Files
Omika/tests/Omika.Tests/Mapping/BatikCollaborateurMapperTests.cs
T
2026-10-23 18:46:50 +02:00

307 lines
11 KiB
C#

using Omika.Core.Compatibility;
using Omika.Core.Domain.Entities.Organisation;
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 collaborateurs (table Collaborateur).
/// Aucune base réelle, aucun HFSQL : uniquement des objets en mémoire.
/// </summary>
public class BatikCollaborateurMapperTests
{
// ---- 1. Collaborateur Batik minimal -------------------------------------------
[Fact]
public void CollaborateurBatik_Minimal_MapsWithoutExceptionAndKeepsNoFabricatedValue()
{
var row = new BatikModels.CollaborateurRow { COPKID = 1 };
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.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.Null(result.Value.Statut);
Assert.Null(result.Value.Coordonnees);
Assert.False(result.Value.Actif);
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. Collaborateur Batik complet -------------------------------------------
[Fact]
public void CollaborateurBatik_Full_MapsAllCanonicalProperties()
{
var row = new BatikModels.CollaborateurRow
{
COPKID = 42,
COIDCivilite = 2,
CONom = "Dupont",
COPrenom = "Jean",
COTrigramme = "JD",
COTelFixe = "0472000000",
COTelMobile = "0600000000",
COEmail = "jean.dupont@ville-lyon.fr",
COIDStatut = 3,
COActif = true,
COIDImport = "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 = "S", PAValeur = "1", PALibelle = "Actif" }
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row, referenceRows);
Collaborateur collaborateur = result.Value;
Assert.Equal("M.", collaborateur.Civilite!.Label);
Assert.Equal(2, collaborateur.Civilite!.LegacyId);
Assert.Equal("Actif", collaborateur.Statut!.Label);
Assert.Equal(3, collaborateur.Statut!.LegacyId);
Assert.Equal("Dupont", collaborateur.Nom);
Assert.Equal("Jean", collaborateur.Prenom);
Assert.Equal("JD", collaborateur.Code);
Assert.Equal("jean.dupont@ville-lyon.fr", collaborateur.Coordonnees!.Email);
Assert.Equal("0472000000", collaborateur.Coordonnees!.Phone);
Assert.Equal("0600000000", collaborateur.Coordonnees!.Mobile);
Assert.True(collaborateur.Actif);
Assert.Equal(42, collaborateur.SourceReference!.NumericId);
Assert.Equal(DatabaseSchemaVersion.Batik, collaborateur.SourceReference!.Source);
}
// ---- 3. Coordonnées nulles ----------------------------------------------------
[Fact]
public void CollaborateurBatik_EmptyCoordinates_ProducesNullCoordonnees()
{
var row = new BatikModels.CollaborateurRow
{
COPKID = 5,
CONom = "Martin",
COEmail = " ",
COTelFixe = "",
COTelMobile = null
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row);
Assert.Null(result.Value.Coordonnees);
Assert.Null(result.Value.Prenom);
Assert.Equal("Martin", result.Value.Nom);
}
[Fact]
public void CollaborateurBatik_PartialCoordinates_KeepsOnlyProvidedValues()
{
var row = new BatikModels.CollaborateurRow
{
COPKID = 6,
COEmail = "m@exemple.fr",
COTelFixe = null,
COTelMobile = "0600000000"
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.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);
}
// ---- 4. Conservation de l'identifiant source ----------------------------------
[Fact]
public void CollaborateurBatik_SourceIdentifier_IsPreservedWithoutFabricatedGuid()
{
var row = new BatikModels.CollaborateurRow { COPKID = 1234, COIDImport = "IMP-B" };
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row);
Assert.NotNull(result.Value.SourceReference);
Assert.Equal(DatabaseSchemaVersion.Batik, result.Value.SourceReference!.Source);
Assert.Equal(1234, result.Value.SourceReference!.NumericId);
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 CollaborateurBatik_EmptyOrNullStrings_NeverThrow()
{
var row = new BatikModels.CollaborateurRow
{
CONom = "",
COPrenom = " ",
COEmail = "",
COTelFixe = null,
COTelMobile = " ",
COTrigramme = "",
COIDImport = ""
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row);
Assert.NotNull(result.Value);
Assert.Null(result.Value.Nom);
Assert.Null(result.Value.Prenom);
Assert.Null(result.Value.Coordonnees);
Assert.Empty(result.Warnings);
}
[Fact]
public void CollaborateurBatik_DefaultRow_NeverThrows()
{
var row = new BatikModels.CollaborateurRow();
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.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 CollaborateurBatik_CanonicalDomain_DoesNotExposeHfSqlNames()
{
var row = new BatikModels.CollaborateurRow
{
COPKID = 40,
COIDCivilite = 2,
CONom = "Dupont",
COPrenom = "Jean",
COTelFixe = "01",
COTelMobile = "06",
COEmail = "j@exemple.fr",
COActif = true,
COIDImport = "IMP-40"
};
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
{
[2] = new() { PAPKID = 2, PACode = "C", PAValeur = "1", PALibelle = "M." }
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row, referenceRows);
Collaborateur collaborateur = result.Value;
string[] forbidden =
[
"CO_", "CL_", "PA_", "PKID", "HfSql", "HFSQL", "GUID"
];
AssertHasNoPhysicalNames(collaborateur, forbidden);
if (collaborateur.Coordonnees is not null)
{
AssertHasNoPhysicalNames(collaborateur.Coordonnees, forbidden);
}
if (collaborateur.SourceReference is not null)
{
AssertHasNoPhysicalNames(collaborateur.SourceReference, forbidden);
}
}
// ---- Référentiels non résolus --------------------------------------------------
[Fact]
public void CollaborateurBatik_UnresolvedCiviliteAndStatut_KeepsLegacyIdAndWarns()
{
var row = new BatikModels.CollaborateurRow
{
COPKID = 7,
COIDCivilite = 77,
COIDStatut = 88
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row);
Assert.NotNull(result.Value.Civilite);
Assert.Equal(77, result.Value.Civilite!.LegacyId);
Assert.Equal(string.Empty, result.Value.Civilite!.Label);
Assert.NotNull(result.Value.Statut);
Assert.Equal(88, result.Value.Statut!.LegacyId);
Assert.Contains(result.Warnings, w => w.Contains("CO_IDCivilite", StringComparison.Ordinal)
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
Assert.Contains(result.Warnings, w => w.Contains("CO_IDStatut", StringComparison.Ordinal)
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
}
[Fact]
public void CollaborateurBatik_ZeroCiviliteAndStatut_ProducesNoReference()
{
var row = new BatikModels.CollaborateurRow { COPKID = 8, COIDCivilite = 0, COIDStatut = 0 };
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row);
Assert.Null(result.Value.Civilite);
Assert.Null(result.Value.Statut);
Assert.Empty(result.Warnings);
}
// ---- Rubriques sans équivalent --------------------------------------------------
[Fact]
public void CollaborateurBatik_FieldsWithoutCanonicalEquivalent_AreReportedAsIgnored()
{
var row = new BatikModels.CollaborateurRow
{
COPKID = 9,
COFonction = "Développeur",
COPonderation = 1.5f,
COIDImport = "IMP-9",
COAuPlanning = true,
COAccesBO = true,
COAccesMobile = true,
CreationDate = new DateTime(2024, 1, 1),
ModifDate = new DateTime(2024, 6, 1)
};
CanonicalMappingResult<Collaborateur> result = BatikMappers.BatikCollaborateurMapper.Map(row);
Assert.Equal("Développeur", result.Value.Fonction);
Assert.Contains(result.IgnoredFields, f => f == "CO_Ponderation");
Assert.Contains(result.IgnoredFields, f => f == "CO_IDImport");
Assert.Contains(result.IgnoredFields, f => f == "CO_AuPlanning");
Assert.Contains(result.IgnoredFields, f => f == "CO_AccesBO");
Assert.Contains(result.IgnoredFields, f => f == "CO_AccesMobile");
Assert.Contains(result.IgnoredFields, f => f == "CreationDate");
Assert.Contains(result.IgnoredFields, f => f == "ModifDate");
Assert.Null(result.Value.SocieteId);
}
// ---- 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));
}
}
}