package dev.lions.unionflow.server.resource; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; import dev.lions.unionflow.server.api.dto.common.PagedResponse; import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationResponse; import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationSummaryResponse; import dev.lions.unionflow.server.entity.Organisation; import dev.lions.unionflow.server.service.KeycloakService; import dev.lions.unionflow.server.service.OrganisationService; import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.test.InjectMock; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.security.TestSecurity; import jakarta.inject.Inject; import jakarta.ws.rs.core.Response; import java.security.Principal; import java.util.List; import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; /** * Tests CDI directs pour {@link OrganisationResource} couvrant les branches * inaccessibles via HTTP standard (principal null). * * */ @QuarkusTest @DisplayName("OrganisationResource — branches de couverture manquantes") class OrganisationResourceMissingBranchesTest { @Inject OrganisationResource organisationResource; @InjectMock OrganisationService organisationService; @InjectMock KeycloakService keycloakService; @InjectMock SecurityIdentity securityIdentity; // ========================================================================= // listerMesOrganisations L75 : principal null → email null → liste vide // ========================================================================= @Test @TestSecurity(user = "membre@test.com", roles = {"MEMBRE"}) @DisplayName("listerMesOrganisations — principal null → email null → liste vide (couvre L75)") void listerMesOrganisations_principalNull_retourneListeVide() { when(securityIdentity.getPrincipal()).thenReturn(null); Response response = organisationResource.listerMesOrganisations(); assertThat(response.getStatus()).isEqualTo(200); @SuppressWarnings("unchecked") List body = (List) response.getEntity(); assertThat(body).isEmpty(); } // ========================================================================= // listerOrganisations L172 : ADMIN_ORGANISATION + principal null → chemin global (else) // ========================================================================= @Test @TestSecurity(user = "orgadmin@test.com", roles = {"ADMIN_ORGANISATION"}) @DisplayName("listerOrganisations — ADMIN_ORGANISATION + principal null → chemin global (couvre L172)") void listerOrganisations_adminOrg_principalNull_cheminGlobal() { when(securityIdentity.getRoles()).thenReturn(Set.of("ADMIN_ORGANISATION")); when(securityIdentity.getPrincipal()).thenReturn(null); when(organisationService.listerOrganisationsActives(anyInt(), anyInt())).thenReturn(List.of()); when(organisationService.compterOrganisationsActives()).thenReturn(0L); PagedResponse result = organisationResource.listerOrganisations( 0, 20, null); assertThat(result).isNotNull(); } // ========================================================================= // listerOrganisations L175-180 : ADMIN_ORGANISATION + principal non-null + recherche non-vide // → filtre appliqué sur les organisations (lambda getNom/getNomCourt) // ========================================================================= @Test @TestSecurity(user = "orgadmin@test.com", roles = {"ADMIN_ORGANISATION"}) @DisplayName("listerOrganisations — ADMIN_ORGANISATION + recherche → filtre lambda getNom (couvre L175-180)") void listerOrganisations_adminOrg_avecRecherche_filtreParNom() { Principal principal = () -> "orgadmin@test.com"; when(securityIdentity.getRoles()).thenReturn(Set.of("ADMIN_ORGANISATION")); when(securityIdentity.getPrincipal()).thenReturn(principal); // Organisation dont le nom contient "test" — passera le filtre Organisation org1 = new Organisation(); org1.setId(UUID.randomUUID()); org1.setNom("Organisation Test"); org1.setNomCourt(null); // Organisation dont nomCourt contient "test" — passera le filtre via nomCourt Organisation org2 = new Organisation(); org2.setId(UUID.randomUUID()); org2.setNom(null); org2.setNomCourt("Org Test Court"); // Organisation qui ne correspond pas Organisation org3 = new Organisation(); org3.setId(UUID.randomUUID()); org3.setNom("Autre Association"); org3.setNomCourt("AA"); when(organisationService.listerOrganisationsPourUtilisateur("orgadmin@test.com")) .thenReturn(List.of(org1, org2, org3)); when(organisationService.convertToSummaryResponse(any(Organisation.class))) .thenReturn(new OrganisationSummaryResponse(null, null, null, null, null, null, null, null, null, null, null, null)); // recherche = "test" → filtre les organisations dont nom ou nomCourt contient "test" PagedResponse result = organisationResource.listerOrganisations( 0, 20, "test"); assertThat(result).isNotNull(); // org1 et org2 correspondent, org3 non → 2 résultats assertThat(result.getData()).hasSize(2); } @Test @TestSecurity(user = "orgadmin@test.com", roles = {"ADMIN_ORGANISATION"}) @DisplayName("listerOrganisations — ADMIN_ORGANISATION + recherche → filtre lambda avec nom null et nomCourt null") void listerOrganisations_adminOrg_avecRecherche_nomEtNomCourtNull_filtre() { Principal principal = () -> "orgadmin@test.com"; when(securityIdentity.getRoles()).thenReturn(Set.of("ADMIN_ORGANISATION")); when(securityIdentity.getPrincipal()).thenReturn(principal); // Organisation avec nom=null et nomCourt=null — ne passera pas le filtre Organisation org = new Organisation(); org.setId(UUID.randomUUID()); org.setNom(null); org.setNomCourt(null); when(organisationService.listerOrganisationsPourUtilisateur("orgadmin@test.com")) .thenReturn(List.of(org)); // recherche non vide → filtre → nom null && nomCourt null → aucun résultat PagedResponse result = organisationResource.listerOrganisations( 0, 20, "quelquechose"); assertThat(result).isNotNull(); assertThat(result.getData()).isEmpty(); } // ========================================================================= // listerOrganisations L170 : ADMIN_ORGANISATION + ADMIN → onlyOrgAdmin=false // ========================================================================= @Test @TestSecurity(user = "admin@test.com", roles = {"ADMIN_ORGANISATION", "ADMIN"}) @DisplayName("listerOrganisations — ADMIN_ORGANISATION + ADMIN → onlyOrgAdmin=false, chemin global (couvre L170)") void listerOrganisations_adminOrgPlusAdmin_onlyOrgAdminFalse() { when(securityIdentity.getRoles()).thenReturn(Set.of("ADMIN_ORGANISATION", "ADMIN")); when(organisationService.listerOrganisationsActives(anyInt(), anyInt())).thenReturn(List.of()); when(organisationService.compterOrganisationsActives()).thenReturn(0L); PagedResponse result = organisationResource.listerOrganisations( 0, 20, null); assertThat(result).isNotNull(); } // ========================================================================= // listerOrganisations L171 : ADMIN_ORGANISATION + SUPER_ADMIN → onlyOrgAdmin=false // ========================================================================= @Test @TestSecurity(user = "superadmin@test.com", roles = {"ADMIN_ORGANISATION", "SUPER_ADMIN"}) @DisplayName("listerOrganisations — ADMIN_ORGANISATION + SUPER_ADMIN → onlyOrgAdmin=false (couvre L171)") void listerOrganisations_adminOrgPlusSuperAdmin_onlyOrgAdminFalse() { when(securityIdentity.getRoles()).thenReturn(Set.of("ADMIN_ORGANISATION", "SUPER_ADMIN")); when(organisationService.listerOrganisationsActives(anyInt(), anyInt())).thenReturn(List.of()); when(organisationService.compterOrganisationsActives()).thenReturn(0L); PagedResponse result = organisationResource.listerOrganisations( 0, 20, null); assertThat(result).isNotNull(); } // ========================================================================= // listerOrganisations L188 : onlyOrgAdmin=false + recherche non-null mais blank // → !recherche.trim().isEmpty()=false → else branch // ========================================================================= @Test @TestSecurity(user = "membre@test.com", roles = {"MEMBRE"}) @DisplayName("listerOrganisations — MEMBRE + recherche blank → else if isEmpty()=true → else (couvre L188)") void listerOrganisations_membre_rechercheBlank_elseElse() { when(securityIdentity.getRoles()).thenReturn(Set.of("MEMBRE")); when(organisationService.listerOrganisationsActives(anyInt(), anyInt())).thenReturn(List.of()); when(organisationService.compterOrganisationsActives()).thenReturn(0L); // recherche non-null mais blank → trim().isEmpty()=true → condition false → else PagedResponse result = organisationResource.listerOrganisations( 0, 20, " "); assertThat(result).isNotNull(); } // ========================================================================= // Error cases // ========================================================================= @Test @TestSecurity(user = "membre@test.com", roles = {"MEMBRE"}) @DisplayName("listerMesOrganisations — service lève exception → exception propagée") void listerMesOrganisations_serviceException_propagee() { Principal principal = () -> "membre@test.com"; when(securityIdentity.getPrincipal()).thenReturn(principal); when(organisationService.listerOrganisationsPourUtilisateur(anyString())) .thenThrow(new RuntimeException("Erreur base de données")); org.junit.jupiter.api.Assertions.assertThrows(RuntimeException.class, () -> organisationResource.listerMesOrganisations()); } @Test @TestSecurity(user = "superadmin@test.com", roles = {"SUPER_ADMIN"}) @DisplayName("listerOrganisations — SUPER_ADMIN + service retourne liste vide → résultat non null") void listerOrganisations_superAdmin_listeVide_retourneResultatNonNull() { when(securityIdentity.getRoles()).thenReturn(Set.of("SUPER_ADMIN")); when(organisationService.listerOrganisationsActives(anyInt(), anyInt())).thenReturn(List.of()); when(organisationService.compterOrganisationsActives()).thenReturn(0L); PagedResponse result = organisationResource.listerOrganisations( 0, 20, null); assertThat(result).isNotNull(); assertThat(result.getData()).isEmpty(); } @Test @TestSecurity(user = "orgadmin@test.com", roles = {"ADMIN_ORGANISATION"}) @DisplayName("listerOrganisations — ADMIN_ORGANISATION + service lève exception → exception propagée") void listerOrganisations_adminOrg_serviceException_propagee() { when(securityIdentity.getRoles()).thenReturn(Set.of("ADMIN_ORGANISATION")); Principal principal = () -> "orgadmin@test.com"; when(securityIdentity.getPrincipal()).thenReturn(principal); when(organisationService.listerOrganisationsPourUtilisateur(anyString())) .thenThrow(new RuntimeException("Accès base de données impossible")); org.junit.jupiter.api.Assertions.assertThrows(RuntimeException.class, () -> organisationResource.listerOrganisations(0, 20, null)); } }