using Omika.App.Local.Abstractions;
using Omika.App.Local.Models;
using Omika.Core.Contracts.Mobile.Languages;
namespace Omika.Tests.Mobile.Local;
///
/// Double de test de : conserve
/// la langue choisie en mémoire, sans SQLite ni identité de bootstrap.
///
public sealed class FakeLangueSecondairePreferenceService : ILangueSecondairePreferenceService
{
private LangueSecondairePreference _preference = LangueSecondairePreference.ParDefaut;
/// Langue effectivement enregistrée (dernier appel réussi).
public LangueSecondairePreference Enregistree => _preference;
/// Nombre d'appels à .
public int Effacements { get; private set; }
/// Configure la préférence retournée par .
public void Set(string code, string libelle = "")
=> _preference = LangueSecondairePreference.Normaliser(code, libelle);
///
public Task GetAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(_preference);
///
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;
}
///
public Task EffacerAsync(CancellationToken cancellationToken = default)
{
Effacements++;
_preference = LangueSecondairePreference.ParDefaut;
return Task.CompletedTask;
}
}
///
/// Double de test de : aucun réseau, aucune
/// écriture disque. La liste et le résultat de téléchargement sont pilotés par
/// le test.
///
public sealed class FakeLanguagePackService : ILanguagePackService
{
/// Langues retournées par .
public List Langues { get; } = [];
/// URL de base retournée (paramètre SRV_LANGUES simulé).
public string? UrlBase { get; set; } = "https://langues.exemple.test";
/// Erreur à lever par (cas hors ligne).
public Exception? EchecListe { get; set; }
/// Erreur à lever par .
public Exception? EchecTelechargement { get; set; }
/// Codes de langue effectivement téléchargés.
public List Telecharges { get; } = [];
/// Codes de langue effectivement supprimés.
public List Supprimes { get; } = [];
/// Vrai si le dernier appel de liste demandait le réseau.
public bool DernierAppelReseau { get; private set; }
///
public Task GetUrlBaseAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(UrlBase);
///
public Task> ListerLanguesAsync(
bool forcerReseau = false,
CancellationToken cancellationToken = default)
{
DernierAppelReseau = forcerReseau;
if (EchecListe is not null)
{
throw EchecListe;
}
return Task.FromResult>(Langues);
}
///
public Task TelechargerAsync(
string code,
IProgress? 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]
});
}
///
public Task SupprimerAsync(string code, CancellationToken cancellationToken = default)
{
Supprimes.Add(code);
return Task.CompletedTask;
}
/// Construit une langue disponible pour les tests.
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
};
}
///
/// Double de test de : 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.
///
public sealed class FakeTranslationService : ITranslationService
{
/// Vrai si un moteur d'inférence est simulé comme présent.
public bool EstDisponible { get; set; }
/// Vrai si les modèles sont simulés comme installés.
public bool ModelesInstalles { get; set; }
/// Texte retourné par la traduction.
public string Resultat { get; set; } = "[traduit]";
/// Erreur à lever à la place d'une traduction.
public Exception? Echec { get; set; }
/// Sens demandés lors des traductions (dans l'ordre).
public List SensDemandes { get; } = [];
///
public Task EstInstalleeAsync(
string codeLangue,
SensTraduction sens,
CancellationToken cancellationToken = default)
=> Task.FromResult(ModelesInstalles);
///
public Task TraduireAsync(
string? texte,
string codeLangue,
SensTraduction sens,
CancellationToken cancellationToken = default)
{
SensDemandes.Add(sens);
return Echec is not null
? Task.FromException(Echec)
: Task.FromResult(Resultat);
}
}