Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
using Omika.Core.Compatibility;
|
||||
using Omika.Core.Domain.Entities.Interventions;
|
||||
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 interventions.
|
||||
/// Aucune base réelle, aucun HFSQL : uniquement des objets en mémoire.
|
||||
/// </summary>
|
||||
public class BatikInterventionMapperTests
|
||||
{
|
||||
// ---- 1. Intervention Batik minimale -------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_Minimal_MapsWithoutExceptionAndKeepsNoFabricatedValue()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow { INPKID = 1 };
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row);
|
||||
|
||||
Assert.Equal(DatabaseSchemaVersion.Batik, result.SourceVersion);
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.Titre);
|
||||
Assert.Null(result.Value.Reference);
|
||||
Assert.Null(result.Value.Type);
|
||||
Assert.Null(result.Value.Etat);
|
||||
Assert.False(result.Value.EstArchive);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
// ---- 2. Intervention Batik complète -------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_Full_MapsAllCanonicalProperties()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow
|
||||
{
|
||||
INPKID = 42,
|
||||
INTitre = "Réparation chaudière",
|
||||
INRefInterne = "INT-042",
|
||||
INDescription = "Remplacement de la chaudière",
|
||||
INIDTypeIntervention = 2,
|
||||
INIDEtatIntervention = 3,
|
||||
INDateIntervention = new DateOnly(2026, 3, 15),
|
||||
Archive = true,
|
||||
INIDImport = "IMP-B-42"
|
||||
};
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[2] = new() { PAPKID = 2, PACode = "T", PAValeur = "1", PALibelle = "Maintenance" },
|
||||
[3] = new() { PAPKID = 3, PACode = "S", PAValeur = "1", PALibelle = "En cours" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row, referenceRows);
|
||||
|
||||
Intervention intervention = result.Value;
|
||||
Assert.Equal("Réparation chaudière", intervention.Titre);
|
||||
Assert.Equal("INT-042", intervention.Reference);
|
||||
Assert.Equal("Remplacement de la chaudière", intervention.Description);
|
||||
Assert.Equal("Maintenance", intervention.Type!.Label);
|
||||
Assert.Equal(2, intervention.Type!.LegacyId);
|
||||
Assert.Equal("En cours", intervention.Etat!.Label);
|
||||
Assert.Equal(3, intervention.Etat!.LegacyId);
|
||||
Assert.Equal(new DateTime(2026, 3, 15), intervention.DatePrevueDebut);
|
||||
Assert.True(intervention.EstArchive);
|
||||
}
|
||||
|
||||
// ---- 4. Type et état ----------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_Type_IsResolvedFromLegacyId()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow { INPKID = 5, INIDTypeIntervention = 7 };
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[7] = new() { PAPKID = 7, PACode = "T", PAValeur = "2", PALibelle = "Urgence" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row, referenceRows);
|
||||
|
||||
Assert.NotNull(result.Value.Type);
|
||||
Assert.Equal("Urgence", result.Value.Type!.Label);
|
||||
Assert.Equal(7, result.Value.Type!.LegacyId);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_UnresolvedType_KeepsLegacyIdAndWarns()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow { INPKID = 6, INIDTypeIntervention = 77 };
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.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("IN_IDTypeIntervention", StringComparison.Ordinal)
|
||||
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_ZeroType_ProducesNoReference()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow { INPKID = 8, INIDTypeIntervention = 0 };
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row);
|
||||
|
||||
Assert.Null(result.Value.Type);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_UnresolvedEtat_KeepsLegacyIdAndWarns()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow { INPKID = 9, INIDEtatIntervention = 88 };
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value.Etat);
|
||||
Assert.Equal(88, result.Value.Etat!.LegacyId);
|
||||
Assert.Contains(result.Warnings, w => w.Contains("IN_IDEtatIntervention", StringComparison.Ordinal)
|
||||
&& w.Contains(MappingWarningCodes.UnresolvedReference, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
// ---- 5. Champs ignorés --------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_FieldsWithoutCanonicalEquivalent_AreReportedAsIgnored()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow
|
||||
{
|
||||
INPKID = 15,
|
||||
INIDClient = 1,
|
||||
INIDLieu = 2,
|
||||
INIDDossier = 3,
|
||||
INIDSuiviPar = 4,
|
||||
INIDDemandeur = 5,
|
||||
INIDSociete = 6,
|
||||
INAttestationTVAPresente = true,
|
||||
INNoteInterne = "note",
|
||||
INRefExterne = "EXT-1",
|
||||
INDureePrevue = 2.5f,
|
||||
INNumDevis = "DEV-1",
|
||||
INDateDevis = new DateOnly(2026, 1, 1),
|
||||
INNumFacture = "FAC-1",
|
||||
INDateFacture = new DateOnly(2026, 2, 1),
|
||||
INNumIntervention = "N-1",
|
||||
ModifDate = new DateTime(2024, 1, 1),
|
||||
CreationDate = new DateTime(2023, 1, 1),
|
||||
DateArchivage = new DateTime(2024, 6, 1)
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row);
|
||||
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_IDClient");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_IDLieu");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_IDDossier");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_IDSuiviPar");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_IDDemandeur");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_IDSociete");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_AttestationTVAPresente");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_NoteInterne");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_DureePrevue");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_DateDevis");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "IN_DateFacture");
|
||||
Assert.Equal(new DateTime(2024, 1, 1), result.Value.DateModification);
|
||||
Assert.Contains(result.IgnoredFields, f => f == "CreationDate");
|
||||
Assert.Contains(result.IgnoredFields, f => f == "DateArchivage");
|
||||
|
||||
// Champs désormais dotés d'un équivalent canonique : ils ne sont plus
|
||||
// ignorés, ils sont mappés dans l'entité Intervention.
|
||||
Assert.Equal("EXT-1", result.Value.ReferenceExterne);
|
||||
Assert.Equal("DEV-1", result.Value.NumeroDevis);
|
||||
Assert.Equal("N-1", result.Value.NumeroIntervention);
|
||||
Assert.Equal("FAC-1", result.Value.NumeroFacture);
|
||||
}
|
||||
|
||||
// ---- 6. Aucune exception sur les chaînes vides --------------------------------
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_EmptyOrNullStrings_NeverThrow()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow
|
||||
{
|
||||
INTitre = "",
|
||||
INRefInterne = " ",
|
||||
INDescription = "",
|
||||
INNoteInterne = " ",
|
||||
INRefExterne = "",
|
||||
INIDImport = " "
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Null(result.Value.Titre);
|
||||
Assert.Null(result.Value.Reference);
|
||||
Assert.Null(result.Value.Description);
|
||||
Assert.Empty(result.Warnings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_DefaultRow_NeverThrows()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow();
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row);
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.False(result.Value.EstArchive);
|
||||
}
|
||||
|
||||
// ---- 7. Absence de noms physiques HFSQL dans le domaine canonique -------------
|
||||
|
||||
[Fact]
|
||||
public void InterventionBatik_CanonicalDomain_DoesNotExposeHfSqlNames()
|
||||
{
|
||||
var row = new BatikModels.InterventionRow
|
||||
{
|
||||
INPKID = 40,
|
||||
INTitre = "Titre",
|
||||
INRefInterne = "INT-040",
|
||||
INDescription = "desc",
|
||||
INIDTypeIntervention = 2,
|
||||
INIDEtatIntervention = 3,
|
||||
INDateIntervention = new DateOnly(2026, 1, 1),
|
||||
Archive = false,
|
||||
INIDImport = "IMP-40",
|
||||
INIDClient = 1,
|
||||
INIDLieu = 2,
|
||||
INIDDossier = 3,
|
||||
INIDSuiviPar = 4,
|
||||
INIDDemandeur = 5,
|
||||
INIDSociete = 6,
|
||||
INAttestationTVAPresente = true,
|
||||
INNoteInterne = "note",
|
||||
INRefExterne = "EXT",
|
||||
INDureePrevue = 1f,
|
||||
INNumDevis = "DEV",
|
||||
INNumFacture = "FAC",
|
||||
INNumIntervention = "N"
|
||||
};
|
||||
|
||||
var referenceRows = new Dictionary<long, BatikModels.ParametreMetierRow>
|
||||
{
|
||||
[2] = new() { PAPKID = 2, PACode = "T", PAValeur = "1", PALibelle = "Maintenance" },
|
||||
[3] = new() { PAPKID = 3, PACode = "S", PAValeur = "1", PALibelle = "En cours" }
|
||||
};
|
||||
|
||||
CanonicalMappingResult<Intervention> result = BatikMappers.BatikInterventionMapper.Map(row, referenceRows);
|
||||
Intervention intervention = result.Value;
|
||||
|
||||
string[] forbidden =
|
||||
[
|
||||
"IN_", "PA_", "PKID", "HfSql", "HFSQL", "GUID"
|
||||
];
|
||||
|
||||
AssertHasNoPhysicalNames(intervention, forbidden);
|
||||
|
||||
if (intervention.SourceReference is not null)
|
||||
{
|
||||
AssertHasNoPhysicalNames(intervention.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