using Omika.Core.Contracts.Mobile.Bootstrap; using Omika.Data.Configuration; using Omika.Data.Connection; using Omika.Data.Repositories.Batik; namespace Omika.Tests.Repositories.Batik; /// /// Tests du repository d'identité mobile Batik. /// Vérifie que le chemin historique Batik continue de résoudre les permissions /// (UT_IDTypeProfil → AccesEtDroit.AED_IDProfil + modules ParametreMetier) et /// que l'utilisateur est désormais résolu par UT_PKID (et non par UT_Login). /// public class BatikMobileIdentityRepositoryTests { private const long UserIdTest = 1001; private const long ProfilIdTest = 3001; private const long ModulePkTest = 5001; private const string LoginTest = "TEST_USER"; [Fact] public async Task GetPermissionsAsync_ResoutParUT_PKID_EtRetourneALicMob() { var connection = new FakeHfsqlConnection(HfsqlConnectionState.Open); connection.UtilisateurRows.Add(UtilisateurRow(UserIdTest, LoginTest, ProfilIdTest)); connection.ParametreMetierRows.Add(ModuleRow(ModulePkTest, "M.PlClb.11")); // → A.LIC.MOB connection.AccesEtDroitRows.Add(DroitRow(ProfilIdTest, ModulePkTest, true)); var repository = new BatikMobileIdentityRepository(connection); IReadOnlyDictionary permissions = await repository.GetPermissionsAsync(UserIdTest.ToString()); Assert.True(permissions["A.LIC.MOB"]); string utilisateurSql = connection.Queries.First(q => q.Contains("FROM Utilisateur", StringComparison.OrdinalIgnoreCase)); Assert.Contains("UT_PKID = ?", utilisateurSql); Assert.DoesNotContain("UT_Login = ?", utilisateurSql); } [Fact] public async Task GetLoginByUserIdAsync_RetourneLoginReel() { var connection = new FakeHfsqlConnection(HfsqlConnectionState.Open); connection.UtilisateurRows.Add(UtilisateurRow(UserIdTest, LoginTest, ProfilIdTest)); var repository = new BatikMobileIdentityRepository(connection); string? login = await repository.GetLoginByUserIdAsync(UserIdTest.ToString()); Assert.Equal(LoginTest, login); } [Fact] public async Task GetProfileAsync_ResoutProfilBatik() { var connection = new FakeHfsqlConnection(HfsqlConnectionState.Open); connection.UtilisateurRows.Add(UtilisateurRow(UserIdTest, LoginTest, ProfilIdTest)); connection.ParametreMetierRows.Add(ProfilRow(ProfilIdTest, "BATIK_PROFIL")); var repository = new BatikMobileIdentityRepository(connection); MobileProfileDto profile = await repository.GetProfileAsync(UserIdTest.ToString()); Assert.Equal("PROFIL", profile.Code); Assert.Equal("BATIK_PROFIL", profile.Nom); } // ===== Fixtures ===== private static Dictionary UtilisateurRow(long pkId, string login, long profilId) => new() { ["UT_PKID"] = pkId, ["UT_Login"] = login, ["UT_IDCollaborateur"] = 2001L, ["UT_IDTypeProfil"] = profilId, ["UT_AccesMobile"] = true }; // Module de la catégorie 29 (« Modules intervenir ») : PA_Valeur = clé Batik. private static Dictionary ModuleRow(long pkId, string valeur) => new() { ["PA_PKID"] = pkId, ["PA_Code"] = "29", ["PA_Libelle"] = "Module", ["PA_Valeur"] = valeur, ["PA_Actif"] = true }; private static Dictionary ProfilRow(long pkId, string libelle) => new() { ["PA_PKID"] = pkId, ["PA_Code"] = "PROFIL", ["PA_Libelle"] = libelle, ["PA_Valeur"] = libelle, ["PA_Actif"] = true }; private static Dictionary DroitRow(long profilId, long moduleId, bool acces) => new() { ["AED_PKID"] = 4001L, ["AED_IDProfil"] = profilId, ["AED_IDModule"] = moduleId, ["AED_Acces"] = acces }; // ===== Fake ===== private sealed class FakeHfsqlConnection : IHfsqlConnection { public FakeHfsqlConnection(HfsqlConnectionState state) => State = state; public HfsqlOptions Options => new(); public HfsqlConnectionState State { get; private set; } public List> UtilisateurRows { get; } = []; public List> ParametreMetierRows { get; } = []; public List> AccesEtDroitRows { get; } = []; public List Queries { get; } = []; public Task OpenAsync(CancellationToken cancellationToken = default) { State = HfsqlConnectionState.Open; return Task.CompletedTask; } public Task CloseAsync() { State = HfsqlConnectionState.Closed; return Task.CompletedTask; } public ValueTask DisposeAsync() => ValueTask.CompletedTask; public Task ExecuteScalarAsync(string sql, IReadOnlyList? parameters = null, CancellationToken cancellationToken = default) => Task.FromResult(null); public Task ExecuteNonQueryAsync(string sql, IReadOnlyList? parameters = null, CancellationToken cancellationToken = default) => Task.FromResult(0); public Task>> QueryAsync(string sql, IReadOnlyList? parameters = null, CancellationToken cancellationToken = default) { Queries.Add(sql); IReadOnlyList> result = sql switch { _ when sql.Contains("FROM Utilisateur", StringComparison.OrdinalIgnoreCase) => UtilisateurRows, _ when sql.Contains("FROM ParametreMetier", StringComparison.OrdinalIgnoreCase) => ParametreMetierRows, _ when sql.Contains("FROM AccesEtDroit", StringComparison.OrdinalIgnoreCase) => AccesEtDroitRows, _ => [] }; return Task.FromResult(result); } public Task> GetColumnsAsync(string tableName, CancellationToken cancellationToken = default) => Task.FromResult>([]); } }