218 lines
8.2 KiB
C#
218 lines
8.2 KiB
C#
using Omika.Data.Repositories;
|
|
|
|
namespace Omika.Tests.Data;
|
|
|
|
/// <summary>
|
|
/// Tests de la résolution répertoire par répertoire des documents (ancres #id).
|
|
/// Le chemin est reconstruit depuis la structure Omika :
|
|
/// <c>[LI_CodeLieu] #[LI_PKID]\[CL_Nom] #[CL_PKID]\[IN_RefInterne] #[IN_PKID]\$DC_Categorie_Id$</c>.
|
|
/// Objectif : retrouver le répertoire existant même si un libellé a été modifié ou
|
|
/// contient des espaces en trop, sans jamais créer de doublon — et sans jamais
|
|
/// lancer de recherche sur le chemin complet.
|
|
/// </summary>
|
|
public class DocumentAnchoredPathTests : IDisposable
|
|
{
|
|
private const string ExpectedPath =
|
|
@"402 ORCHIDEES 2 #3512\Dupont #12\INT-0001 #3401\Photos #46";
|
|
|
|
private readonly string _root;
|
|
|
|
public DocumentAnchoredPathTests()
|
|
{
|
|
_root = Path.Combine(Path.GetTempPath(), "omika-anchors", Guid.NewGuid().ToString("N"));
|
|
Directory.CreateDirectory(_root);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(_root))
|
|
{
|
|
Directory.Delete(_root, recursive: true);
|
|
}
|
|
}
|
|
|
|
// --- Extraction de l'ancre ------------------------------------------------
|
|
|
|
[Fact]
|
|
public void TryParseAnchor_ExtraitLeDernierIdentifiant()
|
|
{
|
|
bool parsed = DocumentPathResolver.TryParseAnchor("Dupont #2 #3512", out string label, out long id);
|
|
|
|
Assert.True(parsed);
|
|
Assert.Equal(3512, id);
|
|
Assert.Equal("Dupont #2", label);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseAnchor_TolereLesEspacesAutourDuDiese()
|
|
{
|
|
Assert.True(DocumentPathResolver.TryParseAnchor("Photos # 46", out _, out long id1));
|
|
Assert.Equal(46, id1);
|
|
|
|
Assert.True(DocumentPathResolver.TryParseAnchor("Photos #46", out _, out long id2));
|
|
Assert.Equal(46, id2);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseAnchor_SansIdentifiant_RetourneFaux()
|
|
{
|
|
Assert.False(DocumentPathResolver.TryParseAnchor("Intervention", out string label, out long id));
|
|
Assert.Equal(0, id);
|
|
Assert.Equal("Intervention", label);
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizeSegmentName_CompacteLesEspacesEtLaCasse()
|
|
{
|
|
Assert.Equal(
|
|
DocumentPathResolver.NormalizeSegmentName("402 ORCHIDEES 2 #3512"),
|
|
DocumentPathResolver.NormalizeSegmentName("402 ORCHIDEES 2 #3512"));
|
|
}
|
|
|
|
// --- Recherche du fichier -------------------------------------------------
|
|
|
|
[Fact]
|
|
public void RetrouveLeFichier_MalgreUnEspaceDoubleDansLeRepertoireRacine()
|
|
{
|
|
// Le disque porte « 402 ORCHIDEES 2 #3512 » (deux espaces), la base produit
|
|
// « 402 ORCHIDEES 2 #3512 » (un seul).
|
|
string actualDirectory = CreateDirectoryWithFile(@"402 ORCHIDEES 2 #3512\Dupont #12\INT-0001 #3401\Photos #46");
|
|
|
|
string? found = DocumentPathResolver.ResolveAnchoredDocumentFile(
|
|
_root, ExpectedPath, "photo.jpg", Guid.Empty);
|
|
|
|
Assert.NotNull(found);
|
|
Assert.Equal(
|
|
Path.GetFullPath(Path.Combine(actualDirectory, "photo.jpg")),
|
|
Path.GetFullPath(found!));
|
|
}
|
|
|
|
[Fact]
|
|
public void RetrouveLeFichier_MalgreUnLibelleModifie()
|
|
{
|
|
// Le client a été renommé : le disque porte « Dupont SA #12 », la base produit
|
|
// « Dupont #12 ». L'ancre #12 reste identique.
|
|
string actualDirectory = CreateDirectoryWithFile(@"402 ORCHIDEES 2 #3512\Dupont SA #12\INT-0001 #3401\Photos #46");
|
|
|
|
string? found = DocumentPathResolver.ResolveAnchoredDocumentFile(
|
|
_root, ExpectedPath, "photo.jpg", Guid.Empty);
|
|
|
|
Assert.NotNull(found);
|
|
Assert.Equal(
|
|
Path.GetFullPath(Path.Combine(actualDirectory, "photo.jpg")),
|
|
Path.GetFullPath(found!));
|
|
}
|
|
|
|
[Fact]
|
|
public void RetrouveLeFichier_QuandLeSegmentDeCategorieEstAbsent()
|
|
{
|
|
// Document historique : pas de sous-répertoire de catégorie sur le disque.
|
|
string interventionDirectory = CreateDirectoryWithFile(@"402 ORCHIDEES 2 #3512\Dupont #12\INT-0001 #3401");
|
|
|
|
string? found = DocumentPathResolver.ResolveAnchoredDocumentFile(
|
|
_root, ExpectedPath, "photo.jpg", Guid.Empty);
|
|
|
|
Assert.NotNull(found);
|
|
Assert.Equal(
|
|
Path.GetFullPath(Path.Combine(interventionDirectory, "photo.jpg")),
|
|
Path.GetFullPath(found!));
|
|
}
|
|
|
|
[Fact]
|
|
public void NeDescendPas_QuandUnNiveauIntermediaireManque()
|
|
{
|
|
// Le répertoire du client est absent : la descente doit s'arrêter là et ne
|
|
// jamais partir en recherche sur le chemin complet.
|
|
CreateDirectoryWithFile(@"402 ORCHIDEES 2 #3512\INT-0001 #3401\Photos #46");
|
|
|
|
string? found = DocumentPathResolver.ResolveAnchoredDocumentFile(
|
|
_root, ExpectedPath, "photo.jpg", Guid.Empty);
|
|
|
|
Assert.Null(found);
|
|
}
|
|
|
|
[Fact]
|
|
public void NeConfondPasDeuxIdentifiantsProches()
|
|
{
|
|
// #3512 attendu, le disque porte #13512 : aucune correspondance.
|
|
CreateDirectoryWithFile(@"402 ORCHIDEES 2 #13512\Dupont #12\INT-0001 #3401\Photos #46");
|
|
|
|
string? found = DocumentPathResolver.ResolveAnchoredDocumentFile(
|
|
_root, ExpectedPath, "photo.jpg", Guid.Empty);
|
|
|
|
Assert.Null(found);
|
|
}
|
|
|
|
// --- Création : réutilisation sans doublon --------------------------------
|
|
|
|
[Fact]
|
|
public void Creation_ReutiliseLeRepertoireExistant()
|
|
{
|
|
string existing = CreateDirectoryWithFile(@"402 ORCHIDEES 2 #3512\Dupont SA #12\INT-0001 #3401\Photos #46");
|
|
int directoriesBefore = Directory.GetDirectories(_root, "*", SearchOption.AllDirectories).Length;
|
|
|
|
DocumentPathResolver.AnchorResolution resolution = DocumentPathResolver.EnsureAnchoredDirectory(
|
|
_root, DocumentPathResolver.ParseAnchors(ExpectedPath));
|
|
|
|
// Le répertoire réel (deux espaces, libellé « Dupont SA ») est réutilisé tel quel.
|
|
Assert.NotNull(resolution.RelativeDirectory);
|
|
Assert.Equal(
|
|
Path.GetFullPath(existing),
|
|
Path.GetFullPath(Path.Combine(_root, resolution.RelativeDirectory!)));
|
|
|
|
// Aucun répertoire concurrent n'a été créé.
|
|
Assert.Equal(directoriesBefore, Directory.GetDirectories(_root, "*", SearchOption.AllDirectories).Length);
|
|
Assert.False(Directory.Exists(Path.Combine(_root, @"402 ORCHIDEES 2 #3512")));
|
|
}
|
|
|
|
[Fact]
|
|
public void Creation_AjouteUniquementLesSegmentsManquants()
|
|
{
|
|
// Client et intervention existent, la catégorie manque.
|
|
string interventionDirectory = Path.Combine(_root, @"402 ORCHIDEES 2 #3512\Dupont #12\INT-0001 #3401");
|
|
Directory.CreateDirectory(interventionDirectory);
|
|
Directory.CreateDirectory(Path.Combine(_root, @"402 ORCHIDEES 2 #3512\Dupont #12"));
|
|
|
|
DocumentPathResolver.AnchorResolution resolution = DocumentPathResolver.EnsureAnchoredDirectory(
|
|
_root, DocumentPathResolver.ParseAnchors(ExpectedPath));
|
|
|
|
Assert.True(resolution.IsComplete);
|
|
Assert.Equal(4, resolution.ResolvedDepth);
|
|
|
|
string expectedFinal = Path.Combine(interventionDirectory, "Photos #46");
|
|
Assert.Equal(Path.GetFullPath(expectedFinal), Path.GetFullPath(resolution.FullDirectory!));
|
|
Assert.True(Directory.Exists(expectedFinal));
|
|
}
|
|
|
|
[Fact]
|
|
public void Creation_DepuisUneRacineVide_CreeTouteLArborescence()
|
|
{
|
|
DocumentPathResolver.AnchorResolution resolution = DocumentPathResolver.EnsureAnchoredDirectory(
|
|
_root, DocumentPathResolver.ParseAnchors(ExpectedPath));
|
|
|
|
Assert.True(resolution.IsComplete);
|
|
Assert.Equal(
|
|
Path.GetFullPath(Path.Combine(_root, ExpectedPath)),
|
|
Path.GetFullPath(resolution.FullDirectory!));
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseAnchors_IgnoreLesSeparateursMultiples()
|
|
{
|
|
IReadOnlyList<DocumentPathResolver.AnchoredSegment> segments =
|
|
DocumentPathResolver.ParseAnchors(@"\\402 ORCHIDEES 2 #3512\\Dupont #12\");
|
|
|
|
Assert.Equal(2, segments.Count);
|
|
Assert.Equal(3512, segments[0].Id);
|
|
Assert.Equal(12, segments[1].Id);
|
|
}
|
|
|
|
private string CreateDirectoryWithFile(string relativeDirectory)
|
|
{
|
|
string directory = Path.Combine(_root, relativeDirectory);
|
|
Directory.CreateDirectory(directory);
|
|
File.WriteAllBytes(Path.Combine(directory, "photo.jpg"), [1, 2, 3]);
|
|
return directory;
|
|
}
|
|
}
|