Files
2026-10-23 18:46:50 +02:00

195 lines
6.7 KiB
C#

using Omika.App.Local.Abstractions;
using Omika.App.Local.Models;
using Omika.Core.Contracts.Mobile.Languages;
namespace Omika.Tests.Mobile.Local;
/// <summary>
/// Double de test de <see cref="ILangueSecondairePreferenceService"/> : conserve
/// la langue choisie en mémoire, sans SQLite ni identité de bootstrap.
/// </summary>
public sealed class FakeLangueSecondairePreferenceService : ILangueSecondairePreferenceService
{
private LangueSecondairePreference _preference = LangueSecondairePreference.ParDefaut;
/// <summary>Langue effectivement enregistrée (dernier appel réussi).</summary>
public LangueSecondairePreference Enregistree => _preference;
/// <summary>Nombre d'appels à <see cref="EffacerAsync"/>.</summary>
public int Effacements { get; private set; }
/// <summary>Configure la préférence retournée par <see cref="GetAsync"/>.</summary>
public void Set(string code, string libelle = "")
=> _preference = LangueSecondairePreference.Normaliser(code, libelle);
/// <inheritdoc />
public Task<LangueSecondairePreference> GetAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(_preference);
/// <inheritdoc />
public Task SaveAsync(string code, string libelle, CancellationToken cancellationToken = default)
{
// Même règle que l'implémentation réelle : un code vide n'est jamais
// enregistré (c'est EffacerAsync qui retire la langue).
if (string.IsNullOrWhiteSpace(code))
{
throw new ArgumentException("Le code de langue est requis.", nameof(code));
}
_preference = LangueSecondairePreference.Normaliser(code, libelle);
return Task.CompletedTask;
}
/// <inheritdoc />
public Task EffacerAsync(CancellationToken cancellationToken = default)
{
Effacements++;
_preference = LangueSecondairePreference.ParDefaut;
return Task.CompletedTask;
}
}
/// <summary>
/// Double de test de <see cref="ILanguagePackService"/> : aucun réseau, aucune
/// écriture disque. La liste et le résultat de téléchargement sont pilotés par
/// le test.
/// </summary>
public sealed class FakeLanguagePackService : ILanguagePackService
{
/// <summary>Langues retournées par <see cref="ListerLanguesAsync"/>.</summary>
public List<LangueDisponible> Langues { get; } = [];
/// <summary>URL de base retournée (paramètre <c>SRV_LANGUES</c> simulé).</summary>
public string? UrlBase { get; set; } = "https://langues.exemple.test";
/// <summary>Erreur à lever par <see cref="ListerLanguesAsync"/> (cas hors ligne).</summary>
public Exception? EchecListe { get; set; }
/// <summary>Erreur à lever par <see cref="TelechargerAsync"/>.</summary>
public Exception? EchecTelechargement { get; set; }
/// <summary>Codes de langue effectivement téléchargés.</summary>
public List<string> Telecharges { get; } = [];
/// <summary>Codes de langue effectivement supprimés.</summary>
public List<string> Supprimes { get; } = [];
/// <summary>Vrai si le dernier appel de liste demandait le réseau.</summary>
public bool DernierAppelReseau { get; private set; }
/// <inheritdoc />
public Task<string?> GetUrlBaseAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(UrlBase);
/// <inheritdoc />
public Task<IReadOnlyList<LangueDisponible>> ListerLanguesAsync(
bool forcerReseau = false,
CancellationToken cancellationToken = default)
{
DernierAppelReseau = forcerReseau;
if (EchecListe is not null)
{
throw EchecListe;
}
return Task.FromResult<IReadOnlyList<LangueDisponible>>(Langues);
}
/// <inheritdoc />
public Task<PackLangueInstalle> TelechargerAsync(
string code,
IProgress<ProgressionTelechargement>? progression = null,
CancellationToken cancellationToken = default)
{
if (EchecTelechargement is not null)
{
throw EchecTelechargement;
}
Telecharges.Add(code);
var fichier = new FichierModeleInstalle
{
Sens = LanguageModelDirections.VersFrancais,
NomFichier = "encoder.onnx",
TailleOctets = 1024,
Sha256 = new string('a', 64)
};
return Task.FromResult(new PackLangueInstalle
{
Code = code,
Libelle = code,
Version = "1.0.0",
InstalleLeUtc = DateTimeOffset.UtcNow,
Fichiers = [fichier]
});
}
/// <inheritdoc />
public Task SupprimerAsync(string code, CancellationToken cancellationToken = default)
{
Supprimes.Add(code);
return Task.CompletedTask;
}
/// <summary>Construit une langue disponible pour les tests.</summary>
public static LangueDisponible Langue(
string code, string libelle, bool installee = false, long taille = 120_000_000)
=> new()
{
Code = code,
Libelle = libelle,
Version = "1.0.0",
TailleOctets = taille,
NombreFichiers = 3,
EstInstallee = installee,
VersionInstallee = installee ? "1.0.0" : string.Empty
};
}
/// <summary>
/// Double de test de <see cref="ITranslationService"/> : la disponibilité, l'état
/// d'installation et la traduction sont pilotés par le test. Aucun modèle ONNX
/// n'est nécessaire, et aucun texte n'est réellement traduit.
/// </summary>
public sealed class FakeTranslationService : ITranslationService
{
/// <summary>Vrai si un moteur d'inférence est simulé comme présent.</summary>
public bool EstDisponible { get; set; }
/// <summary>Vrai si les modèles sont simulés comme installés.</summary>
public bool ModelesInstalles { get; set; }
/// <summary>Texte retourné par la traduction.</summary>
public string Resultat { get; set; } = "[traduit]";
/// <summary>Erreur à lever à la place d'une traduction.</summary>
public Exception? Echec { get; set; }
/// <summary>Sens demandés lors des traductions (dans l'ordre).</summary>
public List<SensTraduction> SensDemandes { get; } = [];
/// <inheritdoc />
public Task<bool> EstInstalleeAsync(
string codeLangue,
SensTraduction sens,
CancellationToken cancellationToken = default)
=> Task.FromResult(ModelesInstalles);
/// <inheritdoc />
public Task<string> TraduireAsync(
string? texte,
string codeLangue,
SensTraduction sens,
CancellationToken cancellationToken = default)
{
SensDemandes.Add(sens);
return Echec is not null
? Task.FromException<string>(Echec)
: Task.FromResult(Resultat);
}
}