Premiere commit - Omika

This commit is contained in:
2026-10-23 18:46:50 +02:00
commit 8ea76c1b24
2155 changed files with 984301 additions and 0 deletions
@@ -0,0 +1,233 @@
using System.Text;
using Omika.Core.Services;
namespace Omika.Tests.Services;
/// <summary>
/// Tests de la préparation pure d'une tentative d'envoi : composition du corps
/// (BASE BODY + signature), décodage de signature, fusion CC/CCI effectifs
/// (règles §4, §8-§11). Aucun réseau ni persistance.
/// </summary>
public class EmailEnvoiPreparationTests
{
// TEST 4 / 5 : la signature n'est ajoutée qu'au corps d'envoi, jamais au corps de base.
[Fact]
public void ComposerCorpsEnvoi_SansSignature_RetourneCorpsDeBase()
{
Assert.Equal("BODY", EmailEnvoiPreparation.ComposerCorpsEnvoi("BODY", null));
Assert.Equal("BODY", EmailEnvoiPreparation.ComposerCorpsEnvoi("BODY", " "));
Assert.Equal("BODY", EmailEnvoiPreparation.ComposerCorpsEnvoi("BODY", string.Empty));
}
[Fact]
public void ComposerCorpsEnvoi_AvecSignature_AppendLaSignature()
{
Assert.Equal("BODY<div>sig</div>", EmailEnvoiPreparation.ComposerCorpsEnvoi("BODY", "<div>sig</div>"));
}
// TEST 6 : changer de configuration (A → B) n'accumule jamais les signatures.
[Fact]
public void ComposerCorpsEnvoi_ConfigurationsDifferentes_SignaturesIndependantes()
{
const string baseBody = "BODY";
Assert.Equal("BODY<A>", EmailEnvoiPreparation.ComposerCorpsEnvoi(baseBody, "<A>"));
Assert.Equal("BODY<B>", EmailEnvoiPreparation.ComposerCorpsEnvoi(baseBody, "<B>"));
Assert.Equal("BODY", baseBody); // le corps de base n'est jamais muté.
}
[Fact]
public void DecoderSignature_Base64Html_ExtraitBody()
{
string html = "<html><head><style>a{}</style></head><body><p>Signature</p></body></html>";
string b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(html));
Assert.Equal("<p>Signature</p>", EmailEnvoiPreparation.DecoderSignature(b64));
}
[Fact]
public void DecoderSignature_VideOuAbsente_RetourneNull()
{
Assert.Null(EmailEnvoiPreparation.DecoderSignature(null));
Assert.Null(EmailEnvoiPreparation.DecoderSignature(" "));
}
// TEST 7 : tabCC_CopieEmail ajouté au CC SMTP (fusion).
[Fact]
public void FusionnerCc_UserEtConfig_Fusionne()
{
IReadOnlyList<string> result = EmailEnvoiPreparation.FusionnerCc(
"client1@example.test",
["archive@example.test", "supervision@example.test"]);
Assert.Equal(["client1@example.test", "archive@example.test", "supervision@example.test"], result);
}
// TEST 8 : en cas d'échec, seul le CC utilisateur est conservé (aucun CC config).
[Fact]
public void FusionnerCc_UserSeul_SansConfig()
{
IReadOnlyList<string> result = EmailEnvoiPreparation.FusionnerCc("client1@example.test", null);
Assert.Equal(["client1@example.test"], result);
}
// TEST 11 : fusion + dédoublonnage insensible à la casse + vides retirés.
[Fact]
public void FusionnerCc_DedoublonneEtNettoie()
{
IReadOnlyList<string> result = EmailEnvoiPreparation.FusionnerCc(
"A@x.com; b@x.com; ;a@X.com",
["a@x.com", "", "C@x.com"]);
Assert.Equal(["A@x.com", "b@x.com", "C@x.com"], result);
}
// TEST 9 : bEnCopieCachee=true → adresse expéditrice ajoutée au CCI.
[Fact]
public void FusionnerCci_EnCopieCachee_AjouteSender()
{
IReadOnlyList<string> result = EmailEnvoiPreparation.FusionnerCci("user@x.com", true, "sender@x.com");
Assert.Equal(["user@x.com", "sender@x.com"], result);
}
// TEST 10 : bEnCopieCachee=false → aucun auto-CCI.
[Fact]
public void FusionnerCci_SansEnCopieCachee_NeAjoutePasSender()
{
IReadOnlyList<string> result = EmailEnvoiPreparation.FusionnerCci("user@x.com", false, "sender@x.com");
Assert.Equal(["user@x.com"], result);
}
[Fact]
public void FusionnerCci_DedoublonneSender()
{
IReadOnlyList<string> result = EmailEnvoiPreparation.FusionnerCci("sender@x.com", true, "sender@x.com");
Assert.Equal(["sender@x.com"], result);
}
// =====================================================================
// ME_IDDocPJ — construction des PKID HFSQL (règles §2, §6)
// =====================================================================
// TEST PJ ID 1 : aucune pièce jointe → chaîne vide (jamais "0").
[Fact]
public void ConstruireIdDocPj_AucunePiece_RetourneChaineVide()
{
Assert.Equal(string.Empty, EmailEnvoiPreparation.ConstruireIdDocPj([]));
Assert.Equal(string.Empty, EmailEnvoiPreparation.ConstruireIdDocPj(null!));
}
// TEST PJ ID 2 : une seule PJ → son PKID, sans séparateur.
[Fact]
public void ConstruireIdDocPj_UnePiece_RetourneLePk()
{
Assert.Equal("281474976850215", EmailEnvoiPreparation.ConstruireIdDocPj([281474976850215L]));
}
// TEST PJ ID 3 : plusieurs PJ → séparées par « ; », ordre conservé.
[Fact]
public void ConstruireIdDocPj_TroisPieces_SeparateurPointVirgule()
{
string result = EmailEnvoiPreparation.ConstruireIdDocPj(
[281474976850215L, 281474976850216L, 281474976850217L]);
Assert.Equal("281474976850215;281474976850216;281474976850217", result);
}
// TEST PJ ID 4 : jamais de virgule.
[Fact]
public void ConstruireIdDocPj_NeContientPasDeVirgule()
{
string result = EmailEnvoiPreparation.ConstruireIdDocPj(
[281474976850215L, 281474976850216L]);
Assert.DoesNotContain(",", result);
}
// TEST PJ ID 5 : jamais de GUID (uniquement des chiffres et « ; »).
[Fact]
public void ConstruireIdDocPj_NeContientPasDeGuid()
{
string result = EmailEnvoiPreparation.ConstruireIdDocPj(
[281474976850215L, 281474976850216L]);
Assert.Matches("^[0-9;]+$", result);
Assert.DoesNotContain("-", result);
}
// TEST PJ ID 6 : aucun séparateur final.
[Fact]
public void ConstruireIdDocPj_AucunSeparateurFinal()
{
string result = EmailEnvoiPreparation.ConstruireIdDocPj(
[281474976850215L, 281474976850216L]);
Assert.False(result.EndsWith(';'));
}
// Règles §6 : IDs <= 0 ignorés, doublons supprimés.
[Fact]
public void ConstruireIdDocPj_IgnoreIdsNonPositifs_EtDedoublonne()
{
string result = EmailEnvoiPreparation.ConstruireIdDocPj(
[0L, -5L, 281474976850215L, 281474976850215L, 281474976850216L]);
Assert.Equal("281474976850215;281474976850216", result);
}
// =====================================================================
// ME_PieceJointes — chemins complets serveur (règles §5)
// =====================================================================
// TEST PATH 1 : un seul document → son chemin complet serveur.
[Fact]
public void ConstruireCheminsPj_UnChemin_RetourneLeChemin()
{
Assert.Equal(@"D:\Documents\Client\Inter\photo.jpg",
EmailEnvoiPreparation.ConstruireCheminsPj([@"D:\Documents\Client\Inter\photo.jpg"]));
}
// TEST PATH 2 : deux documents → PATH1;PATH2.
[Fact]
public void ConstruireCheminsPj_DeuxChemins_SeparateurPointVirgule()
{
string result = EmailEnvoiPreparation.ConstruireCheminsPj(
[@"D:\Documents\a.jpg", @"D:\Documents\b.pdf"]);
Assert.Equal(@"D:\Documents\a.jpg;D:\Documents\b.pdf", result);
}
// TEST PATH 5 : cardinalité identique entre ME_IDDocPJ et ME_PieceJointes.
[Fact]
public void IdDocPj_EtChemins_ComptesIdentiques()
{
long[] pks = [101, 205, 312];
string[] chemins = [@"D:\a.jpg", @"D:\b.pdf", @"D:\c.txt"];
string ids = EmailEnvoiPreparation.ConstruireIdDocPj(pks);
string paths = EmailEnvoiPreparation.ConstruireCheminsPj(chemins);
Assert.Equal("101;205;312", ids);
Assert.Equal(3, ids.Split(';').Length);
Assert.Equal(3, paths.Split(';').Length);
}
// Règles §5 : vides retirés, doublons supprimés (insensible à la casse),
// aucun séparateur final.
[Fact]
public void ConstruireCheminsPj_RetireVides_Dedoublonne_SansSeparateurFinal()
{
string result = EmailEnvoiPreparation.ConstruireCheminsPj(
[@"D:\a.jpg", "", " ", @"d:\A.JPG", @"D:\b.pdf"]);
Assert.Equal(@"D:\a.jpg;D:\b.pdf", result);
Assert.False(result.EndsWith(';'));
}
// Aucune pièce jointe → chaîne vide (jamais null ni "0").
[Fact]
public void ConstruireCheminsPj_AucunChemin_RetourneChaineVide()
{
Assert.Equal(string.Empty, EmailEnvoiPreparation.ConstruireCheminsPj([]));
Assert.Equal(string.Empty, EmailEnvoiPreparation.ConstruireCheminsPj(null!));
}
}