using Omika.App.Local.Abstractions; using Omika.Core.Constants; using Omika.Core.Interfaces; namespace Omika.Tests.Mobile.Local; /// /// Double de test de . /// /// Par défaut il reproduit le comportement « aucune optimisation » : le fichier /// source est copié à l'identique vers la destination et le résultat indique que /// rien n'a été modifié. C'est le comportement attendu pour une image déjà sous /// la limite, et cela permet aux tests existants de rester valides. /// /// Le test peut demander une optimisation simulée via . /// public sealed class FakeImageOptimizer : IImageOptimizer { /// Nombre d'appels reçus. public int Calls { get; private set; } /// Dernière limite reçue, en kilo-octets. public int LastMaxSizeKb { get; private set; } = -1; /// /// Contenu à écrire lorsque l'optimisation est simulée. /// signifie « copier la source telle quelle ». /// public byte[]? OptimizedBytes { get; set; } /// Qualité à reporter lorsque l'optimisation est simulée. public int? ReportedQuality { get; set; } = 78; /// public Task OptimizeFileAsync( string sourcePath, string destinationPath, string? fileName, string? mimeType, int maxSizeKb, CancellationToken cancellationToken = default) { Calls++; LastMaxSizeKb = maxSizeKb; long originalBytes = new FileInfo(sourcePath).Length; if (OptimizedBytes is not null) { File.WriteAllBytes(destinationPath, OptimizedBytes); return Task.FromResult(new ImageOptimizationResult { DestinationPath = destinationPath, WasOptimized = true, OriginalBytes = originalBytes, FinalBytes = OptimizedBytes.LongLength, OriginalWidth = 4000, OriginalHeight = 3000, FinalWidth = 2000, FinalHeight = 1500, Quality = ReportedQuality }); } File.Copy(sourcePath, destinationPath, overwrite: true); return Task.FromResult(new ImageOptimizationResult { DestinationPath = destinationPath, WasOptimized = false, OriginalBytes = originalBytes, FinalBytes = originalBytes }); } } /// /// Double de test de : retourne une limite /// fixe, configurable par le test. /// public sealed class FakePhotoPolicyProvider : IPhotoPolicyProvider { /// Limite retournée, en kilo-octets (0 = aucune limite). public int MaxSizeKb { get; set; } = 500; /// Origine retournée. public PhotoLimitSource Source { get; set; } = PhotoLimitSource.ApplicationParameter; /// public Task GetResolutionAsync(CancellationToken cancellationToken = default) => Task.FromResult(new PhotoLimitResolution(MaxSizeKb, Source)); } /// /// Double de test de adossé à un /// dictionnaire en mémoire. /// public sealed class FakeApplicationParameterRepository : IApplicationParameterRepository { /// Valeurs des paramètres applicatifs, indexées par code. public Dictionary Values { get; } = new(StringComparer.Ordinal); /// public Task GetValueAsync(string code, CancellationToken cancellationToken = default) { Values.TryGetValue(code, out string? value); return Task.FromResult(value); } } /// /// Double de test de . /// /// Par défaut il reproduit le cas « aucune métadonnée fiable » : la date système /// est retournée avec la source , /// ce qui correspond au comportement des tests existants (aucun fichier réel /// porteur d'EXIF). Le test peut fixer une date explicite avec /// , ou simuler un lecteur en échec avec /// . /// public sealed class FakeDocumentDateResolver : IDocumentDateResolver { /// Nombre d'appels reçus. public int Calls { get; private set; } /// Dernier chemin reçu. public string? LastPath { get; private set; } /// Date retournée lorsque la propriété est fixée. public DateTime? ResolvedDate { get; set; } /// Origine retournée (utilisée seulement si est fixée). public DocumentDateSource Source { get; set; } = DocumentDateSource.ExifDateTimeOriginal; /// Simule un lecteur en échec : la résolution lève une exception. public bool ThrowOnResolve { get; set; } /// public Task ResolveAsync( string filePath, string? fileName, CancellationToken cancellationToken = default) { Calls++; LastPath = filePath; if (ThrowOnResolve) { throw new IOException("Métadonnées illisibles (simulation de test)."); } return Task.FromResult(ResolvedDate is { } value ? new DocumentDateResolution(value, Source) : new DocumentDateResolution(DateTime.Now, DocumentDateSource.SystemFallback)); } }