Refactoring - Version stable
This commit is contained in:
@@ -118,6 +118,94 @@ class AdresseTest {
|
||||
assertThat(a.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
// ── Branch coverage: getAdresseComplete ────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: only complementAdresse (sb empty at append)")
|
||||
void getAdresseComplete_onlyComplementAdresse() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setComplementAdresse("Bât B");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("Bât B");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: only codePostal (sb empty at append)")
|
||||
void getAdresseComplete_onlyCodePostal() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setCodePostal("75002");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("75002");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: only region (sb empty at append)")
|
||||
void getAdresseComplete_onlyRegion() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setRegion("Bretagne");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("Bretagne");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: only pays (sb empty at append)")
|
||||
void getAdresseComplete_onlyPays() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setPays("France");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("France");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: adresse + codePostal (skip complementAdresse), triggers sb>0 for codePostal")
|
||||
void getAdresseComplete_adresseAndCodePostal() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setAdresse("2 rue X");
|
||||
a.setCodePostal("13000");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("2 rue X, 13000");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: codePostal + ville (sb>0 for ville space separator)")
|
||||
void getAdresseComplete_codePostalAndVille() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setCodePostal("69001");
|
||||
a.setVille("Lyon");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("69001 Lyon");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: adresse with empty string fields ignored")
|
||||
void getAdresseComplete_emptyStringFieldsIgnored() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setAdresse("3 rue Y");
|
||||
a.setComplementAdresse("");
|
||||
a.setCodePostal("");
|
||||
a.setVille("");
|
||||
a.setRegion("");
|
||||
a.setPays("");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("3 rue Y");
|
||||
}
|
||||
|
||||
// ── Branch coverage manquante ──────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* L107 branch manquante : adresse != null mais adresse.isEmpty() → false (deuxième branche du &&)
|
||||
* → `if (adresse != null && !adresse.isEmpty())` → false (adresse est vide "")
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("getAdresseComplete: adresse = empty string (non null) → ignorée (branche isEmpty)")
|
||||
void getAdresseComplete_adresseEmptyString_ignored() {
|
||||
Adresse a = new Adresse();
|
||||
a.setTypeAdresse("SIEGE");
|
||||
a.setAdresse(""); // non null mais vide → condition !adresse.isEmpty() est false → ignorée
|
||||
a.setVille("Dakar");
|
||||
assertThat(a.getAdresseComplete()).isEqualTo("Dakar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("relations: organisation, membre, evenement")
|
||||
void relations() {
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("ApproverAction")
|
||||
class ApproverActionTest {
|
||||
|
||||
private static TransactionApproval newApproval() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setId(UUID.randomUUID());
|
||||
return ta;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// approve
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("approve: positionne la décision à APPROVED")
|
||||
void approve_setsDecisionApproved() {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setDecision("PENDING");
|
||||
a.approve("Tout est correct");
|
||||
assertThat(a.getDecision()).isEqualTo("APPROVED");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("approve: positionne le commentaire")
|
||||
void approve_setsComment() {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.approve("Approuvé sans réserve");
|
||||
assertThat(a.getComment()).isEqualTo("Approuvé sans réserve");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("approve: positionne decidedAt à une date non nulle")
|
||||
void approve_setsDecidedAt() {
|
||||
LocalDateTime before = LocalDateTime.now().minusSeconds(1);
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.approve("OK");
|
||||
assertThat(a.getDecidedAt()).isNotNull().isAfterOrEqualTo(before);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// reject
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("reject: positionne la décision à REJECTED")
|
||||
void reject_setsDecisionRejected() {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setDecision("PENDING");
|
||||
a.reject("Montant trop élevé");
|
||||
assertThat(a.getDecision()).isEqualTo("REJECTED");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("reject: positionne la raison dans le commentaire")
|
||||
void reject_setsReason() {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.reject("Justificatif manquant");
|
||||
assertThat(a.getComment()).isEqualTo("Justificatif manquant");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("reject: positionne decidedAt à une date non nulle")
|
||||
void reject_setsDecidedAt() {
|
||||
LocalDateTime before = LocalDateTime.now().minusSeconds(1);
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.reject("Raison");
|
||||
assertThat(a.getDecidedAt()).isNotNull().isAfterOrEqualTo(before);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// onCreate (réflexion)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise decision à PENDING si null")
|
||||
void onCreate_initializesDecisionIfNull() throws Exception {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setDecision(null);
|
||||
|
||||
Method onCreate = ApproverAction.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(a);
|
||||
|
||||
assertThat(a.getDecision()).isEqualTo("PENDING");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: ne remplace pas decision si déjà renseigné")
|
||||
void onCreate_doesNotOverrideDecision() throws Exception {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setDecision("APPROVED");
|
||||
|
||||
Method onCreate = ApproverAction.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(a);
|
||||
|
||||
assertThat(a.getDecision()).isEqualTo("APPROVED");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// builder
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("builder: positionne tous les champs correctement")
|
||||
void builder_setsAllFields() {
|
||||
TransactionApproval approval = newApproval();
|
||||
UUID approverId = UUID.randomUUID();
|
||||
LocalDateTime decidedAt = LocalDateTime.of(2026, 3, 20, 14, 30);
|
||||
|
||||
ApproverAction a = ApproverAction.builder()
|
||||
.approval(approval)
|
||||
.approverId(approverId)
|
||||
.approverName("Mamadou Diallo")
|
||||
.approverRole("TRESORIER")
|
||||
.decision("APPROVED")
|
||||
.comment("Dépense justifiée")
|
||||
.decidedAt(decidedAt)
|
||||
.build();
|
||||
|
||||
assertThat(a.getApproval()).isSameAs(approval);
|
||||
assertThat(a.getApproverId()).isEqualTo(approverId);
|
||||
assertThat(a.getApproverName()).isEqualTo("Mamadou Diallo");
|
||||
assertThat(a.getApproverRole()).isEqualTo("TRESORIER");
|
||||
assertThat(a.getDecision()).isEqualTo("APPROVED");
|
||||
assertThat(a.getComment()).isEqualTo("Dépense justifiée");
|
||||
assertThat(a.getDecidedAt()).isEqualTo(decidedAt);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getters / setters
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("getters/setters: tous les champs accessibles en lecture/écriture")
|
||||
void gettersSetters_workCorrectly() {
|
||||
TransactionApproval approval = newApproval();
|
||||
UUID approverId = UUID.randomUUID();
|
||||
LocalDateTime decidedAt = LocalDateTime.now();
|
||||
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setApproval(approval);
|
||||
a.setApproverId(approverId);
|
||||
a.setApproverName("Aïssata Koné");
|
||||
a.setApproverRole("VICE_PRESIDENT");
|
||||
a.setDecision("REJECTED");
|
||||
a.setComment("Documents insuffisants");
|
||||
a.setDecidedAt(decidedAt);
|
||||
|
||||
assertThat(a.getApproval()).isSameAs(approval);
|
||||
assertThat(a.getApproverId()).isEqualTo(approverId);
|
||||
assertThat(a.getApproverName()).isEqualTo("Aïssata Koné");
|
||||
assertThat(a.getApproverRole()).isEqualTo("VICE_PRESIDENT");
|
||||
assertThat(a.getDecision()).isEqualTo("REJECTED");
|
||||
assertThat(a.getComment()).isEqualTo("Documents insuffisants");
|
||||
assertThat(a.getDecidedAt()).isEqualTo(decidedAt);
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,20 @@ class AyantDroitTest {
|
||||
assertThat(a.isCouvertAujourdhui()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCouvertAujourdhui: false si actif=false même avec dates valides")
|
||||
void isCouvertAujourdhui_false_whenActifFalse() {
|
||||
AyantDroit a = new AyantDroit();
|
||||
a.setMembreOrganisation(newMembreOrganisation());
|
||||
a.setPrenom("X");
|
||||
a.setNom("Y");
|
||||
a.setLienParente(LienParente.ENFANT);
|
||||
a.setDateDebutCouverture(LocalDate.now().minusDays(1));
|
||||
a.setDateFinCouverture(null);
|
||||
a.setActif(false);
|
||||
assertThat(a.isCouvertAujourdhui()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCouvertAujourdhui: true si actif et dates couvrent aujourd'hui")
|
||||
void isCouvertAujourdhui_true() {
|
||||
@@ -151,4 +165,62 @@ class AyantDroitTest {
|
||||
a.setLienParente(LienParente.ENFANT);
|
||||
assertThat(a.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
// ── Branch coverage manquantes ─────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("isCouvertAujourdhui: dateDebutCouverture null → condition L85 null short-circuit → continue (branche dateDebutCouverture==null)")
|
||||
void isCouvertAujourdhui_debutNull_branchNullShortCircuit() {
|
||||
AyantDroit a = new AyantDroit();
|
||||
a.setMembreOrganisation(newMembreOrganisation());
|
||||
a.setPrenom("X");
|
||||
a.setNom("Y");
|
||||
a.setLienParente(LienParente.ENFANT);
|
||||
a.setDateDebutCouverture(null); // null → dateDebutCouverture != null = false → skip at L85
|
||||
a.setDateFinCouverture(null); // null → dateFinCouverture != null = false → skip at L87
|
||||
a.setActif(true);
|
||||
// Pas de retour false aux conditions → return Boolean.TRUE.equals(true) = true
|
||||
assertThat(a.isCouvertAujourdhui()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* L85 branch manquante : dateDebutCouverture != null mais today >= dateDebutCouverture
|
||||
* (today is NOT before → condition false)
|
||||
* → couvre la branche `dateDebutCouverture != null && today.isBefore(...) → false`
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isCouvertAujourdhui: dateDebutCouverture non null mais pas avant → continue (branche false)")
|
||||
void isCouvertAujourdhui_debutNonNull_nonBefore_continueToActif() {
|
||||
AyantDroit a = new AyantDroit();
|
||||
a.setMembreOrganisation(newMembreOrganisation());
|
||||
a.setPrenom("X");
|
||||
a.setNom("Y");
|
||||
a.setLienParente(LienParente.ENFANT);
|
||||
// dateDebutCouverture est dans le passé → today.isBefore(debutCouverture) est false
|
||||
a.setDateDebutCouverture(LocalDate.now().minusDays(5));
|
||||
a.setDateFinCouverture(null);
|
||||
a.setActif(true);
|
||||
// Ne retourne pas false à la première condition → continue et retourne true (actif=true)
|
||||
assertThat(a.isCouvertAujourdhui()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* L87 branch manquante : dateFinCouverture != null mais today <= dateFinCouverture
|
||||
* (today is NOT after → condition false)
|
||||
* → couvre la branche `dateFinCouverture != null && today.isAfter(...) → false`
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isCouvertAujourdhui: dateFinCouverture non null mais pas encore dépassée → continue (branche false)")
|
||||
void isCouvertAujourdhui_finNonNull_nonAfter_continueToActif() {
|
||||
AyantDroit a = new AyantDroit();
|
||||
a.setMembreOrganisation(newMembreOrganisation());
|
||||
a.setPrenom("X");
|
||||
a.setNom("Y");
|
||||
a.setLienParente(LienParente.ENFANT);
|
||||
a.setDateDebutCouverture(LocalDate.now().minusDays(5));
|
||||
// dateFinCouverture dans le futur → today.isAfter(finCouverture) est false → continue
|
||||
a.setDateFinCouverture(LocalDate.now().plusDays(5));
|
||||
a.setActif(true);
|
||||
assertThat(a.isCouvertAujourdhui()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("BudgetLine")
|
||||
class BudgetLineTest {
|
||||
|
||||
private static Budget newBudget() {
|
||||
Budget b = new Budget();
|
||||
b.setId(UUID.randomUUID());
|
||||
return b;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getRealizationRate
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("getRealizationRate: amountPlanned == 0 renvoie 0.0")
|
||||
void getRealizationRate_zeroPlan_returns0() {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(BigDecimal.ZERO);
|
||||
line.setAmountRealized(new BigDecimal("100.00"));
|
||||
assertThat(line.getRealizationRate()).isEqualTo(0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getRealizationRate: 75 réalisé / 100 prévu = 75%")
|
||||
void getRealizationRate_withValues_returnsRatio() {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(new BigDecimal("100.00"));
|
||||
line.setAmountRealized(new BigDecimal("75.00"));
|
||||
assertThat(line.getRealizationRate()).isEqualTo(75.0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getVariance
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("getVariance: positif quand réalisé > prévu")
|
||||
void getVariance_positive_whenOver() {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(new BigDecimal("100.00"));
|
||||
line.setAmountRealized(new BigDecimal("120.00"));
|
||||
assertThat(line.getVariance()).isEqualByComparingTo("20.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getVariance: négatif quand réalisé < prévu")
|
||||
void getVariance_negative_whenUnder() {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(new BigDecimal("100.00"));
|
||||
line.setAmountRealized(new BigDecimal("80.00"));
|
||||
assertThat(line.getVariance()).isEqualByComparingTo("-20.00");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isOverBudget
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isOverBudget: réalisé > prévu renvoie true")
|
||||
void isOverBudget_whenOver_returnsTrue() {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(new BigDecimal("200.00"));
|
||||
line.setAmountRealized(new BigDecimal("201.00"));
|
||||
assertThat(line.isOverBudget()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOverBudget: réalisé <= prévu renvoie false")
|
||||
void isOverBudget_whenNotOver_returnsFalse() {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(new BigDecimal("200.00"));
|
||||
line.setAmountRealized(new BigDecimal("200.00"));
|
||||
assertThat(line.isOverBudget()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// onCreate (réflexion)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise amountRealized à ZERO si null")
|
||||
void onCreate_initializesAmountRealizedIfNull() throws Exception {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountRealized(null);
|
||||
|
||||
Method onCreate = BudgetLine.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(line);
|
||||
|
||||
assertThat(line.getAmountRealized()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: ne remplace pas amountRealized si déjà renseigné")
|
||||
void onCreate_doesNotOverrideAmountRealized() throws Exception {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountRealized(new BigDecimal("350.00"));
|
||||
|
||||
Method onCreate = BudgetLine.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(line);
|
||||
|
||||
assertThat(line.getAmountRealized()).isEqualByComparingTo("350.00");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// builder
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("builder: positionne tous les champs correctement")
|
||||
void builder_setsAllFields() {
|
||||
Budget budget = newBudget();
|
||||
|
||||
BudgetLine line = BudgetLine.builder()
|
||||
.budget(budget)
|
||||
.category("CONTRIBUTIONS")
|
||||
.name("Cotisations membres")
|
||||
.description("Cotisations mensuelles")
|
||||
.amountPlanned(new BigDecimal("50000.00"))
|
||||
.amountRealized(new BigDecimal("42000.00"))
|
||||
.notes("Léger retard de collecte")
|
||||
.build();
|
||||
|
||||
assertThat(line.getBudget()).isSameAs(budget);
|
||||
assertThat(line.getCategory()).isEqualTo("CONTRIBUTIONS");
|
||||
assertThat(line.getName()).isEqualTo("Cotisations membres");
|
||||
assertThat(line.getDescription()).isEqualTo("Cotisations mensuelles");
|
||||
assertThat(line.getAmountPlanned()).isEqualByComparingTo("50000.00");
|
||||
assertThat(line.getAmountRealized()).isEqualByComparingTo("42000.00");
|
||||
assertThat(line.getNotes()).isEqualTo("Léger retard de collecte");
|
||||
}
|
||||
}
|
||||
319
src/test/java/dev/lions/unionflow/server/entity/BudgetTest.java
Normal file
319
src/test/java/dev/lions/unionflow/server/entity/BudgetTest.java
Normal file
@@ -0,0 +1,319 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("Budget")
|
||||
class BudgetTest {
|
||||
|
||||
private static Organisation newOrganisation() {
|
||||
Organisation o = new Organisation();
|
||||
o.setId(UUID.randomUUID());
|
||||
return o;
|
||||
}
|
||||
|
||||
private static BudgetLine newLine(BigDecimal planned, BigDecimal realized) {
|
||||
BudgetLine line = new BudgetLine();
|
||||
line.setAmountPlanned(planned);
|
||||
line.setAmountRealized(realized);
|
||||
return line;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getRealizationRate
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("getRealizationRate: totalPlanned == 0 renvoie 0.0")
|
||||
void getRealizationRate_zeroPlan_returns0() {
|
||||
Budget b = new Budget();
|
||||
b.setTotalPlanned(BigDecimal.ZERO);
|
||||
b.setTotalRealized(new BigDecimal("500.00"));
|
||||
assertThat(b.getRealizationRate()).isEqualTo(0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getRealizationRate: 500 réalisé / 1000 prévu = 50%")
|
||||
void getRealizationRate_withPlan_returnsRatio() {
|
||||
Budget b = new Budget();
|
||||
b.setTotalPlanned(new BigDecimal("1000.00"));
|
||||
b.setTotalRealized(new BigDecimal("500.00"));
|
||||
assertThat(b.getRealizationRate()).isEqualTo(50.0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getVariance
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("getVariance: renvoie réalisé - prévu")
|
||||
void getVariance_returnsRealized_minus_planned() {
|
||||
Budget b = new Budget();
|
||||
b.setTotalPlanned(new BigDecimal("1000.00"));
|
||||
b.setTotalRealized(new BigDecimal("1200.00"));
|
||||
assertThat(b.getVariance()).isEqualByComparingTo("200.00");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isOverBudget
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isOverBudget: réalisé > prévu renvoie true")
|
||||
void isOverBudget_whenOver_returnsTrue() {
|
||||
Budget b = new Budget();
|
||||
b.setTotalPlanned(new BigDecimal("1000.00"));
|
||||
b.setTotalRealized(new BigDecimal("1001.00"));
|
||||
assertThat(b.isOverBudget()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOverBudget: réalisé == prévu renvoie false")
|
||||
void isOverBudget_whenEqual_returnsFalse() {
|
||||
Budget b = new Budget();
|
||||
b.setTotalPlanned(new BigDecimal("1000.00"));
|
||||
b.setTotalRealized(new BigDecimal("1000.00"));
|
||||
assertThat(b.isOverBudget()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isActive
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive: statut ACTIVE renvoie true")
|
||||
void isActive_active_returnsTrue() {
|
||||
Budget b = new Budget();
|
||||
b.setStatus("ACTIVE");
|
||||
assertThat(b.isActive()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive: statut DRAFT renvoie false")
|
||||
void isActive_draft_returnsFalse() {
|
||||
Budget b = new Budget();
|
||||
b.setStatus("DRAFT");
|
||||
assertThat(b.isActive()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isCurrentPeriod
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isCurrentPeriod: aujourd'hui dans la période renvoie true")
|
||||
void isCurrentPeriod_duringPeriod_returnsTrue() {
|
||||
Budget b = new Budget();
|
||||
b.setStartDate(LocalDate.now().minusDays(5));
|
||||
b.setEndDate(LocalDate.now().plusDays(5));
|
||||
assertThat(b.isCurrentPeriod()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCurrentPeriod: période terminée renvoie false")
|
||||
void isCurrentPeriod_afterPeriod_returnsFalse() {
|
||||
Budget b = new Budget();
|
||||
b.setStartDate(LocalDate.now().minusDays(10));
|
||||
b.setEndDate(LocalDate.now().minusDays(1));
|
||||
assertThat(b.isCurrentPeriod()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCurrentPeriod: période pas encore commencée renvoie false")
|
||||
void isCurrentPeriod_beforePeriod_returnsFalse() {
|
||||
Budget b = new Budget();
|
||||
b.setStartDate(LocalDate.now().plusDays(1));
|
||||
b.setEndDate(LocalDate.now().plusDays(10));
|
||||
assertThat(b.isCurrentPeriod()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// addLine / removeLine / recalculateTotals
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("addLine: ajoute la ligne, lie le budget parent et recalcule les totaux")
|
||||
void addLine_addsLineAndRecalculates() {
|
||||
Budget b = Budget.builder()
|
||||
.name("Budget Test")
|
||||
.organisation(newOrganisation())
|
||||
.period("ANNUAL")
|
||||
.year(2026)
|
||||
.status("DRAFT")
|
||||
.createdById(UUID.randomUUID())
|
||||
.createdAtBudget(LocalDateTime.now())
|
||||
.startDate(LocalDate.of(2026, 1, 1))
|
||||
.endDate(LocalDate.of(2026, 12, 31))
|
||||
.build();
|
||||
|
||||
BudgetLine line = newLine(new BigDecimal("500.00"), new BigDecimal("200.00"));
|
||||
b.addLine(line);
|
||||
|
||||
assertThat(b.getLines()).hasSize(1);
|
||||
assertThat(line.getBudget()).isSameAs(b);
|
||||
assertThat(b.getTotalPlanned()).isEqualByComparingTo("500.00");
|
||||
assertThat(b.getTotalRealized()).isEqualByComparingTo("200.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("removeLine: retire la ligne, délie le budget parent et recalcule les totaux")
|
||||
void removeLine_removesAndRecalculates() {
|
||||
Budget b = Budget.builder()
|
||||
.name("Budget Test")
|
||||
.organisation(newOrganisation())
|
||||
.period("ANNUAL")
|
||||
.year(2026)
|
||||
.status("DRAFT")
|
||||
.createdById(UUID.randomUUID())
|
||||
.createdAtBudget(LocalDateTime.now())
|
||||
.startDate(LocalDate.of(2026, 1, 1))
|
||||
.endDate(LocalDate.of(2026, 12, 31))
|
||||
.build();
|
||||
|
||||
BudgetLine line1 = newLine(new BigDecimal("300.00"), new BigDecimal("100.00"));
|
||||
BudgetLine line2 = newLine(new BigDecimal("200.00"), new BigDecimal("50.00"));
|
||||
b.addLine(line1);
|
||||
b.addLine(line2);
|
||||
assertThat(b.getLines()).hasSize(2);
|
||||
|
||||
b.removeLine(line1);
|
||||
|
||||
assertThat(b.getLines()).hasSize(1);
|
||||
assertThat(line1.getBudget()).isNull();
|
||||
assertThat(b.getTotalPlanned()).isEqualByComparingTo("200.00");
|
||||
assertThat(b.getTotalRealized()).isEqualByComparingTo("50.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("recalculateTotals: somme correcte avec plusieurs lignes")
|
||||
void recalculateTotals_multipleLines_sumsCorrectly() {
|
||||
Budget b = Budget.builder()
|
||||
.name("Budget Multi")
|
||||
.organisation(newOrganisation())
|
||||
.period("ANNUAL")
|
||||
.year(2026)
|
||||
.status("DRAFT")
|
||||
.createdById(UUID.randomUUID())
|
||||
.createdAtBudget(LocalDateTime.now())
|
||||
.startDate(LocalDate.of(2026, 1, 1))
|
||||
.endDate(LocalDate.of(2026, 12, 31))
|
||||
.build();
|
||||
|
||||
b.addLine(newLine(new BigDecimal("100.00"), new BigDecimal("80.00")));
|
||||
b.addLine(newLine(new BigDecimal("200.00"), new BigDecimal("150.00")));
|
||||
b.addLine(newLine(new BigDecimal("300.00"), new BigDecimal("320.00")));
|
||||
|
||||
assertThat(b.getTotalPlanned()).isEqualByComparingTo("600.00");
|
||||
assertThat(b.getTotalRealized()).isEqualByComparingTo("550.00");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// onCreate (réflexion)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les champs null (createdAtBudget, currency, status, totalPlanned, totalRealized)")
|
||||
void onCreate_initializesNullFields() throws Exception {
|
||||
Budget b = new Budget();
|
||||
b.setCreatedAtBudget(null);
|
||||
b.setCurrency(null);
|
||||
b.setStatus(null);
|
||||
b.setTotalPlanned(null);
|
||||
b.setTotalRealized(null);
|
||||
|
||||
Method onCreate = Budget.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(b);
|
||||
|
||||
assertThat(b.getCreatedAtBudget()).isNotNull();
|
||||
assertThat(b.getCurrency()).isEqualTo("XOF");
|
||||
assertThat(b.getStatus()).isEqualTo("DRAFT");
|
||||
assertThat(b.getTotalPlanned()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(b.getTotalRealized()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: ne remplace pas les champs déjà renseignés")
|
||||
void onCreate_doesNotOverrideExistingFields() throws Exception {
|
||||
LocalDateTime existingDate = LocalDateTime.of(2025, 6, 15, 10, 0);
|
||||
Budget b = new Budget();
|
||||
b.setCreatedAtBudget(existingDate);
|
||||
b.setCurrency("EUR");
|
||||
b.setStatus("ACTIVE");
|
||||
b.setTotalPlanned(new BigDecimal("5000.00"));
|
||||
b.setTotalRealized(new BigDecimal("2500.00"));
|
||||
|
||||
Method onCreate = Budget.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(b);
|
||||
|
||||
assertThat(b.getCreatedAtBudget()).isEqualTo(existingDate);
|
||||
assertThat(b.getCurrency()).isEqualTo("EUR");
|
||||
assertThat(b.getStatus()).isEqualTo("ACTIVE");
|
||||
assertThat(b.getTotalPlanned()).isEqualByComparingTo("5000.00");
|
||||
assertThat(b.getTotalRealized()).isEqualByComparingTo("2500.00");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// builder
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("builder: crée un objet complet avec tous les champs")
|
||||
void builder_createsComplete() {
|
||||
UUID createdById = UUID.randomUUID();
|
||||
UUID approvedById = UUID.randomUUID();
|
||||
Organisation org = newOrganisation();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime approvedAt = now.plusDays(1);
|
||||
LocalDate start = LocalDate.of(2026, 1, 1);
|
||||
LocalDate end = LocalDate.of(2026, 12, 31);
|
||||
|
||||
Budget b = Budget.builder()
|
||||
.name("Budget Annuel 2026")
|
||||
.description("Description du budget")
|
||||
.organisation(org)
|
||||
.period("ANNUAL")
|
||||
.year(2026)
|
||||
.month(null)
|
||||
.status("ACTIVE")
|
||||
.totalPlanned(new BigDecimal("1000000.00"))
|
||||
.totalRealized(new BigDecimal("500000.00"))
|
||||
.currency("XOF")
|
||||
.createdById(createdById)
|
||||
.createdAtBudget(now)
|
||||
.approvedAt(approvedAt)
|
||||
.approvedById(approvedById)
|
||||
.startDate(start)
|
||||
.endDate(end)
|
||||
.metadata("{\"note\":\"test\"}")
|
||||
.build();
|
||||
|
||||
assertThat(b.getName()).isEqualTo("Budget Annuel 2026");
|
||||
assertThat(b.getDescription()).isEqualTo("Description du budget");
|
||||
assertThat(b.getOrganisation()).isSameAs(org);
|
||||
assertThat(b.getPeriod()).isEqualTo("ANNUAL");
|
||||
assertThat(b.getYear()).isEqualTo(2026);
|
||||
assertThat(b.getMonth()).isNull();
|
||||
assertThat(b.getStatus()).isEqualTo("ACTIVE");
|
||||
assertThat(b.getTotalPlanned()).isEqualByComparingTo("1000000.00");
|
||||
assertThat(b.getTotalRealized()).isEqualByComparingTo("500000.00");
|
||||
assertThat(b.getCurrency()).isEqualTo("XOF");
|
||||
assertThat(b.getCreatedById()).isEqualTo(createdById);
|
||||
assertThat(b.getCreatedAtBudget()).isEqualTo(now);
|
||||
assertThat(b.getApprovedAt()).isEqualTo(approvedAt);
|
||||
assertThat(b.getApprovedById()).isEqualTo(approvedById);
|
||||
assertThat(b.getStartDate()).isEqualTo(start);
|
||||
assertThat(b.getEndDate()).isEqualTo(end);
|
||||
assertThat(b.getMetadata()).isEqualTo("{\"note\":\"test\"}");
|
||||
assertThat(b.getLines()).isNotNull().isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -89,4 +89,38 @@ class CompteWaveTest {
|
||||
c.setNumeroTelephone("+22507000005");
|
||||
assertThat(c.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: environnement null → SANDBOX")
|
||||
void onCreate_environnementNull_defaultsSandbox() {
|
||||
CompteWave c = new CompteWave();
|
||||
c.setStatutCompte(null);
|
||||
c.setEnvironnement(null);
|
||||
c.onCreate();
|
||||
assertThat(c.getEnvironnement()).isEqualTo("SANDBOX");
|
||||
assertThat(c.getStatutCompte()).isEqualTo(StatutCompteWave.NON_VERIFIE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: environnement vide → SANDBOX")
|
||||
void onCreate_environnementEmpty_defaultsSandbox() {
|
||||
CompteWave c = new CompteWave();
|
||||
c.setEnvironnement("");
|
||||
c.onCreate();
|
||||
assertThat(c.getEnvironnement()).isEqualTo("SANDBOX");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: statutCompte et environnement déjà définis → conservés (branches false)")
|
||||
void onCreate_allDejaDefinis_conservesValues() {
|
||||
// Valeurs déjà définies → conservées sans modification
|
||||
CompteWave c = new CompteWave();
|
||||
c.setStatutCompte(StatutCompteWave.VERIFIE);
|
||||
c.setEnvironnement("PRODUCTION");
|
||||
|
||||
c.onCreate();
|
||||
|
||||
assertThat(c.getStatutCompte()).isEqualTo(StatutCompteWave.VERIFIE);
|
||||
assertThat(c.getEnvironnement()).isEqualTo("PRODUCTION");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,43 @@ class ConfigurationWaveTest {
|
||||
assertThat(c.getEnvironnement()).isEqualTo("COMMON");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate initialise typeValeur et environnement si vide")
|
||||
void onCreate_initialiseChamps_empty() throws Exception {
|
||||
ConfigurationWave c = new ConfigurationWave();
|
||||
c.setCle("k2");
|
||||
c.setTypeValeur("");
|
||||
c.setEnvironnement("");
|
||||
Method onCreate = ConfigurationWave.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(c);
|
||||
assertThat(c.getTypeValeur()).isEqualTo("STRING");
|
||||
assertThat(c.getEnvironnement()).isEqualTo("COMMON");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: typeValeur et environnement déjà renseignés → non écrasés")
|
||||
void onCreate_existingValues_notOverwritten() throws Exception {
|
||||
ConfigurationWave c = new ConfigurationWave();
|
||||
c.setCle("k3");
|
||||
c.setTypeValeur("NUMBER");
|
||||
c.setEnvironnement("PRODUCTION");
|
||||
Method onCreate = ConfigurationWave.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(c);
|
||||
assertThat(c.getTypeValeur()).isEqualTo("NUMBER");
|
||||
assertThat(c.getEnvironnement()).isEqualTo("PRODUCTION");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEncryptee: false si typeValeur null")
|
||||
void isEncryptee_nullTypeValeur_returnsFalse() {
|
||||
ConfigurationWave c = new ConfigurationWave();
|
||||
c.setCle("x");
|
||||
c.setTypeValeur(null);
|
||||
assertThat(c.isEncryptee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
|
||||
@DisplayName("Conversation")
|
||||
class ConversationTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("getters/setters de base")
|
||||
void gettersSetters() {
|
||||
Conversation c = new Conversation();
|
||||
c.setName("Groupe Test");
|
||||
c.setDescription("Description groupe");
|
||||
c.setType(ConversationType.GROUP);
|
||||
c.setIsMuted(false);
|
||||
c.setIsPinned(true);
|
||||
c.setIsArchived(false);
|
||||
|
||||
assertThat(c.getName()).isEqualTo("Groupe Test");
|
||||
assertThat(c.getDescription()).isEqualTo("Description groupe");
|
||||
assertThat(c.getType()).isEqualTo(ConversationType.GROUP);
|
||||
assertThat(c.getIsMuted()).isFalse();
|
||||
assertThat(c.getIsPinned()).isTrue();
|
||||
assertThat(c.getIsArchived()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onUpdate (PreUpdate) - met à jour updatedAt via réflexion")
|
||||
void onUpdate_setsUpdatedAt() throws Exception {
|
||||
Conversation c = new Conversation();
|
||||
assertThat(c.getUpdatedAt()).isNull();
|
||||
|
||||
Method onUpdate = Conversation.class.getDeclaredMethod("onUpdate");
|
||||
onUpdate.setAccessible(true);
|
||||
|
||||
LocalDateTime before = LocalDateTime.now().minusSeconds(1);
|
||||
onUpdate.invoke(c);
|
||||
LocalDateTime after = LocalDateTime.now().plusSeconds(1);
|
||||
|
||||
assertThat(c.getUpdatedAt()).isNotNull();
|
||||
assertThat(c.getUpdatedAt()).isAfter(before);
|
||||
assertThat(c.getUpdatedAt()).isBefore(after);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onUpdate appelé deux fois met à jour updatedAt à chaque fois")
|
||||
void onUpdate_calledTwice_updatesEachTime() throws Exception {
|
||||
Conversation c = new Conversation();
|
||||
|
||||
Method onUpdate = Conversation.class.getDeclaredMethod("onUpdate");
|
||||
onUpdate.setAccessible(true);
|
||||
|
||||
onUpdate.invoke(c);
|
||||
LocalDateTime first = c.getUpdatedAt();
|
||||
|
||||
// petit délai pour différencier les timestamps
|
||||
Thread.sleep(5);
|
||||
|
||||
onUpdate.invoke(c);
|
||||
LocalDateTime second = c.getUpdatedAt();
|
||||
|
||||
assertThat(second).isAfterOrEqualTo(first);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("participants initialisé à liste vide")
|
||||
void participants_initializedEmpty() {
|
||||
Conversation c = new Conversation();
|
||||
assertThat(c.getParticipants()).isNotNull().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("messages initialisé à liste vide")
|
||||
void messages_initializedEmpty() {
|
||||
Conversation c = new Conversation();
|
||||
assertThat(c.getMessages()).isNotNull().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isMuted et isPinned et isArchived défaut false")
|
||||
void defaultFlags_areFalse() {
|
||||
Conversation c = new Conversation();
|
||||
assertThat(c.getIsMuted()).isFalse();
|
||||
assertThat(c.getIsPinned()).isFalse();
|
||||
assertThat(c.getIsArchived()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -142,4 +142,79 @@ class CotisationTest {
|
||||
c.setAnnee(2025);
|
||||
assertThat(c.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getMontantRestant: ZERO si montantDu null")
|
||||
void getMontantRestant_montantDuNull_returnsZero() {
|
||||
Cotisation c = new Cotisation();
|
||||
c.setMontantPaye(new BigDecimal("50.00"));
|
||||
// montantDu = null
|
||||
assertThat(c.getMontantRestant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnRetard: false si dateEcheance null")
|
||||
void isEnRetard_echeanceNull_returnsFalse() {
|
||||
Cotisation c = new Cotisation();
|
||||
c.setMontantDu(new BigDecimal("100.00"));
|
||||
c.setMontantPaye(BigDecimal.ZERO);
|
||||
// dateEcheance = null
|
||||
assertThat(c.isEnRetard()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: numeroReference déjà défini → conservé (branche false)")
|
||||
void onCreate_numeroReferenceDejaDefini_conserve() {
|
||||
// numeroReference déjà défini → non écrasé par onCreate
|
||||
Cotisation c = new Cotisation();
|
||||
c.setNumeroReference("COT-EXISTANT-001");
|
||||
c.setCodeDevise("XOF");
|
||||
c.setStatut("EN_ATTENTE");
|
||||
c.setMontantPaye(BigDecimal.ZERO);
|
||||
c.setNombreRappels(0);
|
||||
c.setRecurrente(false);
|
||||
|
||||
c.onCreate();
|
||||
|
||||
// numeroReference doit rester inchangé
|
||||
assertThat(c.getNumeroReference()).isEqualTo("COT-EXISTANT-001");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: numeroReference vide (empty string) → généré (branche isEmpty)")
|
||||
void onCreate_emptyNumeroReference_generated() throws Exception {
|
||||
Cotisation c = new Cotisation();
|
||||
c.setNumeroReference(""); // non null mais vide → isEmpty() est true → doit générer
|
||||
c.setCodeDevise("XOF");
|
||||
c.setStatut("EN_ATTENTE");
|
||||
c.setMontantPaye(BigDecimal.ZERO);
|
||||
c.setNombreRappels(0);
|
||||
c.setRecurrente(false);
|
||||
|
||||
java.lang.reflect.Method onCreate = Cotisation.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(c);
|
||||
|
||||
assertThat(c.getNumeroReference()).isNotEmpty().startsWith("COT-");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les défauts si null")
|
||||
void onCreate_setsDefaults() {
|
||||
Cotisation c = new Cotisation();
|
||||
// Force null pour couvrir toutes les branches de initialisation
|
||||
c.setNumeroReference(null);
|
||||
c.setCodeDevise(null);
|
||||
c.setStatut(null);
|
||||
c.setMontantPaye(null);
|
||||
c.setNombreRappels(null);
|
||||
c.setRecurrente(null);
|
||||
c.onCreate();
|
||||
assertThat(c.getNumeroReference()).isNotNull().startsWith("COT-");
|
||||
assertThat(c.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(c.getStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(c.getMontantPaye()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(c.getNombreRappels()).isEqualTo(0);
|
||||
assertThat(c.getRecurrente()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests de couverture complémentaires pour DemandeAdhesion.
|
||||
* Couvre les branches manquantes de isPayeeIntegralement().
|
||||
*/
|
||||
@DisplayName("DemandeAdhesion - couverture complémentaire")
|
||||
class DemandeAdhesionCoverageTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne false quand montantPaye est null")
|
||||
void isPayeeIntegralement_nullMontantPaye_returnsFalse() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(new BigDecimal("5000.00"));
|
||||
d.setMontantPaye(null);
|
||||
assertThat(d.isPayeeIntegralement()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne true quand montantPaye > fraisAdhesion (overpayment)")
|
||||
void isPayeeIntegralement_overpayment_returnsTrue() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(new BigDecimal("5000.00"));
|
||||
d.setMontantPaye(new BigDecimal("6000.00"));
|
||||
assertThat(d.isPayeeIntegralement()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne true quand fraisAdhesion est zero et montantPaye est zero")
|
||||
void isPayeeIntegralement_zeroFraisZeroMontant_returnsTrue() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(BigDecimal.ZERO);
|
||||
d.setMontantPaye(BigDecimal.ZERO);
|
||||
assertThat(d.isPayeeIntegralement()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne false quand les deux champs sont null")
|
||||
void isPayeeIntegralement_bothNull_returnsFalse() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(null);
|
||||
d.setMontantPaye(null);
|
||||
assertThat(d.isPayeeIntegralement()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnAttente retourne false pour statut ANNULEE")
|
||||
void isEnAttente_annulee_returnsFalse() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setStatut("ANNULEE");
|
||||
assertThat(d.isEnAttente()).isFalse();
|
||||
assertThat(d.isApprouvee()).isFalse();
|
||||
assertThat(d.isRejetee()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -91,4 +91,124 @@ class DemandeAdhesionTest {
|
||||
d.setOrganisation(newOrganisation());
|
||||
assertThat(d.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isApprouvee retourne true pour statut APPROUVEE")
|
||||
void isApprouvee_approuvee_returnsTrue() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setStatut("APPROUVEE");
|
||||
assertThat(d.isApprouvee()).isTrue();
|
||||
assertThat(d.isRejetee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isRejetee retourne true pour statut REJETEE")
|
||||
void isRejetee_rejetee_returnsTrue() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setStatut("REJETEE");
|
||||
assertThat(d.isRejetee()).isTrue();
|
||||
assertThat(d.isApprouvee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("genererNumeroReference retourne un code non vide")
|
||||
void genererNumeroReference_returnsNonEmpty() {
|
||||
String ref = DemandeAdhesion.genererNumeroReference();
|
||||
assertThat(ref).isNotNull().isNotEmpty().startsWith("ADH-");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise tous les défauts si null")
|
||||
void onCreate_setsDefaults() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
// Les champs @Builder.Default sont déjà initialisés — les forcer à null pour tester les branches true
|
||||
d.setDateDemande(null);
|
||||
d.setStatut(null);
|
||||
d.setCodeDevise(null);
|
||||
d.setFraisAdhesion(null);
|
||||
d.setMontantPaye(null);
|
||||
// numeroReference est null par défaut (pas de @Builder.Default)
|
||||
d.onCreate();
|
||||
assertThat(d.getDateDemande()).isNotNull();
|
||||
assertThat(d.getStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(d.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(d.getFraisAdhesion()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(d.getMontantPaye()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(d.getNumeroReference()).isNotNull().startsWith("ADH-");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: ne modifie pas les champs déjà initialisés")
|
||||
void onCreate_preservesExistingValues() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
LocalDateTime specificDate = LocalDateTime.of(2024, 1, 15, 10, 30);
|
||||
d.setDateDemande(specificDate);
|
||||
d.setStatut("APPROUVEE");
|
||||
d.setCodeDevise("EUR");
|
||||
d.setFraisAdhesion(BigDecimal.valueOf(100));
|
||||
d.setMontantPaye(BigDecimal.valueOf(50));
|
||||
d.setNumeroReference("ADH-CUSTOM-001");
|
||||
|
||||
d.onCreate();
|
||||
|
||||
assertThat(d.getDateDemande()).isEqualTo(specificDate);
|
||||
assertThat(d.getStatut()).isEqualTo("APPROUVEE");
|
||||
assertThat(d.getCodeDevise()).isEqualTo("EUR");
|
||||
assertThat(d.getFraisAdhesion()).isEqualByComparingTo(BigDecimal.valueOf(100));
|
||||
assertThat(d.getMontantPaye()).isEqualByComparingTo(BigDecimal.valueOf(50));
|
||||
assertThat(d.getNumeroReference()).isEqualTo("ADH-CUSTOM-001");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: génère une référence si numeroReference est vide")
|
||||
void onCreate_emptyReference_generatesNew() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setNumeroReference(""); // vide → condition isEmpty() == true
|
||||
d.setStatut("EN_ATTENTE");
|
||||
d.setCodeDevise("XOF");
|
||||
d.setFraisAdhesion(BigDecimal.ZERO);
|
||||
d.setMontantPaye(BigDecimal.ZERO);
|
||||
d.setDateDemande(LocalDateTime.now());
|
||||
|
||||
d.onCreate();
|
||||
|
||||
assertThat(d.getNumeroReference()).isNotEmpty().startsWith("ADH-");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnAttente retourne true pour statut EN_ATTENTE")
|
||||
void isEnAttente_retournsTrue() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setStatut("EN_ATTENTE");
|
||||
assertThat(d.isEnAttente()).isTrue();
|
||||
assertThat(d.isApprouvee()).isFalse();
|
||||
assertThat(d.isRejetee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne true quand montantPaye >= fraisAdhesion")
|
||||
void isPayeeIntegralement_paymentComplete_returnsTrue() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(new BigDecimal("5000.00"));
|
||||
d.setMontantPaye(new BigDecimal("5000.00"));
|
||||
assertThat(d.isPayeeIntegralement()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne false quand montantPaye < fraisAdhesion")
|
||||
void isPayeeIntegralement_paymentIncomplete_returnsFalse() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(new BigDecimal("5000.00"));
|
||||
d.setMontantPaye(new BigDecimal("2500.00"));
|
||||
assertThat(d.isPayeeIntegralement()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPayeeIntegralement retourne false quand fraisAdhesion est null")
|
||||
void isPayeeIntegralement_nullFrais_returnsFalse() {
|
||||
DemandeAdhesion d = new DemandeAdhesion();
|
||||
d.setFraisAdhesion(null);
|
||||
d.setMontantPaye(BigDecimal.ZERO);
|
||||
assertThat(d.isPayeeIntegralement()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,14 @@ class DocumentTest {
|
||||
assertThat(d.verifierIntegriteSha256("autre")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("verifierIntegriteSha256: false si hashSha256 null")
|
||||
void verifierIntegriteSha256_hashNull_returnsFalse() {
|
||||
Document d = new Document();
|
||||
d.setHashSha256(null);
|
||||
assertThat(d.verifierIntegriteSha256("def456")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getTailleFormatee: B, KB, MB")
|
||||
void getTailleFormatee() {
|
||||
|
||||
@@ -4,10 +4,13 @@ import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("EcritureComptable")
|
||||
@@ -122,4 +125,228 @@ class EcritureComptableTest {
|
||||
e.setJournal(newJournal());
|
||||
assertThat(e.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onUpdate (PreUpdate) calcule les totaux via réflexion")
|
||||
void onUpdate_calculesTotaux() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("L");
|
||||
e.setJournal(newJournal());
|
||||
e.setMontantDebit(BigDecimal.ZERO);
|
||||
e.setMontantCredit(BigDecimal.ZERO);
|
||||
|
||||
LigneEcriture l1 = new LigneEcriture();
|
||||
l1.setMontantDebit(new BigDecimal("200"));
|
||||
l1.setMontantCredit(BigDecimal.ZERO);
|
||||
LigneEcriture l2 = new LigneEcriture();
|
||||
l2.setMontantDebit(BigDecimal.ZERO);
|
||||
l2.setMontantCredit(new BigDecimal("200"));
|
||||
e.getLignes().add(l1);
|
||||
e.getLignes().add(l2);
|
||||
|
||||
Method onUpdate = EcritureComptable.class.getDeclaredMethod("onUpdate");
|
||||
onUpdate.setAccessible(true);
|
||||
onUpdate.invoke(e);
|
||||
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo("200");
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo("200");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les défauts si null")
|
||||
void onCreate_setsDefaults() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece(null);
|
||||
e.setDateEcriture(null);
|
||||
e.setMontantDebit(null);
|
||||
e.setMontantCredit(null);
|
||||
e.setPointe(null);
|
||||
|
||||
Method onCreate = EcritureComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(e);
|
||||
|
||||
assertThat(e.getNumeroPiece()).isNotNull().startsWith("ECR-");
|
||||
assertThat(e.getDateEcriture()).isEqualTo(LocalDate.now());
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(e.getPointe()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: numeroPiece vide → généré")
|
||||
void onCreate_numeroPieceEmpty_generated() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("");
|
||||
e.setDateEcriture(LocalDate.of(2025, 6, 1));
|
||||
|
||||
Method onCreate = EcritureComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(e);
|
||||
|
||||
assertThat(e.getNumeroPiece()).isNotEmpty().startsWith("ECR-20250601-");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: avec lignes → calculerTotaux appelé")
|
||||
void onCreate_withLignes_calculesTotaux() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
LigneEcriture l1 = new LigneEcriture();
|
||||
l1.setMontantDebit(new BigDecimal("300"));
|
||||
l1.setMontantCredit(BigDecimal.ZERO);
|
||||
LigneEcriture l2 = new LigneEcriture();
|
||||
l2.setMontantDebit(BigDecimal.ZERO);
|
||||
l2.setMontantCredit(new BigDecimal("300"));
|
||||
e.getLignes().add(l1);
|
||||
e.getLignes().add(l2);
|
||||
|
||||
Method onCreate = EcritureComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(e);
|
||||
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo("300");
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo("300");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEquilibree: false si montantCredit null (branche ||)")
|
||||
void isEquilibree_montantCreditNull_returnsFalse() {
|
||||
// montantDebit non null mais montantCredit null → retourne false
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setJournal(newJournal());
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("L");
|
||||
e.setMontantDebit(new BigDecimal("100.00"));
|
||||
e.setMontantCredit(null);
|
||||
assertThat(e.isEquilibree()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("calculerTotaux: lignes vides → totaux à ZERO")
|
||||
void calculerTotaux_emptyLignes_setsZero() {
|
||||
// Couvre la branche : `if (lignes == null || lignes.isEmpty()) { return ZERO; }`
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setJournal(newJournal());
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("L");
|
||||
e.setMontantDebit(new BigDecimal("500.00"));
|
||||
e.setMontantCredit(new BigDecimal("500.00"));
|
||||
// lignes est vide (défaut)
|
||||
e.calculerTotaux();
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: lignes non vides présentes → calculerTotaux() appelé (branche true)")
|
||||
void onCreate_lignesNonVides_calculeTotaux() throws Exception {
|
||||
// Couvre la branche `if (lignes != null && !lignes.isEmpty())` → true dans onCreate
|
||||
// Ce test est complémentaire à onCreate_withLignes_calculesTotaux pour s'assurer
|
||||
// que le chemin est bien couvert.
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("PIECE-001");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("Test");
|
||||
LigneEcriture l1 = new LigneEcriture();
|
||||
l1.setMontantDebit(new BigDecimal("75"));
|
||||
l1.setMontantCredit(BigDecimal.ZERO);
|
||||
LigneEcriture l2 = new LigneEcriture();
|
||||
l2.setMontantDebit(BigDecimal.ZERO);
|
||||
l2.setMontantCredit(new BigDecimal("75"));
|
||||
e.getLignes().add(l1);
|
||||
e.getLignes().add(l2);
|
||||
|
||||
Method onCreate = EcritureComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(e);
|
||||
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo("75");
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo("75");
|
||||
// numeroPiece déjà défini → conservé (branche false du if numeroPiece)
|
||||
assertThat(e.getNumeroPiece()).isEqualTo("PIECE-001");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("calculerTotaux: lignes == null → totaux à ZERO (branche lignes null)")
|
||||
void calculerTotaux_nullLignes_setsZero() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("L");
|
||||
e.setMontantDebit(new BigDecimal("999"));
|
||||
e.setMontantCredit(new BigDecimal("999"));
|
||||
// Forcer lignes à null via réflexion
|
||||
java.lang.reflect.Field lignesField = EcritureComptable.class.getDeclaredField("lignes");
|
||||
lignesField.setAccessible(true);
|
||||
lignesField.set(e, null);
|
||||
e.calculerTotaux();
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: lignes != null et isEmpty → calculerTotaux NON appelé (branche false)")
|
||||
void onCreate_lignesEmptyList_calculerTotauxNotCalled() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("L");
|
||||
e.setMontantDebit(new BigDecimal("10"));
|
||||
e.setMontantCredit(new BigDecimal("10"));
|
||||
// lignes est une ArrayList vide (valeur par défaut) → lignes != null && !lignes.isEmpty() → false
|
||||
assertThat(e.getLignes()).isEmpty();
|
||||
Method onCreate = EcritureComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(e);
|
||||
// calculerTotaux n'a pas été appelé → montants restent (ou reset à 0 par init)
|
||||
// but montantDebit/Credit were already set, and they won't be recalculated
|
||||
// Just verify no exception and onCreate ran
|
||||
assertThat(e.getNumeroPiece()).isEqualTo("X");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: numeroPiece vide ('') → génère un nouveau numeroPiece (branche isEmpty() true)")
|
||||
void onCreate_numeroPieceEmpty_generatesPiece() throws Exception {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece(""); // non-null mais vide → isEmpty() true → génère
|
||||
e.setDateEcriture(LocalDate.now()); // non-null → ternaire true
|
||||
e.setLibelle("L");
|
||||
e.setMontantDebit(new BigDecimal("10"));
|
||||
e.setMontantCredit(new BigDecimal("10"));
|
||||
|
||||
Method onCreate = EcritureComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(e);
|
||||
|
||||
// numeroPiece était vide → a été généré
|
||||
assertThat(e.getNumeroPiece()).isNotEmpty();
|
||||
assertThat(e.getNumeroPiece()).startsWith("ECR");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("calculerTotaux: filtre les montants null (branch false des lambdas filter)")
|
||||
void calculerTotaux_withNullAmounts() {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("X");
|
||||
e.setDateEcriture(LocalDate.now());
|
||||
e.setLibelle("L");
|
||||
// Ligne avec montants null → filtrée (couvre branch false: amount != null → false)
|
||||
LigneEcriture l1 = new LigneEcriture();
|
||||
l1.setMontantDebit(null);
|
||||
l1.setMontantCredit(null);
|
||||
LigneEcriture l2 = new LigneEcriture();
|
||||
l2.setMontantDebit(new BigDecimal("50"));
|
||||
l2.setMontantCredit(new BigDecimal("50"));
|
||||
e.getLignes().add(l1);
|
||||
e.getLignes().add(l2);
|
||||
e.calculerTotaux();
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo("50");
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo("50");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,622 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.membre.StatutMembre;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
import dev.lions.unionflow.server.api.enums.wave.StatutWebhook;
|
||||
import dev.lions.unionflow.server.api.enums.communication.ConversationType;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests de couverture pour les branches manquées dans les entités.
|
||||
* Cible les branches des @PrePersist/@PreUpdate et des méthodes métier
|
||||
* non couvertes par les tests unitaires existants.
|
||||
*/
|
||||
@DisplayName("EntityCoverageTest — branches @PrePersist et méthodes métier")
|
||||
class EntityCoverageTest {
|
||||
|
||||
// ─── Membre ──────────────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Membre — branches manquées")
|
||||
class MembreCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statutCompte=null l'initialise à EN_ATTENTE_VALIDATION")
|
||||
void onCreate_nullStatutCompte_setsDefault() {
|
||||
// On ne peut pas appeler directement @PrePersist hors container JPA,
|
||||
// mais on peut tester la branche via reflection ou en vérifiant la valeur Builder.Default.
|
||||
// Alternative : vérifier que le Builder.Default couvre le null au niveau entité.
|
||||
Membre m = new Membre();
|
||||
m.setNumeroMembre("X");
|
||||
m.setPrenom("A");
|
||||
m.setNom("B");
|
||||
m.setEmail("a@test.com");
|
||||
m.setDateNaissance(LocalDate.now());
|
||||
// La valeur par défaut via Builder.Default est "EN_ATTENTE_VALIDATION"
|
||||
// mais l'instanciation via new Membre() ne déclenche pas le @Builder.Default.
|
||||
// On couvre la branche en appelant le @PrePersist directement via under-test:
|
||||
m.setStatutCompte(null);
|
||||
// Invoke the protected onCreate via direct call (simulated)
|
||||
m.onCreate();
|
||||
assertThat(m.getStatutCompte()).isEqualTo("EN_ATTENTE_VALIDATION");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAge() avec dateNaissance=null retourne 0")
|
||||
void getAge_nullDateNaissance_returnsZero() {
|
||||
Membre m = new Membre();
|
||||
m.setDateNaissance(null);
|
||||
assertThat(m.getAge()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isMajeur() avec dateNaissance=null retourne false")
|
||||
void isMajeur_nullDateNaissance_returnsFalse() {
|
||||
Membre m = new Membre();
|
||||
m.setDateNaissance(null);
|
||||
assertThat(m.isMajeur()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── MembreOrganisation ───────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("MembreOrganisation — branches manquées")
|
||||
class MembreOrganisationCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statutMembre=null l'initialise à EN_ATTENTE_VALIDATION")
|
||||
void onCreate_nullStatutMembre_setsDefault() {
|
||||
MembreOrganisation mo = new MembreOrganisation();
|
||||
mo.setStatutMembre(null);
|
||||
mo.onCreate();
|
||||
assertThat(mo.getStatutMembre()).isEqualTo(StatutMembre.EN_ATTENTE_VALIDATION);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── ModuleOrganisationActif ──────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("ModuleOrganisationActif — isActif() non couvert")
|
||||
class ModuleOrganisationActifCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif() retourne true quand actif=true")
|
||||
void isActif_true() {
|
||||
ModuleOrganisationActif m = new ModuleOrganisationActif();
|
||||
m.setActif(true);
|
||||
m.setModuleCode("TEST");
|
||||
assertThat(m.isActif()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif() retourne false quand actif=false")
|
||||
void isActif_false() {
|
||||
ModuleOrganisationActif m = new ModuleOrganisationActif();
|
||||
m.setActif(false);
|
||||
m.setModuleCode("TEST");
|
||||
assertThat(m.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif() retourne false quand actif=null")
|
||||
void isActif_null() {
|
||||
ModuleOrganisationActif m = new ModuleOrganisationActif();
|
||||
m.setActif(null);
|
||||
assertThat(m.isActif()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── InscriptionEvenement — preUpdate ─────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("InscriptionEvenement — preUpdate() non couvert")
|
||||
class InscriptionEvenementCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("preUpdate() appelle super.onUpdate() sans exception")
|
||||
void preUpdate_doesNotThrow() {
|
||||
InscriptionEvenement ie = new InscriptionEvenement();
|
||||
ie.setStatut("CONFIRMEE");
|
||||
ie.preUpdate();
|
||||
// La date de modification est setDateModification — on vérifie juste que ça ne plante pas
|
||||
assertThat(ie.getDateModification()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Conversation — onUpdate ─────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Conversation — onUpdate() non couvert")
|
||||
class ConversationCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("Conversation getters/setters de base")
|
||||
void gettersSetters() {
|
||||
Conversation c = new Conversation();
|
||||
c.setName("Chat Test");
|
||||
c.setDescription("Description");
|
||||
c.setType(ConversationType.GROUP);
|
||||
c.setIsMuted(false);
|
||||
c.setIsPinned(true);
|
||||
c.setIsArchived(false);
|
||||
c.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
assertThat(c.getName()).isEqualTo("Chat Test");
|
||||
assertThat(c.getType()).isEqualTo(ConversationType.GROUP);
|
||||
assertThat(c.getIsPinned()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onUpdate() met à jour updatedAt")
|
||||
void onUpdate_setsUpdatedAt() {
|
||||
Conversation c = new Conversation();
|
||||
c.setName("Chat");
|
||||
c.setType(ConversationType.INDIVIDUAL);
|
||||
assertThat(c.getUpdatedAt()).isNull();
|
||||
c.onUpdate();
|
||||
assertThat(c.getUpdatedAt()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── EcritureComptable — onUpdate ────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("EcritureComptable — onUpdate() non couvert")
|
||||
class EcritureComptableCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onUpdate() appelle calculerTotaux")
|
||||
void onUpdate_calculerTotaux() {
|
||||
EcritureComptable e = new EcritureComptable();
|
||||
e.setNumeroPiece("ECR-UPD-001");
|
||||
e.setDateEcriture(java.time.LocalDate.now());
|
||||
e.setLibelle("Test update");
|
||||
e.setMontantDebit(java.math.BigDecimal.ZERO);
|
||||
e.setMontantCredit(java.math.BigDecimal.ZERO);
|
||||
// onUpdate calls calculerTotaux; with empty lignes, totals reset to ZERO
|
||||
e.onUpdate();
|
||||
assertThat(e.getMontantDebit()).isEqualByComparingTo(java.math.BigDecimal.ZERO);
|
||||
assertThat(e.getMontantCredit()).isEqualByComparingTo(java.math.BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── ValidationEtapeDemande — onCreate ───────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("ValidationEtapeDemande — onCreate() non couvert")
|
||||
class ValidationEtapeDemandeCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statut=null initialise à EN_ATTENTE")
|
||||
void onCreate_nullStatut_setsDefault() {
|
||||
dev.lions.unionflow.server.api.enums.solidarite.StatutValidationEtape statut =
|
||||
dev.lions.unionflow.server.api.enums.solidarite.StatutValidationEtape.EN_ATTENTE;
|
||||
ValidationEtapeDemande ved = new ValidationEtapeDemande();
|
||||
ved.setStatut(null);
|
||||
ved.onCreate();
|
||||
assertThat(ved.getStatut()).isEqualTo(statut);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statut déjà défini le préserve")
|
||||
void onCreate_existingStatut_preserves() {
|
||||
dev.lions.unionflow.server.api.enums.solidarite.StatutValidationEtape statut =
|
||||
dev.lions.unionflow.server.api.enums.solidarite.StatutValidationEtape.APPROUVEE;
|
||||
ValidationEtapeDemande ved = new ValidationEtapeDemande();
|
||||
ved.setStatut(statut);
|
||||
ved.onCreate();
|
||||
assertThat(ved.getStatut()).isEqualTo(statut);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── SystemAlert — branches @PrePersist ──────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("SystemAlert — branches @PrePersist non couvertes")
|
||||
class SystemAlertCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec timestamp=null l'initialise")
|
||||
void onCreate_nullTimestamp_setsNow() {
|
||||
SystemAlert a = new SystemAlert();
|
||||
a.setLevel("WARNING");
|
||||
a.setTitle("Test");
|
||||
a.setMessage("Msg");
|
||||
a.setTimestamp(null);
|
||||
a.setAcknowledged(null);
|
||||
a.onCreate();
|
||||
assertThat(a.getTimestamp()).isNotNull();
|
||||
assertThat(a.getAcknowledged()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec timestamp et acknowledged déjà définis ne les écrase pas")
|
||||
void onCreate_withExistingValues_preserves() {
|
||||
LocalDateTime ts = LocalDateTime.of(2026, 1, 1, 0, 0);
|
||||
SystemAlert a = new SystemAlert();
|
||||
a.setTimestamp(ts);
|
||||
a.setAcknowledged(true);
|
||||
a.onCreate();
|
||||
assertThat(a.getTimestamp()).isEqualTo(ts);
|
||||
assertThat(a.getAcknowledged()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── SystemLog — branche @PrePersist ─────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("SystemLog — branche @PrePersist non couverte")
|
||||
class SystemLogCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec timestamp=null l'initialise")
|
||||
void onCreate_nullTimestamp_setsNow() {
|
||||
SystemLog sl = new SystemLog();
|
||||
sl.setLevel("ERROR");
|
||||
sl.setSource("TEST");
|
||||
sl.setMessage("Message test");
|
||||
sl.setTimestamp(null);
|
||||
sl.onCreate();
|
||||
assertThat(sl.getTimestamp()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Getters/setters de SystemLog")
|
||||
void gettersSetters() {
|
||||
SystemLog sl = new SystemLog();
|
||||
sl.setLevel("INFO");
|
||||
sl.setSource("Database");
|
||||
sl.setMessage("DB query");
|
||||
sl.setDetails("stack trace here");
|
||||
sl.setTimestamp(LocalDateTime.now());
|
||||
sl.setUserId("user-123");
|
||||
sl.setSessionId("sess-abc");
|
||||
sl.setEndpoint("/api/test");
|
||||
sl.setHttpStatusCode(200);
|
||||
|
||||
assertThat(sl.getLevel()).isEqualTo("INFO");
|
||||
assertThat(sl.getSource()).isEqualTo("Database");
|
||||
assertThat(sl.getEndpoint()).isEqualTo("/api/test");
|
||||
assertThat(sl.getHttpStatusCode()).isEqualTo(200);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── WebhookWave — branches @PrePersist ──────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("WebhookWave — branches @PrePersist non couvertes")
|
||||
class WebhookWaveCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statutTraitement=null l'initialise à EN_ATTENTE")
|
||||
void onCreate_nullStatut_setsDefault() {
|
||||
WebhookWave w = new WebhookWave();
|
||||
w.setWaveEventId("evt-" + UUID.randomUUID());
|
||||
w.setStatutTraitement(null);
|
||||
w.setNombreTentatives(null);
|
||||
w.setDateReception(null);
|
||||
w.onCreate();
|
||||
assertThat(w.getStatutTraitement()).isEqualTo(StatutWebhook.EN_ATTENTE.name());
|
||||
assertThat(w.getNombreTentatives()).isEqualTo(0);
|
||||
assertThat(w.getDateReception()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() ne surécrit pas des valeurs déjà définies")
|
||||
void onCreate_withExistingValues_preserves() {
|
||||
WebhookWave w = new WebhookWave();
|
||||
w.setWaveEventId("evt-" + UUID.randomUUID());
|
||||
w.setStatutTraitement(StatutWebhook.TRAITE.name());
|
||||
w.setNombreTentatives(3);
|
||||
LocalDateTime reception = LocalDateTime.of(2026, 1, 1, 12, 0);
|
||||
w.setDateReception(reception);
|
||||
w.onCreate();
|
||||
assertThat(w.getStatutTraitement()).isEqualTo(StatutWebhook.TRAITE.name());
|
||||
assertThat(w.getNombreTentatives()).isEqualTo(3);
|
||||
assertThat(w.getDateReception()).isEqualTo(reception);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Paiement — branches @PrePersist ─────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Paiement — branches @PrePersist non couvertes")
|
||||
class PaiementCoverage {
|
||||
|
||||
private Membre newMembre() {
|
||||
Membre m = new Membre();
|
||||
m.setId(UUID.randomUUID());
|
||||
m.setNumeroMembre("MX");
|
||||
m.setPrenom("X");
|
||||
m.setNom("Y");
|
||||
m.setEmail("xy@test.com");
|
||||
m.setDateNaissance(LocalDate.now());
|
||||
return m;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec numeroReference=null génère un numéro")
|
||||
void onCreate_nullNumeroReference_generates() {
|
||||
Paiement p = new Paiement();
|
||||
p.setNumeroReference(null);
|
||||
p.setStatutPaiement(null);
|
||||
p.setMontant(BigDecimal.ONE);
|
||||
p.setCodeDevise("XOF");
|
||||
p.setMethodePaiement("WAVE");
|
||||
p.setMembre(newMembre());
|
||||
p.onCreate();
|
||||
assertThat(p.getNumeroReference()).startsWith("PAY-");
|
||||
assertThat(p.getStatutPaiement()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(p.getDatePaiement()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec numeroReference vide génère un numéro")
|
||||
void onCreate_emptyNumeroReference_generates() {
|
||||
Paiement p = new Paiement();
|
||||
p.setNumeroReference("");
|
||||
p.setStatutPaiement("VALIDE");
|
||||
p.setMontant(BigDecimal.ONE);
|
||||
p.setCodeDevise("XOF");
|
||||
p.setMethodePaiement("WAVE");
|
||||
p.setMembre(newMembre());
|
||||
p.setDatePaiement(LocalDateTime.now()); // already set
|
||||
p.onCreate();
|
||||
assertThat(p.getNumeroReference()).startsWith("PAY-");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreModifie() retourne false pour ANNULE")
|
||||
void peutEtreModifie_annule_returnsFalse() {
|
||||
Paiement p = new Paiement();
|
||||
p.setNumeroReference("X");
|
||||
p.setMontant(BigDecimal.ONE);
|
||||
p.setCodeDevise("XOF");
|
||||
p.setMethodePaiement("WAVE");
|
||||
p.setMembre(newMembre());
|
||||
p.setStatutPaiement("ANNULE");
|
||||
assertThat(p.peutEtreModifie()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── DemandeAide — branches @PrePersist ──────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("DemandeAide — branches @PrePersist non couvertes")
|
||||
class DemandeAideCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec dateDemande/statut/urgence=null initialise les defaults")
|
||||
void onCreate_nullFields_setsDefaults() {
|
||||
DemandeAide d = new DemandeAide();
|
||||
d.setDateDemande(null);
|
||||
d.setStatut(null);
|
||||
d.setUrgence(null);
|
||||
d.onCreate();
|
||||
assertThat(d.getDateDemande()).isNotNull();
|
||||
assertThat(d.getStatut()).isEqualTo(StatutAide.EN_ATTENTE);
|
||||
assertThat(d.getUrgence()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── LigneEcriture — branches @PrePersist + getMontant ───────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("LigneEcriture — branches non couvertes")
|
||||
class LigneEcritureCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec montantDebit/montantCredit=null les initialise à ZERO")
|
||||
void onCreate_nullMontants_setsZero() {
|
||||
LigneEcriture le = new LigneEcriture();
|
||||
le.setMontantDebit(null);
|
||||
le.setMontantCredit(null);
|
||||
le.onCreate();
|
||||
assertThat(le.getMontantDebit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(le.getMontantCredit()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getMontant() retourne ZERO quand les deux montants sont null/zero")
|
||||
void getMontant_noDebitNoCredit_returnsZero() {
|
||||
LigneEcriture le = new LigneEcriture();
|
||||
le.setMontantDebit(null);
|
||||
le.setMontantCredit(null);
|
||||
assertThat(le.getMontant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── MembreRole — branches isActif ────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("MembreRole — branches isActif() et @PrePersist non couverts")
|
||||
class MembreRoleCoverage {
|
||||
|
||||
private MembreRole newMembreRole() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setActif(true);
|
||||
return mr;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif() retourne false si actif=false")
|
||||
void isActif_inactif_returnsFalse() {
|
||||
MembreRole mr = newMembreRole();
|
||||
mr.setActif(false);
|
||||
assertThat(mr.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif() retourne false si dateFin est dépassée")
|
||||
void isActif_dateFinPassed_returnsFalse() {
|
||||
MembreRole mr = newMembreRole();
|
||||
mr.setDateDebut(LocalDate.now().minusDays(10));
|
||||
mr.setDateFin(LocalDate.now().minusDays(1));
|
||||
assertThat(mr.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec dateDebut=null l'initialise à aujourd'hui")
|
||||
void onCreate_nullDateDebut_setsToday() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setDateDebut(null);
|
||||
mr.onCreate();
|
||||
assertThat(mr.getDateDebut()).isEqualTo(LocalDate.now());
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Permission — branche @PrePersist ────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Permission — branche @PrePersist non couverte")
|
||||
class PermissionCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec code=null et module/ressource/action définis génère le code")
|
||||
void onCreate_nullCode_withModuleRessourceAction_generatesCode() {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
p.setModule("FINANCE");
|
||||
p.setRessource("COTISATION");
|
||||
p.setAction("CREATE");
|
||||
p.onCreate();
|
||||
assertThat(p.getCode()).isEqualTo("FINANCE > COTISATION > CREATE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec code=null et module=null ne génère rien")
|
||||
void onCreate_nullCode_nullModule_noGeneration() {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
p.setModule(null);
|
||||
p.setRessource(null);
|
||||
p.setAction(null);
|
||||
p.onCreate();
|
||||
assertThat(p.getCode()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Role — branches @PrePersist ─────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Role — branches @PrePersist non couvertes")
|
||||
class RoleCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec typeRole/niveauHierarchique=null initialise les defaults")
|
||||
void onCreate_nullFields_setsDefaults() {
|
||||
Role r = new Role();
|
||||
r.setTypeRole(null);
|
||||
r.setNiveauHierarchique(null);
|
||||
r.onCreate();
|
||||
assertThat(r.getTypeRole()).isNotNull();
|
||||
assertThat(r.getNiveauHierarchique()).isEqualTo(100);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Document — branches @PrePersist ─────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Document — branches @PrePersist non couvertes")
|
||||
class DocumentCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec nombreTelechargements/typeDocument=null initialise les defaults")
|
||||
void onCreate_nullFields_setsDefaults() {
|
||||
Document d = new Document();
|
||||
d.setNombreTelechargements(null);
|
||||
d.setTypeDocument(null);
|
||||
d.onCreate();
|
||||
assertThat(d.getNombreTelechargements()).isEqualTo(0);
|
||||
assertThat(d.getTypeDocument()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── PieceJointe — branche @PrePersist ───────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("PieceJointe — branche @PrePersist non couverte")
|
||||
class PieceJointeCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec ordre=null l'initialise à 1")
|
||||
void onCreate_nullOrdre_setsOne() {
|
||||
PieceJointe pj = new PieceJointe();
|
||||
pj.setOrdre(null);
|
||||
pj.onCreate();
|
||||
assertThat(pj.getOrdre()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Adresse — branche @PrePersist ───────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Adresse — branche @PrePersist non couverte")
|
||||
class AdresseCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec principale=null l'initialise à false")
|
||||
void onCreate_nullPrincipale_setsFalse() {
|
||||
Adresse a = new Adresse();
|
||||
a.setPrincipale(null);
|
||||
a.onCreate();
|
||||
assertThat(a.getPrincipale()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── JournalComptable — branche @PrePersist ──────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("JournalComptable — branche @PrePersist non couverte")
|
||||
class JournalComptableCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statut=null initialise à OUVERT")
|
||||
void onCreate_nullStatut_setsOuvert() {
|
||||
JournalComptable jc = new JournalComptable();
|
||||
jc.setStatut(null);
|
||||
jc.onCreate();
|
||||
assertThat(jc.getStatut()).isEqualTo("OUVERT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec statut vide initialise à OUVERT")
|
||||
void onCreate_emptyStatut_setsOuvert() {
|
||||
JournalComptable jc = new JournalComptable();
|
||||
jc.setStatut("");
|
||||
jc.onCreate();
|
||||
assertThat(jc.getStatut()).isEqualTo("OUVERT");
|
||||
}
|
||||
}
|
||||
|
||||
// ─── SuggestionVote — branches @PrePersist ───────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("SuggestionVote — branches @PrePersist non couvertes")
|
||||
class SuggestionVoteCoverage {
|
||||
|
||||
@Test
|
||||
@DisplayName("onPrePersist() avec dateVote=null l'initialise")
|
||||
void onPrePersist_nullDateVote_setsNow() {
|
||||
SuggestionVote sv = new SuggestionVote();
|
||||
sv.setSuggestionId(UUID.randomUUID());
|
||||
sv.setUtilisateurId(UUID.randomUUID());
|
||||
sv.setDateVote(null);
|
||||
sv.setDateCreation(null);
|
||||
sv.onPrePersist();
|
||||
assertThat(sv.getDateVote()).isNotNull();
|
||||
assertThat(sv.getDateCreation()).isNotNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests de couverture complémentaires pour Evenement.
|
||||
* Couvre les branches manquantes de isTermine(), isEnCours(), getTauxRemplissage().
|
||||
*/
|
||||
@DisplayName("Evenement - couverture complémentaire")
|
||||
class EvenementCoverageTest {
|
||||
|
||||
private Evenement buildEvenement() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Test Evenement");
|
||||
e.setDateDebut(LocalDateTime.now().plusDays(1));
|
||||
e.setStatut("PLANIFIE");
|
||||
return e;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isTermine: true si dateFin est dans le passé (statut non TERMINE)")
|
||||
void isTermine_pastDateFin_returnsTrue() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setDateDebut(LocalDateTime.now().minusDays(2));
|
||||
e.setDateFin(LocalDateTime.now().minusHours(1)); // dateFin passée
|
||||
e.setStatut("CONFIRME"); // pas TERMINE
|
||||
assertThat(e.isTermine()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isTermine: false si dateFin est dans le futur (statut non TERMINE)")
|
||||
void isTermine_futureDateFin_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setDateFin(LocalDateTime.now().plusHours(2)); // dateFin future
|
||||
e.setStatut("PLANIFIE");
|
||||
assertThat(e.isTermine()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnCours: false si dateDebut future")
|
||||
void isEnCours_futureDateDebut_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setDateDebut(LocalDateTime.now().plusHours(1));
|
||||
assertThat(e.isEnCours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnCours: true si dateDebut passée et dateFin null (événement sans fin définie)")
|
||||
void isEnCours_noDateFin_returnsTrue() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setDateDebut(LocalDateTime.now().minusHours(1));
|
||||
e.setDateFin(null); // pas de dateFin → toujours en cours si après dateDebut
|
||||
assertThat(e.isEnCours()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnCours: false si dateFin passée")
|
||||
void isEnCours_pastDateFin_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setDateDebut(LocalDateTime.now().minusHours(2));
|
||||
e.setDateFin(LocalDateTime.now().minusHours(1)); // dateFin passée
|
||||
assertThat(e.isEnCours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getTauxRemplissage: null si capaciteMax est 0")
|
||||
void getTauxRemplissage_zeroCapaciteMax_returnsNull() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setCapaciteMax(0);
|
||||
assertThat(e.getTauxRemplissage()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getTauxRemplissage: retourne le pourcentage si inscriptions")
|
||||
void getTauxRemplissage_withInscriptions_returnsPercentage() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setCapaciteMax(4);
|
||||
|
||||
Membre m1 = new Membre();
|
||||
m1.setId(java.util.UUID.randomUUID());
|
||||
InscriptionEvenement i1 = new InscriptionEvenement();
|
||||
i1.setMembre(m1);
|
||||
i1.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
e.getInscriptions().add(i1);
|
||||
|
||||
Membre m2 = new Membre();
|
||||
m2.setId(java.util.UUID.randomUUID());
|
||||
InscriptionEvenement i2 = new InscriptionEvenement();
|
||||
i2.setMembre(m2);
|
||||
i2.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
e.getInscriptions().add(i2);
|
||||
|
||||
// 2 inscrits sur 4 = 50%
|
||||
assertThat(e.getTauxRemplissage()).isEqualTo(50.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getPlacesRestantes: 0 si nbInscrits >= capaciteMax")
|
||||
void getPlacesRestantes_full_returnsZero() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setCapaciteMax(1);
|
||||
|
||||
Membre m = new Membre();
|
||||
m.setId(java.util.UUID.randomUUID());
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(m);
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
e.getInscriptions().add(i);
|
||||
|
||||
// capaciteMax=1, inscrits=1 → placesRestantes=0
|
||||
assertThat(e.getPlacesRestantes()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isMemberInscrit: false si membre non inscrit mais d'autres sont inscrits")
|
||||
void isMemberInscrit_differentMembre_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
|
||||
Membre m = new Membre();
|
||||
m.setId(java.util.UUID.randomUUID());
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(m);
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
e.getInscriptions().add(i);
|
||||
|
||||
// Vérifie un autre membre (non inscrit)
|
||||
assertThat(e.isMemberInscrit(java.util.UUID.randomUUID())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isMemberInscrit: false si inscription non CONFIRMEE")
|
||||
void isMemberInscrit_nonConfirmee_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
java.util.UUID membreId = java.util.UUID.randomUUID();
|
||||
|
||||
Membre m = new Membre();
|
||||
m.setId(membreId);
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(m);
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.ANNULEE.name()); // pas CONFIRMEE
|
||||
e.getInscriptions().add(i);
|
||||
|
||||
assertThat(e.isMemberInscrit(membreId)).isFalse();
|
||||
}
|
||||
|
||||
// ── Branches manquantes ───────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Branch manquante dans isComplet() : capaciteMax == null → false.
|
||||
* Le code : `return capaciteMax != null && getNombreInscrits() >= capaciteMax`
|
||||
* → quand capaciteMax est null, la condition court-circuite (false).
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isComplet: false si capaciteMax null (capacité illimitée)")
|
||||
void isComplet_capaciteMaxNull_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setCapaciteMax(null); // illimité → jamais complet
|
||||
|
||||
assertThat(e.isComplet()).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Branch manquante dans getTauxRemplissage() : capaciteMax == null → null.
|
||||
* Le code : `if (capaciteMax == null || capaciteMax == 0) { return null; }`
|
||||
* → première condition (capaciteMax == null) doit retourner null.
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("getTauxRemplissage: null si capaciteMax est null")
|
||||
void getTauxRemplissage_capaciteMaxNull_returnsNull() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setCapaciteMax(null);
|
||||
|
||||
assertThat(e.getTauxRemplissage()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Branch manquante dans isMemberInscrit() : inscriptions == null → false.
|
||||
* Le code : `return inscriptions != null && inscriptions.stream()...`
|
||||
* → quand inscriptions est null, retourne false.
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isMemberInscrit: false si inscriptions est null")
|
||||
void isMemberInscrit_inscriptionsNull_returnsFalse() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setInscriptions(null);
|
||||
|
||||
assertThat(e.isMemberInscrit(java.util.UUID.randomUUID())).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Branch manquante dans isOuvertAuxInscriptions() : quand capaciteMax != null
|
||||
* mais getNombreInscrits() < capaciteMax → ne retourne pas false (capacité non atteinte),
|
||||
* passe à la vérification du statut.
|
||||
* Couvre le chemin où la branche capacité est false (non bloquante).
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: true si capaciteMax définie mais non atteinte")
|
||||
void isOuvertAuxInscriptions_capaciteNonAtteinte_returnsTrue() {
|
||||
Evenement e = buildEvenement();
|
||||
e.setInscriptionRequise(true);
|
||||
e.setActif(true);
|
||||
e.setCapaciteMax(5); // capacité non atteinte (0 inscrits)
|
||||
|
||||
assertThat(e.isOuvertAuxInscriptions()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -240,4 +240,138 @@ class EvenementTest {
|
||||
e.setDateDebut(LocalDateTime.now());
|
||||
assertThat(e.isMemberInscrit(UUID.randomUUID())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: false si actif=false")
|
||||
void isOuvertAuxInscriptions_false_actifFalse() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().plusDays(1));
|
||||
e.setInscriptionRequise(true);
|
||||
e.setStatut("PLANIFIE");
|
||||
e.setActif(false);
|
||||
assertThat(e.isOuvertAuxInscriptions()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: false si date limite dépassée")
|
||||
void isOuvertAuxInscriptions_false_dateLimitePassed() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().plusDays(1));
|
||||
e.setDateLimiteInscription(LocalDateTime.now().minusDays(1));
|
||||
e.setInscriptionRequise(true);
|
||||
e.setStatut("PLANIFIE");
|
||||
e.setActif(true);
|
||||
assertThat(e.isOuvertAuxInscriptions()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: false si événement déjà commencé")
|
||||
void isOuvertAuxInscriptions_false_dateDebutPassed() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().minusHours(1));
|
||||
e.setInscriptionRequise(true);
|
||||
e.setStatut("PLANIFIE");
|
||||
e.setActif(true);
|
||||
assertThat(e.isOuvertAuxInscriptions()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: false si capacité atteinte")
|
||||
void isOuvertAuxInscriptions_false_capacitePleine() {
|
||||
Membre m = new Membre();
|
||||
m.setId(UUID.randomUUID());
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(m);
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().plusDays(1));
|
||||
e.setInscriptionRequise(true);
|
||||
e.setStatut("PLANIFIE");
|
||||
e.setActif(true);
|
||||
e.setCapaciteMax(1);
|
||||
e.getInscriptions().add(i);
|
||||
assertThat(e.isOuvertAuxInscriptions()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: true si statut CONFIRME")
|
||||
void isOuvertAuxInscriptions_true_statutConfirme() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().plusDays(1));
|
||||
e.setInscriptionRequise(true);
|
||||
e.setStatut("CONFIRME");
|
||||
e.setActif(true);
|
||||
assertThat(e.isOuvertAuxInscriptions()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getNombreInscrits: 0 si inscriptions null")
|
||||
void getNombreInscrits_inscriptionsNull_returnsZero() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now());
|
||||
e.setInscriptions(null);
|
||||
assertThat(e.getNombreInscrits()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isTermine: true si dateFin passée et statut non TERMINE")
|
||||
void isTermine_true_datefinPassed() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().minusDays(3));
|
||||
e.setDateFin(LocalDateTime.now().minusDays(1));
|
||||
e.setStatut("PLANIFIE");
|
||||
assertThat(e.isTermine()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isOuvertAuxInscriptions: false si statut ni PLANIFIE ni CONFIRME")
|
||||
void isOuvertAuxInscriptions_false_statutAutre() {
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now().plusDays(1));
|
||||
e.setInscriptionRequise(true);
|
||||
e.setStatut("EN_COURS");
|
||||
e.setActif(true);
|
||||
assertThat(e.isOuvertAuxInscriptions()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isMemberInscrit: false si membre non confirmé")
|
||||
void isMemberInscrit_false_notConfirmed() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre m = new Membre();
|
||||
m.setId(membreId);
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(m);
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.EN_ATTENTE.name());
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now());
|
||||
e.getInscriptions().add(i);
|
||||
assertThat(e.isMemberInscrit(membreId)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isMemberInscrit: false si mauvais id membre")
|
||||
void isMemberInscrit_false_wrongId() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre m = new Membre();
|
||||
m.setId(UUID.randomUUID()); // different id
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(m);
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
Evenement e = new Evenement();
|
||||
e.setTitre("Ev");
|
||||
e.setDateDebut(LocalDateTime.now());
|
||||
e.getInscriptions().add(i);
|
||||
assertThat(e.isMemberInscrit(membreId)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour l'entité FeedbackEvenement.
|
||||
* Tests purs (sans Quarkus) car les méthodes sont de la logique en mémoire.
|
||||
*/
|
||||
@DisplayName("FeedbackEvenement")
|
||||
class FeedbackEvenementTest {
|
||||
|
||||
private FeedbackEvenement buildFeedback() {
|
||||
FeedbackEvenement fb = new FeedbackEvenement();
|
||||
fb.setNote(4);
|
||||
fb.setCommentaire("Très bon événement");
|
||||
fb.setDateFeedback(LocalDateTime.now());
|
||||
fb.setModerationStatut(FeedbackEvenement.ModerationStatut.PUBLIE.name());
|
||||
return fb;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPublie retourne true quand statut est PUBLIE")
|
||||
void isPublie_quandStatutPublie_retourneTrue() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
fb.setModerationStatut(FeedbackEvenement.ModerationStatut.PUBLIE.name());
|
||||
|
||||
assertThat(fb.isPublie()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPublie retourne false quand statut est EN_ATTENTE")
|
||||
void isPublie_quandStatutEnAttente_retourneFalse() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
fb.setModerationStatut(FeedbackEvenement.ModerationStatut.EN_ATTENTE.name());
|
||||
|
||||
assertThat(fb.isPublie()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPublie retourne false quand statut est REJETE")
|
||||
void isPublie_quandStatutRejete_retourneFalse() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
fb.setModerationStatut(FeedbackEvenement.ModerationStatut.REJETE.name());
|
||||
|
||||
assertThat(fb.isPublie()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("mettreEnAttente modifie le statut et la raison")
|
||||
void mettreEnAttente_modifieStatutEtRaison() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
|
||||
fb.mettreEnAttente("Contenu inapproprié");
|
||||
|
||||
assertThat(fb.getModerationStatut()).isEqualTo(FeedbackEvenement.ModerationStatut.EN_ATTENTE.name());
|
||||
assertThat(fb.getRaisonModeration()).isEqualTo("Contenu inapproprié");
|
||||
assertThat(fb.isPublie()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("publier restaure le statut PUBLIE et efface la raison")
|
||||
void publier_restaureStatutPublieEtEffaceRaison() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
fb.mettreEnAttente("Raison de test");
|
||||
|
||||
fb.publier();
|
||||
|
||||
assertThat(fb.getModerationStatut()).isEqualTo(FeedbackEvenement.ModerationStatut.PUBLIE.name());
|
||||
assertThat(fb.getRaisonModeration()).isNull();
|
||||
assertThat(fb.isPublie()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("rejeter modifie le statut à REJETE et stocke la raison")
|
||||
void rejeter_modifieStatutEtRaison() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
|
||||
fb.rejeter("Commentaire offensant");
|
||||
|
||||
assertThat(fb.getModerationStatut()).isEqualTo(FeedbackEvenement.ModerationStatut.REJETE.name());
|
||||
assertThat(fb.getRaisonModeration()).isEqualTo("Commentaire offensant");
|
||||
assertThat(fb.isPublie()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString retourne une représentation textuelle avec membre et evenement null")
|
||||
void toString_avecMembreEtEvenementNull_retourneChaineSansException() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
fb.setMembre(null);
|
||||
fb.setEvenement(null);
|
||||
fb.setNote(3);
|
||||
|
||||
String result = fb.toString();
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("FeedbackEvenement");
|
||||
assertThat(result).contains("null"); // membre et evenement sont null
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString retourne une représentation textuelle avec membre et evenement renseignés")
|
||||
void toString_avecMembreEtEvenement_retourneRepresentationComplete() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
Membre membre = new Membre();
|
||||
membre.setEmail("test@test.com");
|
||||
fb.setMembre(membre);
|
||||
|
||||
Evenement evenement = new Evenement();
|
||||
evenement.setTitre("AG 2026");
|
||||
evenement.setDateDebut(LocalDateTime.now());
|
||||
fb.setEvenement(evenement);
|
||||
fb.setNote(5);
|
||||
|
||||
String result = fb.toString();
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("FeedbackEvenement");
|
||||
assertThat(result).contains("test@test.com");
|
||||
assertThat(result).contains("AG 2026");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("preUpdate appelle onUpdate sans exception")
|
||||
void preUpdate_sansException() {
|
||||
FeedbackEvenement fb = buildFeedback();
|
||||
// dateModification initialement null (pas d'id/version puisque pas en base)
|
||||
// preUpdate() appelle super.onUpdate() qui met dateModification à now()
|
||||
// On vérifie que l'appel ne lance pas d'exception
|
||||
fb.preUpdate();
|
||||
assertThat(fb.getDateModification()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ModerationStatut enum contient les trois valeurs attendues")
|
||||
void moderationStatutEnum_contientValeurs() {
|
||||
FeedbackEvenement.ModerationStatut[] values = FeedbackEvenement.ModerationStatut.values();
|
||||
assertThat(values).hasSize(3);
|
||||
assertThat(values).contains(
|
||||
FeedbackEvenement.ModerationStatut.PUBLIE,
|
||||
FeedbackEvenement.ModerationStatut.EN_ATTENTE,
|
||||
FeedbackEvenement.ModerationStatut.REJETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getters et setters fonctionnent correctement")
|
||||
void gettersSetters_fonctionnentCorrectement() {
|
||||
FeedbackEvenement fb = new FeedbackEvenement();
|
||||
LocalDateTime date = LocalDateTime.of(2026, 1, 15, 10, 0);
|
||||
|
||||
fb.setNote(3);
|
||||
fb.setCommentaire("Bien mais peut mieux faire");
|
||||
fb.setDateFeedback(date);
|
||||
fb.setModerationStatut(FeedbackEvenement.ModerationStatut.EN_ATTENTE.name());
|
||||
fb.setRaisonModeration("Vérification en cours");
|
||||
|
||||
assertThat(fb.getNote()).isEqualTo(3);
|
||||
assertThat(fb.getCommentaire()).isEqualTo("Bien mais peut mieux faire");
|
||||
assertThat(fb.getDateFeedback()).isEqualTo(date);
|
||||
assertThat(fb.getModerationStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(fb.getRaisonModeration()).isEqualTo("Vérification en cours");
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,12 @@ package dev.lions.unionflow.server.entity;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
|
||||
@DisplayName("InscriptionEvenement")
|
||||
class InscriptionEvenementTest {
|
||||
@@ -118,4 +120,27 @@ class InscriptionEvenementTest {
|
||||
i.setEvenement(newEvenement());
|
||||
assertThat(i.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("preUpdate ne lève pas d'exception")
|
||||
void preUpdate_doesNotThrow() throws Exception {
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(newMembre());
|
||||
i.setEvenement(newEvenement());
|
||||
i.setStatut(InscriptionEvenement.StatutInscription.CONFIRMEE.name());
|
||||
Method preUpdate = InscriptionEvenement.class.getDeclaredMethod("preUpdate");
|
||||
preUpdate.setAccessible(true);
|
||||
assertThatCode(() -> preUpdate.invoke(i)).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString avec membre et evenement null")
|
||||
void toString_nullMemberAndEvenement() {
|
||||
InscriptionEvenement i = new InscriptionEvenement();
|
||||
i.setMembre(null);
|
||||
i.setEvenement(null);
|
||||
i.setStatut("CONFIRMEE");
|
||||
String s = i.toString();
|
||||
assertThat(s).isNotNull().contains("null");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.paiement.StatutIntentionPaiement;
|
||||
import dev.lions.unionflow.server.api.enums.paiement.TypeObjetIntentionPaiement;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests pour {@link IntentionPaiement} — méthode onCreate().
|
||||
*/
|
||||
@DisplayName("IntentionPaiement — onCreate")
|
||||
class IntentionPaiementBranchTest {
|
||||
|
||||
// ── onCreate() ────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: dateExpiration déjà définie → conservée")
|
||||
void onCreate_dateExpirationDejaDefinie_conservee() throws Exception {
|
||||
IntentionPaiement ip = new IntentionPaiement();
|
||||
ip.setMontantTotal(new BigDecimal("5000.00"));
|
||||
ip.setTypeObjet(TypeObjetIntentionPaiement.COTISATION);
|
||||
|
||||
LocalDateTime expirationFixe = LocalDateTime.of(2025, 12, 31, 23, 59);
|
||||
ip.setDateExpiration(expirationFixe);
|
||||
|
||||
Method onCreate = IntentionPaiement.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(ip);
|
||||
|
||||
// dateExpiration doit rester la valeur fixée, pas être remplacée
|
||||
assertThat(ip.getDateExpiration()).isEqualTo(expirationFixe);
|
||||
// les autres defaults sont bien positionnés
|
||||
assertThat(ip.getStatut()).isEqualTo(StatutIntentionPaiement.INITIEE);
|
||||
assertThat(ip.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: dateExpiration null → positionnée à now+30min")
|
||||
void onCreate_dateExpirationNull_setToNowPlusTrente() throws Exception {
|
||||
IntentionPaiement ip = new IntentionPaiement();
|
||||
ip.setMontantTotal(new BigDecimal("5000.00"));
|
||||
ip.setTypeObjet(TypeObjetIntentionPaiement.COTISATION);
|
||||
ip.setStatut(null);
|
||||
ip.setCodeDevise(null);
|
||||
ip.setDateExpiration(null);
|
||||
|
||||
LocalDateTime avant = LocalDateTime.now();
|
||||
|
||||
Method onCreate = IntentionPaiement.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(ip);
|
||||
|
||||
LocalDateTime apres = LocalDateTime.now();
|
||||
|
||||
assertThat(ip.getDateExpiration()).isNotNull();
|
||||
assertThat(ip.getDateExpiration()).isAfterOrEqualTo(avant.plusMinutes(29));
|
||||
assertThat(ip.getDateExpiration()).isBeforeOrEqualTo(apres.plusMinutes(31));
|
||||
assertThat(ip.getStatut()).isEqualTo(StatutIntentionPaiement.INITIEE);
|
||||
assertThat(ip.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import dev.lions.unionflow.server.api.enums.paiement.TypeObjetIntentionPaiement;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
@@ -121,4 +122,35 @@ class IntentionPaiementTest {
|
||||
i.setTypeObjet(TypeObjetIntentionPaiement.COTISATION);
|
||||
assertThat(i.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isExpiree: false si dateExpiration null")
|
||||
void isExpiree_nullDate_returnsFalse() {
|
||||
IntentionPaiement i = new IntentionPaiement();
|
||||
i.setUtilisateur(newMembre());
|
||||
i.setMontantTotal(BigDecimal.ONE);
|
||||
i.setTypeObjet(TypeObjetIntentionPaiement.COTISATION);
|
||||
i.setDateExpiration(null);
|
||||
assertThat(i.isExpiree()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les défauts si null")
|
||||
void onCreate_setsDefaults() throws Exception {
|
||||
IntentionPaiement i = new IntentionPaiement();
|
||||
i.setUtilisateur(newMembre());
|
||||
i.setMontantTotal(BigDecimal.ONE);
|
||||
i.setTypeObjet(TypeObjetIntentionPaiement.COTISATION);
|
||||
i.setStatut(null);
|
||||
i.setCodeDevise(null);
|
||||
i.setDateExpiration(null);
|
||||
|
||||
Method onCreate = IntentionPaiement.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(i);
|
||||
|
||||
assertThat(i.getStatut()).isEqualTo(StatutIntentionPaiement.INITIEE);
|
||||
assertThat(i.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(i.getDateExpiration()).isNotNull().isAfter(LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests pour {@link JournalComptable} — méthodes estDansPeriode() et onCreate().
|
||||
*/
|
||||
@DisplayName("JournalComptable — estDansPeriode et onCreate")
|
||||
class JournalComptableBranchTest {
|
||||
|
||||
private JournalComptable newJournal() {
|
||||
JournalComptable j = new JournalComptable();
|
||||
j.setCode("AC");
|
||||
j.setLibelle("Achat");
|
||||
j.setTypeJournal(TypeJournalComptable.ACHATS);
|
||||
return j;
|
||||
}
|
||||
|
||||
// ── estDansPeriode() ──────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("estDansPeriode: dateDebut non null mais dateFin null → true (période illimitée)")
|
||||
void estDansPeriode_dateFinNull_returnsTrue() {
|
||||
JournalComptable j = newJournal();
|
||||
j.setDateDebut(LocalDate.of(2025, 1, 1));
|
||||
j.setDateFin(null);
|
||||
|
||||
assertThat(j.estDansPeriode(LocalDate.of(2025, 6, 15))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estDansPeriode: dateDebut null mais dateFin non null → true (période illimitée)")
|
||||
void estDansPeriode_dateDebutNull_returnsTrue() {
|
||||
JournalComptable j = newJournal();
|
||||
j.setDateDebut(null);
|
||||
j.setDateFin(LocalDate.of(2025, 12, 31));
|
||||
|
||||
assertThat(j.estDansPeriode(LocalDate.of(2025, 6, 15))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estDansPeriode: date dans la période → true")
|
||||
void estDansPeriode_dateInPeriode_returnsTrue() {
|
||||
JournalComptable j = newJournal();
|
||||
j.setDateDebut(LocalDate.of(2025, 1, 1));
|
||||
j.setDateFin(LocalDate.of(2025, 12, 31));
|
||||
|
||||
assertThat(j.estDansPeriode(LocalDate.of(2025, 6, 15))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estDansPeriode: date hors période → false")
|
||||
void estDansPeriode_dateOutsidePeriode_returnsFalse() {
|
||||
JournalComptable j = newJournal();
|
||||
j.setDateDebut(LocalDate.of(2025, 1, 1));
|
||||
j.setDateFin(LocalDate.of(2025, 6, 30));
|
||||
|
||||
assertThat(j.estDansPeriode(LocalDate.of(2025, 7, 1))).isFalse();
|
||||
}
|
||||
|
||||
// ── onCreate() ────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: statut null → OUVERT")
|
||||
void onCreate_statutNull_setsOuvert() throws Exception {
|
||||
JournalComptable j = newJournal();
|
||||
j.setStatut(null);
|
||||
|
||||
Method onCreate = JournalComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(j);
|
||||
|
||||
assertThat(j.getStatut()).isEqualTo("OUVERT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: statut vide → OUVERT")
|
||||
void onCreate_statutEmpty_setsOuvert() throws Exception {
|
||||
JournalComptable j = newJournal();
|
||||
j.setStatut("");
|
||||
|
||||
Method onCreate = JournalComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(j);
|
||||
|
||||
assertThat(j.getStatut()).isEqualTo("OUVERT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: statut déjà défini → conservé")
|
||||
void onCreate_statutDejaDefini_conserve() throws Exception {
|
||||
JournalComptable j = newJournal();
|
||||
j.setStatut("FERME");
|
||||
|
||||
Method onCreate = JournalComptable.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(j);
|
||||
|
||||
assertThat(j.getStatut()).isEqualTo("FERME");
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,30 @@ class LigneEcritureTest {
|
||||
assertThat(l.isValide()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isValide: false si ni débit ni crédit (both null)")
|
||||
void isValide_false_bothNull() {
|
||||
LigneEcriture l = new LigneEcriture();
|
||||
l.setEcriture(newEcriture());
|
||||
l.setCompteComptable(newCompte());
|
||||
l.setNumeroLigne(1);
|
||||
l.setMontantDebit(null);
|
||||
l.setMontantCredit(null);
|
||||
assertThat(l.isValide()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isValide: false si ni débit ni crédit (both zero)")
|
||||
void isValide_false_bothZero() {
|
||||
LigneEcriture l = new LigneEcriture();
|
||||
l.setEcriture(newEcriture());
|
||||
l.setCompteComptable(newCompte());
|
||||
l.setNumeroLigne(1);
|
||||
l.setMontantDebit(BigDecimal.ZERO);
|
||||
l.setMontantCredit(BigDecimal.ZERO);
|
||||
assertThat(l.isValide()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getMontant: débit ou crédit")
|
||||
void getMontant() {
|
||||
@@ -88,6 +112,18 @@ class LigneEcritureTest {
|
||||
assertThat(l.getMontant()).isEqualByComparingTo("200");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getMontant: retourne ZERO si ni débit ni crédit (both null)")
|
||||
void getMontant_zero_whenBothNull() {
|
||||
LigneEcriture l = new LigneEcriture();
|
||||
l.setEcriture(newEcriture());
|
||||
l.setCompteComptable(newCompte());
|
||||
l.setNumeroLigne(1);
|
||||
l.setMontantDebit(null);
|
||||
l.setMontantCredit(null);
|
||||
assertThat(l.getMontant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
@@ -117,4 +153,26 @@ class LigneEcritureTest {
|
||||
l.setCompteComptable(newCompte());
|
||||
assertThat(l.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
// ── Branch coverage manquantes ─────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* L82 branch manquante : montantCredit != null mais == 0 (not > 0)
|
||||
* → `montantCredit != null && montantCredit.compareTo(BigDecimal.ZERO) > 0` → false
|
||||
* → retourne BigDecimal.ZERO (la dernière ligne)
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("getMontant: montantDebit null, montantCredit = ZERO → retourne ZERO (branche false compareTo)")
|
||||
void getMontant_debitNull_creditZero_returnsZero() {
|
||||
LigneEcriture l = new LigneEcriture();
|
||||
l.setEcriture(newEcriture());
|
||||
l.setCompteComptable(newCompte());
|
||||
l.setNumeroLigne(1);
|
||||
// montantDebit == null → premiere condition false
|
||||
// montantCredit != null mais == 0 → deuxième condition: compareTo > 0 est FALSE
|
||||
// → retourne BigDecimal.ZERO
|
||||
l.setMontantDebit(null);
|
||||
l.setMontantCredit(BigDecimal.ZERO);
|
||||
assertThat(l.getMontant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,18 @@ class MembreOrganisationTest {
|
||||
assertThat(mo.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif: false si statutMembre ACTIF mais actif=false (branche &&)")
|
||||
void isActif_statutActif_actifFalse_returnsFalse() {
|
||||
// statutMembre ACTIF mais actif=false → isActif() retourne false
|
||||
MembreOrganisation mo = new MembreOrganisation();
|
||||
mo.setMembre(newMembre());
|
||||
mo.setOrganisation(newOrganisation());
|
||||
mo.setStatutMembre(StatutMembre.ACTIF);
|
||||
mo.setActif(false);
|
||||
assertThat(mo.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutDemanderAide")
|
||||
void peutDemanderAide() {
|
||||
|
||||
@@ -60,6 +60,29 @@ class MembreRoleTest {
|
||||
assertThat(mr.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif: false si actif=false")
|
||||
void isActif_false_whenActifFalse() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setMembreOrganisation(newMembreOrganisation());
|
||||
mr.setRole(newRole());
|
||||
mr.setActif(false);
|
||||
mr.setDateDebut(LocalDate.now().minusDays(1));
|
||||
assertThat(mr.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif: false si dateFin dans le passé")
|
||||
void isActif_false_dateFinExpiree() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setMembreOrganisation(newMembreOrganisation());
|
||||
mr.setRole(newRole());
|
||||
mr.setActif(true);
|
||||
mr.setDateDebut(LocalDate.now().minusDays(10));
|
||||
mr.setDateFin(LocalDate.now().minusDays(1));
|
||||
assertThat(mr.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif: true si dans la période")
|
||||
void isActif_true() {
|
||||
@@ -98,4 +121,64 @@ class MembreRoleTest {
|
||||
mr.setRole(newRole());
|
||||
assertThat(mr.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
// ── Branch coverage manquantes ─────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif: dateDebut null → condition L76 false (null short-circuit) → continue vers dateFin")
|
||||
void isActif_dateDebutNull_branchNullShortCircuit() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setMembreOrganisation(newMembreOrganisation());
|
||||
mr.setRole(newRole());
|
||||
mr.setActif(true);
|
||||
mr.setDateDebut(null); // null → dateDebut != null = false → skip if body at L76
|
||||
mr.setDateFin(null); // null → dateFin != null = false → skip if body at L79
|
||||
// → return true
|
||||
assertThat(mr.isActif()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* L72 branch manquante : getActif() == null → Boolean.TRUE.equals(null) = false
|
||||
* → !false = true → returns false
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isActif: actif null → Boolean.TRUE.equals(null) false → retourne false")
|
||||
void isActif_actifNull_returnsFalse() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setMembreOrganisation(newMembreOrganisation());
|
||||
mr.setRole(newRole());
|
||||
// actif n'est pas défini (null)
|
||||
mr.setDateDebut(LocalDate.now().minusDays(1));
|
||||
assertThat(mr.isActif()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActif: dateDebut non null mais passée → ne retourne pas false (branche false isBefore)")
|
||||
void isActif_dateDebut_notNull_notBefore_continues() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setMembreOrganisation(newMembreOrganisation());
|
||||
mr.setRole(newRole());
|
||||
mr.setActif(true);
|
||||
// dateDebut dans le passé → isBefore(dateDebut) est false → on continue
|
||||
mr.setDateDebut(LocalDate.now().minusDays(5));
|
||||
mr.setDateFin(null);
|
||||
assertThat(mr.isActif()).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* L79 branch manquante : dateFin != null mais today <= dateFin (NOT after)
|
||||
* → `dateFin != null && aujourdhui.isAfter(dateFin)` → false → continue → return true
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("isActif: dateFin non null mais pas encore dépassée → ne retourne pas false (branche false isAfter)")
|
||||
void isActif_dateFin_notNull_notAfter_returnsTrue() {
|
||||
MembreRole mr = new MembreRole();
|
||||
mr.setMembreOrganisation(newMembreOrganisation());
|
||||
mr.setRole(newRole());
|
||||
mr.setActif(true);
|
||||
mr.setDateDebut(LocalDate.now().minusDays(5));
|
||||
// dateFin dans le futur → isAfter(dateFin) est false → retourne true
|
||||
mr.setDateFin(LocalDate.now().plusDays(5));
|
||||
assertThat(mr.isActif()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.communication.MessageStatus;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("Message")
|
||||
class MessageTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("markAsRead sets status to READ and sets readAt")
|
||||
void markAsRead_setsStatusAndReadAt() {
|
||||
Message m = new Message();
|
||||
m.setStatus(MessageStatus.SENT);
|
||||
assertThat(m.getReadAt()).isNull();
|
||||
|
||||
m.markAsRead();
|
||||
|
||||
assertThat(m.getStatus()).isEqualTo(MessageStatus.READ);
|
||||
assertThat(m.getReadAt()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("markAsEdited sets isEdited true and sets editedAt")
|
||||
void markAsEdited_setsIsEditedAndEditedAt() {
|
||||
Message m = new Message();
|
||||
assertThat(m.getIsEdited()).isFalse();
|
||||
assertThat(m.getEditedAt()).isNull();
|
||||
|
||||
m.markAsEdited();
|
||||
|
||||
assertThat(m.getIsEdited()).isTrue();
|
||||
assertThat(m.getEditedAt()).isNotNull();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package dev.lions.unionflow.server.entity;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -95,4 +96,34 @@ class NotificationTest {
|
||||
n.setTypeNotification("EMAIL");
|
||||
assertThat(n.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isEnvoyee: false si statut null")
|
||||
void isEnvoyee_nullStatut_returnsFalse() {
|
||||
Notification n = new Notification();
|
||||
n.setTypeNotification("EMAIL");
|
||||
n.setStatut(null);
|
||||
assertThat(n.isEnvoyee()).isFalse();
|
||||
assertThat(n.isLue()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les défauts si null")
|
||||
void onCreate_setsDefaults() throws Exception {
|
||||
Notification n = new Notification();
|
||||
n.setTypeNotification("EMAIL");
|
||||
n.setPriorite(null);
|
||||
n.setStatut(null);
|
||||
n.setNombreTentatives(null);
|
||||
n.setDateEnvoiPrevue(null);
|
||||
|
||||
Method onCreate = Notification.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(n);
|
||||
|
||||
assertThat(n.getPriorite()).isEqualTo("NORMALE");
|
||||
assertThat(n.getStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(n.getNombreTentatives()).isEqualTo(0);
|
||||
assertThat(n.getDateEnvoiPrevue()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,145 +1,805 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("Organisation")
|
||||
@DisplayName("Organisation — couverture complète")
|
||||
class OrganisationTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("getters/setters")
|
||||
void gettersSetters() {
|
||||
// ─── Utilitaire ───────────────────────────────────────────────────────────
|
||||
|
||||
private static Organisation baseOrganisation() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("Club Lions Paris");
|
||||
o.setNomCourt("CL Paris");
|
||||
o.setTypeOrganisation("ASSOCIATION");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail("contact@club.fr");
|
||||
o.setTelephone("+33100000000");
|
||||
o.setDevise("XOF");
|
||||
o.setNombreMembres(50);
|
||||
o.setEstOrganisationRacine(true);
|
||||
o.setAccepteNouveauxMembres(true);
|
||||
|
||||
assertThat(o.getNom()).isEqualTo("Club Lions Paris");
|
||||
assertThat(o.getNomCourt()).isEqualTo("CL Paris");
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
assertThat(o.getEmail()).isEqualTo("contact@club.fr");
|
||||
assertThat(o.getNombreMembres()).isEqualTo(50);
|
||||
return o;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getNomComplet: avec et sans nomCourt")
|
||||
void getNomComplet() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("Club A");
|
||||
o.setNomCourt("CA");
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail("a@b.com");
|
||||
assertThat(o.getNomComplet()).isEqualTo("Club A (CA)");
|
||||
o.setNomCourt(null);
|
||||
assertThat(o.getNomComplet()).isEqualTo("Club A");
|
||||
// ─── Getters / Setters ────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Getters et setters")
|
||||
class GettersSetters {
|
||||
|
||||
@Test
|
||||
@DisplayName("Champs de base")
|
||||
void champsDeBase() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setTelephone("+33100000000");
|
||||
o.setDevise("XOF");
|
||||
o.setNombreMembres(50);
|
||||
o.setEstOrganisationRacine(true);
|
||||
o.setAccepteNouveauxMembres(true);
|
||||
|
||||
assertThat(o.getNom()).isEqualTo("Club Lions Paris");
|
||||
assertThat(o.getNomCourt()).isEqualTo("CL Paris");
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
assertThat(o.getEmail()).isEqualTo("contact@club.fr");
|
||||
assertThat(o.getTelephone()).isEqualTo("+33100000000");
|
||||
assertThat(o.getNombreMembres()).isEqualTo(50);
|
||||
assertThat(o.getEstOrganisationRacine()).isTrue();
|
||||
assertThat(o.getAccepteNouveauxMembres()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("description, numeroEnregistrement, dateFondation")
|
||||
void descriptionEtEnregistrement() {
|
||||
Organisation o = baseOrganisation();
|
||||
LocalDate fondation = LocalDate.of(2010, 6, 15);
|
||||
o.setDescription("Un club de bienfaisance");
|
||||
o.setNumeroEnregistrement("REG-2010-00123");
|
||||
o.setDateFondation(fondation);
|
||||
|
||||
assertThat(o.getDescription()).isEqualTo("Un club de bienfaisance");
|
||||
assertThat(o.getNumeroEnregistrement()).isEqualTo("REG-2010-00123");
|
||||
assertThat(o.getDateFondation()).isEqualTo(fondation);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("telephoneSecondaire et emailSecondaire")
|
||||
void contactsSecondaires() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setTelephoneSecondaire("+33100000099");
|
||||
o.setEmailSecondaire("info@club.fr");
|
||||
|
||||
assertThat(o.getTelephoneSecondaire()).isEqualTo("+33100000099");
|
||||
assertThat(o.getEmailSecondaire()).isEqualTo("info@club.fr");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("adresse, ville, region, pays, codePostal")
|
||||
void adresseComplete() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setAdresse("12 rue de la Paix");
|
||||
o.setVille("Abidjan");
|
||||
o.setRegion("Lagunes");
|
||||
o.setPays("Côte d'Ivoire");
|
||||
o.setCodePostal("01 BP 1234");
|
||||
|
||||
assertThat(o.getAdresse()).isEqualTo("12 rue de la Paix");
|
||||
assertThat(o.getVille()).isEqualTo("Abidjan");
|
||||
assertThat(o.getRegion()).isEqualTo("Lagunes");
|
||||
assertThat(o.getPays()).isEqualTo("Côte d'Ivoire");
|
||||
assertThat(o.getCodePostal()).isEqualTo("01 BP 1234");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("latitude et longitude")
|
||||
void coordonneesGeographiques() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setLatitude(new BigDecimal("5.354680"));
|
||||
o.setLongitude(new BigDecimal("-4.001430"));
|
||||
|
||||
assertThat(o.getLatitude()).isEqualByComparingTo("5.354680");
|
||||
assertThat(o.getLongitude()).isEqualByComparingTo("-4.001430");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("siteWeb, logo, reseauxSociaux")
|
||||
void webEtReseaux() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setSiteWeb("https://club-lions-paris.fr");
|
||||
o.setLogo("https://cdn.example.com/logo.png");
|
||||
o.setReseauxSociaux("{\"twitter\":\"@clublions\"}");
|
||||
|
||||
assertThat(o.getSiteWeb()).isEqualTo("https://club-lions-paris.fr");
|
||||
assertThat(o.getLogo()).isEqualTo("https://cdn.example.com/logo.png");
|
||||
assertThat(o.getReseauxSociaux()).isEqualTo("{\"twitter\":\"@clublions\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("niveauHierarchique, cheminHierarchique, organisationParente")
|
||||
void hierarchie() {
|
||||
Organisation parent = baseOrganisation();
|
||||
parent.setId(UUID.randomUUID());
|
||||
|
||||
Organisation enfant = baseOrganisation();
|
||||
enfant.setNom("Sous-club Lions");
|
||||
enfant.setEmail("sous@club.fr");
|
||||
enfant.setOrganisationParente(parent);
|
||||
enfant.setNiveauHierarchique(1);
|
||||
enfant.setCheminHierarchique("/" + parent.getId());
|
||||
enfant.setEstOrganisationRacine(false);
|
||||
|
||||
assertThat(enfant.getOrganisationParente()).isEqualTo(parent);
|
||||
assertThat(enfant.getNiveauHierarchique()).isEqualTo(1);
|
||||
assertThat(enfant.getCheminHierarchique()).startsWith("/");
|
||||
assertThat(enfant.getEstOrganisationRacine()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("nombreAdministrateurs")
|
||||
void nombreAdministrateurs() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreAdministrateurs(5);
|
||||
assertThat(o.getNombreAdministrateurs()).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("budgetAnnuel, devise, cotisationObligatoire, montantCotisationAnnuelle")
|
||||
void finances() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setBudgetAnnuel(new BigDecimal("5000000.00"));
|
||||
o.setDevise("XOF");
|
||||
o.setCotisationObligatoire(true);
|
||||
o.setMontantCotisationAnnuelle(new BigDecimal("120000.00"));
|
||||
|
||||
assertThat(o.getBudgetAnnuel()).isEqualByComparingTo("5000000.00");
|
||||
assertThat(o.getDevise()).isEqualTo("XOF");
|
||||
assertThat(o.getCotisationObligatoire()).isTrue();
|
||||
assertThat(o.getMontantCotisationAnnuelle()).isEqualByComparingTo("120000.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("objectifs, activitesPrincipales, certifications, partenaires, notes")
|
||||
void informationsComplementaires() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setObjectifs("Aide humanitaire");
|
||||
o.setActivitesPrincipales("Collecte de fonds, bénévolat");
|
||||
o.setCertifications("ISO 9001");
|
||||
o.setPartenaires("Croix-Rouge, ONU");
|
||||
o.setNotes("Organisation fondée par des bénévoles");
|
||||
|
||||
assertThat(o.getObjectifs()).isEqualTo("Aide humanitaire");
|
||||
assertThat(o.getActivitesPrincipales()).isEqualTo("Collecte de fonds, bénévolat");
|
||||
assertThat(o.getCertifications()).isEqualTo("ISO 9001");
|
||||
assertThat(o.getPartenaires()).isEqualTo("Croix-Rouge, ONU");
|
||||
assertThat(o.getNotes()).isEqualTo("Organisation fondée par des bénévoles");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("organisationPublique")
|
||||
void organisationPublique() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setOrganisationPublique(false);
|
||||
assertThat(o.getOrganisationPublique()).isFalse();
|
||||
o.setOrganisationPublique(true);
|
||||
assertThat(o.getOrganisationPublique()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Relations : membresOrganisations, adresses, comptesWave")
|
||||
void relations() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setMembresOrganisations(new ArrayList<>());
|
||||
o.setAdresses(new ArrayList<>());
|
||||
o.setComptesWave(new ArrayList<>());
|
||||
|
||||
assertThat(o.getMembresOrganisations()).isNotNull().isEmpty();
|
||||
assertThat(o.getAdresses()).isNotNull().isEmpty();
|
||||
assertThat(o.getComptesWave()).isNotNull().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Champs hérités de BaseEntity (id, dateCreation, creePar, modifiePar, version, actif)")
|
||||
void champsBaseEntity() {
|
||||
UUID id = UUID.randomUUID();
|
||||
Organisation o = baseOrganisation();
|
||||
o.setId(id);
|
||||
o.setCreePar("admin@unionflow.dev");
|
||||
o.setModifiePar("manager@unionflow.dev");
|
||||
o.setVersion(2L);
|
||||
o.setActif(true);
|
||||
|
||||
assertThat(o.getId()).isEqualTo(id);
|
||||
assertThat(o.getCreePar()).isEqualTo("admin@unionflow.dev");
|
||||
assertThat(o.getModifiePar()).isEqualTo("manager@unionflow.dev");
|
||||
assertThat(o.getVersion()).isEqualTo(2L);
|
||||
assertThat(o.getActif()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAncienneteAnnees et isRecente")
|
||||
void anciennete() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("X");
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail("x@y.com");
|
||||
o.setDateFondation(LocalDate.now().minusYears(5));
|
||||
assertThat(o.getAncienneteAnnees()).isEqualTo(5);
|
||||
assertThat(o.isRecente()).isFalse();
|
||||
o.setDateFondation(LocalDate.now().minusYears(1));
|
||||
assertThat(o.isRecente()).isTrue();
|
||||
// ─── Builder ──────────────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Builder Lombok")
|
||||
class BuilderTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Builder avec champs obligatoires")
|
||||
void builderChampsObligatoires() {
|
||||
Organisation o = Organisation.builder()
|
||||
.nom("Association Solidarité")
|
||||
.typeOrganisation("ASSOCIATION")
|
||||
.statut("ACTIVE")
|
||||
.email("contact@solidarite.ci")
|
||||
.build();
|
||||
|
||||
assertThat(o.getNom()).isEqualTo("Association Solidarité");
|
||||
assertThat(o.getTypeOrganisation()).isEqualTo("ASSOCIATION");
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
assertThat(o.getEmail()).isEqualTo("contact@solidarite.ci");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Builder : valeurs @Builder.Default")
|
||||
void builderDefaults() {
|
||||
Organisation o = Organisation.builder()
|
||||
.nom("Coopérative Test")
|
||||
.typeOrganisation("COOPERATIVE")
|
||||
.statut("ACTIVE")
|
||||
.email("coop@test.ci")
|
||||
.build();
|
||||
|
||||
assertThat(o.getNiveauHierarchique()).isEqualTo(0);
|
||||
assertThat(o.getEstOrganisationRacine()).isTrue();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(0);
|
||||
assertThat(o.getNombreAdministrateurs()).isEqualTo(0);
|
||||
assertThat(o.getDevise()).isEqualTo("XOF");
|
||||
assertThat(o.getCotisationObligatoire()).isFalse();
|
||||
assertThat(o.getOrganisationPublique()).isTrue();
|
||||
assertThat(o.getAccepteNouveauxMembres()).isTrue();
|
||||
assertThat(o.getMembresOrganisations()).isNotNull().isEmpty();
|
||||
assertThat(o.getAdresses()).isNotNull().isEmpty();
|
||||
assertThat(o.getComptesWave()).isNotNull().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Builder avec tous les champs facultatifs")
|
||||
void builderChampsOptionnels() {
|
||||
LocalDate fondation = LocalDate.of(2000, 1, 1);
|
||||
Organisation parent = baseOrganisation();
|
||||
parent.setId(UUID.randomUUID());
|
||||
|
||||
Organisation o = Organisation.builder()
|
||||
.nom("Lions Club Abidjan")
|
||||
.nomCourt("LCA")
|
||||
.typeOrganisation("LIONS")
|
||||
.statut("ACTIVE")
|
||||
.email("lions@abidjan.ci")
|
||||
.telephone("+22520000000")
|
||||
.telephoneSecondaire("+22521000000")
|
||||
.emailSecondaire("info@lions.ci")
|
||||
.description("Club Lions International")
|
||||
.dateFondation(fondation)
|
||||
.numeroEnregistrement("LCA-2000-001")
|
||||
.adresse("Plateau, Av. de la République")
|
||||
.ville("Abidjan")
|
||||
.region("Lagunes")
|
||||
.pays("Côte d'Ivoire")
|
||||
.codePostal("01 BP 100")
|
||||
.latitude(new BigDecimal("5.354"))
|
||||
.longitude(new BigDecimal("-4.001"))
|
||||
.siteWeb("https://lions.ci")
|
||||
.logo("https://cdn.lions.ci/logo.png")
|
||||
.reseauxSociaux("{\"facebook\":\"lionsabidjan\"}")
|
||||
.organisationParente(parent)
|
||||
.niveauHierarchique(1)
|
||||
.estOrganisationRacine(false)
|
||||
.cheminHierarchique("/" + parent.getId())
|
||||
.nombreMembres(120)
|
||||
.nombreAdministrateurs(8)
|
||||
.budgetAnnuel(new BigDecimal("10000000.00"))
|
||||
.devise("XOF")
|
||||
.cotisationObligatoire(true)
|
||||
.montantCotisationAnnuelle(new BigDecimal("100000.00"))
|
||||
.objectifs("Service humanitaire")
|
||||
.activitesPrincipales("Actions sociales")
|
||||
.certifications("Lions International")
|
||||
.partenaires("UNICEF")
|
||||
.notes("Fondé par des membres engagés")
|
||||
.organisationPublique(true)
|
||||
.accepteNouveauxMembres(true)
|
||||
.build();
|
||||
|
||||
assertThat(o.getNomCourt()).isEqualTo("LCA");
|
||||
assertThat(o.getDescription()).isEqualTo("Club Lions International");
|
||||
assertThat(o.getDateFondation()).isEqualTo(fondation);
|
||||
assertThat(o.getNumeroEnregistrement()).isEqualTo("LCA-2000-001");
|
||||
assertThat(o.getVille()).isEqualTo("Abidjan");
|
||||
assertThat(o.getPays()).isEqualTo("Côte d'Ivoire");
|
||||
assertThat(o.getLatitude()).isEqualByComparingTo("5.354");
|
||||
assertThat(o.getLongitude()).isEqualByComparingTo("-4.001");
|
||||
assertThat(o.getSiteWeb()).isEqualTo("https://lions.ci");
|
||||
assertThat(o.getOrganisationParente()).isEqualTo(parent);
|
||||
assertThat(o.getNiveauHierarchique()).isEqualTo(1);
|
||||
assertThat(o.getEstOrganisationRacine()).isFalse();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(120);
|
||||
assertThat(o.getBudgetAnnuel()).isEqualByComparingTo("10000000.00");
|
||||
assertThat(o.getCotisationObligatoire()).isTrue();
|
||||
assertThat(o.getMontantCotisationAnnuelle()).isEqualByComparingTo("100000.00");
|
||||
assertThat(o.getObjectifs()).isEqualTo("Service humanitaire");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive")
|
||||
void isActive() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("X");
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail("x@y.com");
|
||||
o.setActif(true);
|
||||
assertThat(o.isActive()).isTrue();
|
||||
o.setStatut("SUSPENDUE");
|
||||
assertThat(o.isActive()).isFalse();
|
||||
// ─── Méthodes métier ──────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Méthodes métier")
|
||||
class MethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("getNomComplet() avec nomCourt non vide")
|
||||
void getNomComplet_avecNomCourt() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNomCourt("CL Paris");
|
||||
assertThat(o.getNomComplet()).isEqualTo("Club Lions Paris (CL Paris)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getNomComplet() avec nomCourt=null")
|
||||
void getNomComplet_nomCourtNull() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNomCourt(null);
|
||||
assertThat(o.getNomComplet()).isEqualTo("Club Lions Paris");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getNomComplet() avec nomCourt vide ('')")
|
||||
void getNomComplet_nomCourtVide() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNomCourt("");
|
||||
assertThat(o.getNomComplet()).isEqualTo("Club Lions Paris");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAncienneteAnnees() avec dateFondation=null retourne 0")
|
||||
void anciennete_dateFondationNull_retourneZero() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDateFondation(null);
|
||||
assertThat(o.getAncienneteAnnees()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getAncienneteAnnees() avec dateFondation il y a 5 ans retourne 5")
|
||||
void anciennete_cincAns_retourneCinq() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDateFondation(LocalDate.now().minusYears(5));
|
||||
assertThat(o.getAncienneteAnnees()).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isRecente() retourne false si ancienneté >= 2 ans")
|
||||
void isRecente_ancienneOrganisation_retourneFalse() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDateFondation(LocalDate.now().minusYears(3));
|
||||
assertThat(o.isRecente()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isRecente() retourne true si ancienneté < 2 ans")
|
||||
void isRecente_jeuneOrganisation_retourneTrue() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDateFondation(LocalDate.now().minusYears(1));
|
||||
assertThat(o.isRecente()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isRecente() retourne true si dateFondation=null (ancienneté=0 < 2)")
|
||||
void isRecente_dateFondationNull_retourneTrue() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDateFondation(null);
|
||||
assertThat(o.isRecente()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive() retourne true si statut=ACTIVE et actif=true")
|
||||
void isActive_activeEtActif_retourneTrue() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut("ACTIVE");
|
||||
o.setActif(true);
|
||||
assertThat(o.isActive()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive() retourne false si statut=SUSPENDUE")
|
||||
void isActive_suspendue_retourneFalse() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut("SUSPENDUE");
|
||||
o.setActif(true);
|
||||
assertThat(o.isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive() retourne false si actif=false")
|
||||
void isActive_inactif_retourneFalse() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut("ACTIVE");
|
||||
o.setActif(false);
|
||||
assertThat(o.isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive() retourne false si actif=null")
|
||||
void isActive_actifNull_retourneFalse() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut("ACTIVE");
|
||||
o.setActif(null);
|
||||
assertThat(o.isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ajouterMembre() incrémente nombreMembres")
|
||||
void ajouterMembre_incremente() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreMembres(10);
|
||||
o.ajouterMembre();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(11);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ajouterMembre() avec nombreMembres=null initialise à 1")
|
||||
void ajouterMembre_null_initialiseeA1() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreMembres(null);
|
||||
o.ajouterMembre();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("retirerMembre() décrémente nombreMembres")
|
||||
void retirerMembre_decremente() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreMembres(10);
|
||||
o.retirerMembre();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(9);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("retirerMembre() ne passe pas sous 0 quand nombreMembres=0")
|
||||
void retirerMembre_zero_resteAZero() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreMembres(0);
|
||||
o.retirerMembre();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("retirerMembre() ne fait rien si nombreMembres=null")
|
||||
void retirerMembre_null_neFaitRien() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreMembres(null);
|
||||
o.retirerMembre();
|
||||
assertThat(o.getNombreMembres()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("activer() met statut=ACTIVE et actif=true")
|
||||
void activer_metAJourStatutEtActif() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut("SUSPENDUE");
|
||||
o.setActif(false);
|
||||
o.activer("admin@unionflow.dev");
|
||||
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
assertThat(o.getActif()).isTrue();
|
||||
assertThat(o.getModifiePar()).isEqualTo("admin@unionflow.dev");
|
||||
assertThat(o.getDateModification()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("suspendre() met statut=SUSPENDUE et accepteNouveauxMembres=false")
|
||||
void suspendre_metAJourStatutEtMembres() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setAccepteNouveauxMembres(true);
|
||||
o.suspendre("manager@unionflow.dev");
|
||||
|
||||
assertThat(o.getStatut()).isEqualTo("SUSPENDUE");
|
||||
assertThat(o.getAccepteNouveauxMembres()).isFalse();
|
||||
assertThat(o.getModifiePar()).isEqualTo("manager@unionflow.dev");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("dissoudre() met statut=DISSOUTE, actif=false, accepteNouveauxMembres=false")
|
||||
void dissoudre_metAJourTousLesChamps() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setActif(true);
|
||||
o.setAccepteNouveauxMembres(true);
|
||||
o.dissoudre("liquidateur@unionflow.dev");
|
||||
|
||||
assertThat(o.getStatut()).isEqualTo("DISSOUTE");
|
||||
assertThat(o.getActif()).isFalse();
|
||||
assertThat(o.getAccepteNouveauxMembres()).isFalse();
|
||||
assertThat(o.getModifiePar()).isEqualTo("liquidateur@unionflow.dev");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ajouterMembre et retirerMembre")
|
||||
void ajouterRetirerMembre() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("X");
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail("x@y.com");
|
||||
o.setNombreMembres(10);
|
||||
o.ajouterMembre();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(11);
|
||||
o.retirerMembre();
|
||||
o.retirerMembre();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(9);
|
||||
// ─── @PrePersist onCreate ─────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("@PrePersist onCreate()")
|
||||
class OnCreate {
|
||||
|
||||
@Test
|
||||
@DisplayName("statut=null est initialisé à ACTIVE")
|
||||
void statut_null_initialiseeAACtive() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("statut déjà défini n'est pas écrasé")
|
||||
void statut_dejaDefini_nonEcrase() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setStatut("SUSPENDUE");
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getStatut()).isEqualTo("SUSPENDUE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("typeOrganisation=null est initialisé à ASSOCIATION")
|
||||
void typeOrganisation_null_initialiseeAAssociation() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setTypeOrganisation(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getTypeOrganisation()).isEqualTo("ASSOCIATION");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("typeOrganisation déjà défini n'est pas écrasé")
|
||||
void typeOrganisation_dejaDefini_nonEcrase() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setTypeOrganisation("COOPERATIVE");
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getTypeOrganisation()).isEqualTo("COOPERATIVE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("devise=null est initialisé à XOF")
|
||||
void devise_null_initialiseeAXof() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDevise(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("devise déjà défini n'est pas écrasé")
|
||||
void devise_dejaDefinie_nonEcrasee() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDevise("EUR");
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getDevise()).isEqualTo("EUR");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("niveauHierarchique=null est initialisé à 0")
|
||||
void niveauHierarchique_null_initialiseeAZero() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNiveauHierarchique(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getNiveauHierarchique()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estOrganisationRacine=null sans parent est initialisé à true")
|
||||
void estOrganisationRacine_null_sansParent_initialiseeATrue() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setEstOrganisationRacine(null);
|
||||
o.setOrganisationParente(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getEstOrganisationRacine()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estOrganisationRacine=null avec parent est initialisé à false")
|
||||
void estOrganisationRacine_null_avecParent_initialiseeAFalse() {
|
||||
Organisation parent = baseOrganisation();
|
||||
parent.setId(UUID.randomUUID());
|
||||
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNom("Sous-club");
|
||||
o.setEmail("sous@club.fr");
|
||||
o.setEstOrganisationRacine(null);
|
||||
o.setOrganisationParente(parent);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getEstOrganisationRacine()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estOrganisationRacine déjà défini n'est pas écrasé")
|
||||
void estOrganisationRacine_dejaDefini_nonEcrase() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setEstOrganisationRacine(false);
|
||||
o.setOrganisationParente(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getEstOrganisationRacine()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("nombreMembres=null est initialisé à 0")
|
||||
void nombreMembres_null_initialiseeAZero() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreMembres(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getNombreMembres()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("nombreAdministrateurs=null est initialisé à 0")
|
||||
void nombreAdministrateurs_null_initialiseeAZero() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setNombreAdministrateurs(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getNombreAdministrateurs()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("organisationPublique=null est initialisé à true")
|
||||
void organisationPublique_null_initialiseeATrue() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setOrganisationPublique(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getOrganisationPublique()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("accepteNouveauxMembres=null est initialisé à true")
|
||||
void accepteNouveauxMembres_null_initialiseeATrue() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setAccepteNouveauxMembres(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getAccepteNouveauxMembres()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("cotisationObligatoire=null est initialisé à false")
|
||||
void cotisationObligatoire_null_initialiseeAFalse() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setCotisationObligatoire(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getCotisationObligatoire()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() initialise aussi dateCreation et actif via BaseEntity")
|
||||
void onCreateInitialiseBaseEntity() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.setDateCreation(null);
|
||||
o.setActif(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getDateCreation()).isNotNull();
|
||||
assertThat(o.getActif()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() avec tous les champs null initialise toutes les valeurs par défaut")
|
||||
void onCreateTousChampNulls_initialiseDefaults() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("Test Org");
|
||||
o.setEmail("test@org.ci");
|
||||
// Tous les @Builder.Default sont null via new()
|
||||
o.setStatut(null);
|
||||
o.setTypeOrganisation(null);
|
||||
o.setDevise(null);
|
||||
o.setNiveauHierarchique(null);
|
||||
o.setEstOrganisationRacine(null);
|
||||
o.setOrganisationParente(null);
|
||||
o.setNombreMembres(null);
|
||||
o.setNombreAdministrateurs(null);
|
||||
o.setOrganisationPublique(null);
|
||||
o.setAccepteNouveauxMembres(null);
|
||||
o.setCotisationObligatoire(null);
|
||||
o.onCreate();
|
||||
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
assertThat(o.getTypeOrganisation()).isEqualTo("ASSOCIATION");
|
||||
assertThat(o.getDevise()).isEqualTo("XOF");
|
||||
assertThat(o.getNiveauHierarchique()).isEqualTo(0);
|
||||
assertThat(o.getEstOrganisationRacine()).isTrue();
|
||||
assertThat(o.getNombreMembres()).isEqualTo(0);
|
||||
assertThat(o.getNombreAdministrateurs()).isEqualTo(0);
|
||||
assertThat(o.getOrganisationPublique()).isTrue();
|
||||
assertThat(o.getAccepteNouveauxMembres()).isTrue();
|
||||
assertThat(o.getCotisationObligatoire()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("activer, suspendre, dissoudre")
|
||||
void activerSuspendreDissoudre() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("X");
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("SUSPENDUE");
|
||||
o.setEmail("x@y.com");
|
||||
o.activer("admin@test.com");
|
||||
assertThat(o.getStatut()).isEqualTo("ACTIVE");
|
||||
assertThat(o.getActif()).isTrue();
|
||||
o.suspendre("admin@test.com");
|
||||
assertThat(o.getStatut()).isEqualTo("SUSPENDUE");
|
||||
assertThat(o.getAccepteNouveauxMembres()).isFalse();
|
||||
o.dissoudre("admin@test.com");
|
||||
assertThat(o.getStatut()).isEqualTo("DISSOUTE");
|
||||
assertThat(o.getActif()).isFalse();
|
||||
// ─── Equals / HashCode / toString ────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("equals, hashCode et toString")
|
||||
class EgaliteEtToString {
|
||||
|
||||
@Test
|
||||
@DisplayName("Deux instances avec le même id sont égales")
|
||||
void equals_memeId_egales() {
|
||||
UUID id = UUID.randomUUID();
|
||||
Organisation a = buildOrganisation(id, "N", "e@e.com");
|
||||
Organisation b = buildOrganisation(id, "N", "e@e.com");
|
||||
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Deux instances avec des id différents ne sont pas égales")
|
||||
void equals_idsDifferents_pasEgales() {
|
||||
Organisation a = buildOrganisation(UUID.randomUUID(), "N1", "e1@e.com");
|
||||
Organisation b = buildOrganisation(UUID.randomUUID(), "N2", "e2@e.com");
|
||||
|
||||
assertThat(a).isNotEqualTo(b);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString() n'est pas null ni vide")
|
||||
void toString_nonNullNonVide() {
|
||||
Organisation o = baseOrganisation();
|
||||
assertThat(o.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString() contient le nom de l'organisation")
|
||||
void toString_contientNom() {
|
||||
Organisation o = baseOrganisation();
|
||||
assertThat(o.toString()).contains("Club Lions Paris");
|
||||
}
|
||||
|
||||
private Organisation buildOrganisation(UUID id, String nom, String email) {
|
||||
Organisation o = new Organisation();
|
||||
o.setId(id);
|
||||
o.setNom(nom);
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail(email);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
UUID id = UUID.randomUUID();
|
||||
Organisation a = new Organisation();
|
||||
a.setId(id);
|
||||
a.setNom("N");
|
||||
a.setTypeOrganisation("X");
|
||||
a.setStatut("ACTIVE");
|
||||
a.setEmail("e@e.com");
|
||||
Organisation b = new Organisation();
|
||||
b.setId(id);
|
||||
b.setNom("N");
|
||||
b.setTypeOrganisation("X");
|
||||
b.setStatut("ACTIVE");
|
||||
b.setEmail("e@e.com");
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
}
|
||||
// ─── marquerCommeModifie (hérité de BaseEntity) ──────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("toString non null")
|
||||
void toString_nonNull() {
|
||||
Organisation o = new Organisation();
|
||||
o.setNom("X");
|
||||
o.setTypeOrganisation("X");
|
||||
o.setStatut("ACTIVE");
|
||||
o.setEmail("x@y.com");
|
||||
assertThat(o.toString()).isNotNull().isNotEmpty();
|
||||
@Nested
|
||||
@DisplayName("marquerCommeModifie() — hérité de BaseEntity")
|
||||
class MarquerCommeModifie {
|
||||
|
||||
@Test
|
||||
@DisplayName("marquerCommeModifie() met à jour dateModification et modifiePar")
|
||||
void marquerCommeModifie_metAJourChamps() {
|
||||
Organisation o = baseOrganisation();
|
||||
o.marquerCommeModifie("operateur@unionflow.dev");
|
||||
|
||||
assertThat(o.getDateModification()).isNotNull();
|
||||
assertThat(o.getModifiePar()).isEqualTo("operateur@unionflow.dev");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,4 +78,32 @@ class PaiementObjetTest {
|
||||
po.setMontantApplique(BigDecimal.ONE);
|
||||
assertThat(po.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate initialise dateApplication si null")
|
||||
void onCreate_setsDateApplicationWhenNull() {
|
||||
PaiementObjet po = new PaiementObjet();
|
||||
po.setPaiement(newPaiement());
|
||||
po.setTypeObjetCible("COTISATION");
|
||||
po.setObjetCibleId(UUID.randomUUID());
|
||||
po.setMontantApplique(BigDecimal.ONE);
|
||||
// dateApplication est null
|
||||
|
||||
po.onCreate();
|
||||
|
||||
assertThat(po.getDateApplication()).isNotNull();
|
||||
assertThat(po.getActif()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate ne remplace pas une dateApplication existante")
|
||||
void onCreate_doesNotOverrideDateApplication() {
|
||||
LocalDateTime fixed = LocalDateTime.of(2026, 1, 1, 0, 0);
|
||||
PaiementObjet po = new PaiementObjet();
|
||||
po.setDateApplication(fixed);
|
||||
|
||||
po.onCreate();
|
||||
|
||||
assertThat(po.getDateApplication()).isEqualTo(fixed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.lions.unionflow.server.entity;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -44,6 +45,64 @@ class PermissionTest {
|
||||
assertThat(p.isCodeValide()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCodeValide: false si code null")
|
||||
void isCodeValide_null() {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
assertThat(p.isCodeValide()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCodeValide: false si contient ' > ' mais moins de 3 parties")
|
||||
void isCodeValide_twoPartsOnly() {
|
||||
Permission p = new Permission();
|
||||
p.setCode("A > B");
|
||||
assertThat(p.isCodeValide()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: code null + module/ressource/action renseignés → code généré")
|
||||
void onCreate_generatesCode_whenNullAndComponentsPresent() throws Exception {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
p.setModule("org");
|
||||
p.setRessource("membre");
|
||||
p.setAction("create");
|
||||
Method onCreate = Permission.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(p);
|
||||
assertThat(p.getCode()).isEqualTo("ORG > MEMBRE > CREATE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: code null + composants null → code reste null")
|
||||
void onCreate_codeRemainsNull_whenComponentsNull() throws Exception {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
p.setModule(null);
|
||||
p.setRessource(null);
|
||||
p.setAction(null);
|
||||
Method onCreate = Permission.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(p);
|
||||
assertThat(p.getCode()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: code déjà renseigné → non écrasé")
|
||||
void onCreate_existingCode_notOverwritten() throws Exception {
|
||||
Permission p = new Permission();
|
||||
p.setCode("X > Y > Z");
|
||||
p.setModule("other");
|
||||
p.setRessource("other");
|
||||
p.setAction("other");
|
||||
Method onCreate = Permission.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(p);
|
||||
assertThat(p.getCode()).isEqualTo("X > Y > Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
@@ -74,4 +133,61 @@ class PermissionTest {
|
||||
p.setAction("Z");
|
||||
assertThat(p.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
// ── Branch coverage manquantes ─────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* L85 branch manquante : code = "" (not null but isEmpty → true) avec composants présents
|
||||
* → couvre la branche `code != null && code.isEmpty()` (deuxième branche du ||)
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("onCreate: code vide (empty) + composants présents → code généré (branche isEmpty)")
|
||||
void onCreate_emptyCode_withComponents_generatesCode() throws Exception {
|
||||
Permission p = new Permission();
|
||||
p.setCode("");
|
||||
p.setModule("org");
|
||||
p.setRessource("membre");
|
||||
p.setAction("read");
|
||||
Method onCreate = Permission.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(p);
|
||||
assertThat(p.getCode()).isEqualTo("ORG > MEMBRE > READ");
|
||||
}
|
||||
|
||||
/**
|
||||
* L86 branch manquante : module != null, ressource != null, action == null
|
||||
* → la condition `module != null && ressource != null && action != null` est false (action null)
|
||||
* → code reste null
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("onCreate: module et ressource présents, action null → code reste null (branche action null)")
|
||||
void onCreate_moduleAndRessourcePresent_actionNull_codeRemainsNull() throws Exception {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
p.setModule("org");
|
||||
p.setRessource("membre");
|
||||
p.setAction(null);
|
||||
Method onCreate = Permission.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(p);
|
||||
assertThat(p.getCode()).isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* L86 branch manquante : module != null, ressource == null
|
||||
* → la condition `module != null && ressource != null && action != null` est false (ressource null)
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("onCreate: module présent, ressource null → code reste null (branche ressource null)")
|
||||
void onCreate_modulePresent_ressourceNull_codeRemainsNull() throws Exception {
|
||||
Permission p = new Permission();
|
||||
p.setCode(null);
|
||||
p.setModule("org");
|
||||
p.setRessource(null);
|
||||
p.setAction("create");
|
||||
Method onCreate = Permission.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(p);
|
||||
assertThat(p.getCode()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.abonnement.StatutSouscription;
|
||||
import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests de couverture pour SouscriptionOrganisation.
|
||||
* Couvre les branches manquantes de onCreate() et decrementerQuota().
|
||||
*/
|
||||
@DisplayName("SouscriptionOrganisation - branches manquantes")
|
||||
class SouscriptionOrganisationBranchTest {
|
||||
|
||||
// ── onCreate() ────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Branch manquante : formule != null mais quotaMax est déjà renseigné
|
||||
* → la ligne `quotaMax = formule.getMaxMembres()` n'est PAS exécutée.
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("onCreate: formule présente mais quotaMax déjà défini → quotaMax conservé")
|
||||
void onCreate_formuleNonNull_quotaMaxDejaDefini_conserveQuotaMax() throws Exception {
|
||||
FormuleAbonnement formule = new FormuleAbonnement();
|
||||
formule.setMaxMembres(50);
|
||||
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setDateDebut(LocalDate.now());
|
||||
s.setDateFin(LocalDate.now().plusMonths(1));
|
||||
s.setFormule(formule);
|
||||
s.setQuotaMax(100); // déjà défini → ne doit PAS être écrasé
|
||||
|
||||
Method onCreate = SouscriptionOrganisation.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(s);
|
||||
|
||||
// quotaMax reste 100, pas remplacé par formule.getMaxMembres() (50)
|
||||
assertThat(s.getQuotaMax()).isEqualTo(100);
|
||||
// les autres defaults sont positionnés
|
||||
assertThat(s.getStatut()).isEqualTo(StatutSouscription.ACTIVE);
|
||||
assertThat(s.getTypePeriode()).isEqualTo(TypePeriodeAbonnement.MENSUEL);
|
||||
assertThat(s.getQuotaUtilise()).isEqualTo(0);
|
||||
}
|
||||
|
||||
// ── decrementerQuota() ────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Branch manquante : quotaUtilise == 0 → la condition
|
||||
* `quotaUtilise != null && quotaUtilise > 0` est false, le quota ne change pas.
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("decrementerQuota: quotaUtilise=0 → reste 0 (pas de décrément)")
|
||||
void decrementerQuota_quotaUtiliseZero_resterAZero() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setDateDebut(LocalDate.now());
|
||||
s.setDateFin(LocalDate.now().plusMonths(1));
|
||||
s.setQuotaUtilise(0);
|
||||
|
||||
s.decrementerQuota();
|
||||
|
||||
assertThat(s.getQuotaUtilise()).isEqualTo(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Branche couverte pour référence : quotaUtilise null → décrement ignoré.
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("decrementerQuota: quotaUtilise=null → reste null")
|
||||
void decrementerQuota_quotaUtiliseNull_resterNull() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setDateDebut(LocalDate.now());
|
||||
s.setDateFin(LocalDate.now().plusMonths(1));
|
||||
s.setQuotaUtilise(null);
|
||||
|
||||
s.decrementerQuota();
|
||||
|
||||
assertThat(s.getQuotaUtilise()).isNull();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -132,4 +133,113 @@ class SouscriptionOrganisationTest {
|
||||
s.setDateFin(LocalDate.now().plusYears(1));
|
||||
assertThat(s.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isQuotaDepasse: false si quotaMax null")
|
||||
void isQuotaDepasse_quotaMaxNull_returnsFalse() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(newFormule());
|
||||
s.setQuotaMax(null);
|
||||
s.setQuotaUtilise(100);
|
||||
assertThat(s.isQuotaDepasse()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getPlacesRestantes: MAX_VALUE si quotaMax null")
|
||||
void getPlacesRestantes_quotaMaxNull_returnsMaxInt() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(newFormule());
|
||||
s.setQuotaMax(null);
|
||||
assertThat(s.getPlacesRestantes()).isEqualTo(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("incrementerQuota: quotaUtilise null → initialisé à 1")
|
||||
void incrementerQuota_nullQuota_initializesTo1() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(newFormule());
|
||||
s.setQuotaUtilise(null);
|
||||
s.incrementerQuota();
|
||||
assertThat(s.getQuotaUtilise()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("decrementerQuota: quotaUtilise=0 → ne descend pas")
|
||||
void decrementerQuota_zeroQuota_noChange() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(newFormule());
|
||||
s.setQuotaUtilise(0);
|
||||
s.decrementerQuota();
|
||||
assertThat(s.getQuotaUtilise()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isActive: false si statut SUSPENDUE")
|
||||
void isActive_statusSuspendue_returnsFalse() {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(newFormule());
|
||||
s.setDateDebut(LocalDate.now().minusMonths(1));
|
||||
s.setDateFin(LocalDate.now().plusMonths(1));
|
||||
s.setStatut(StatutSouscription.SUSPENDUE);
|
||||
assertThat(s.isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les défauts si null, copie quotaMax depuis formule")
|
||||
void onCreate_setsDefaults() throws Exception {
|
||||
FormuleAbonnement formule = newFormule(); // maxMembres=100
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(formule);
|
||||
s.setDateDebut(LocalDate.now());
|
||||
s.setDateFin(LocalDate.now().plusYears(1));
|
||||
s.setStatut(null);
|
||||
s.setTypePeriode(null);
|
||||
s.setQuotaUtilise(null);
|
||||
s.setQuotaMax(null);
|
||||
|
||||
Method onCreate = SouscriptionOrganisation.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(s);
|
||||
|
||||
assertThat(s.getStatut()).isEqualTo(StatutSouscription.ACTIVE);
|
||||
assertThat(s.getTypePeriode()).isEqualTo(TypePeriodeAbonnement.MENSUEL);
|
||||
assertThat(s.getQuotaUtilise()).isEqualTo(0);
|
||||
assertThat(s.getQuotaMax()).isEqualTo(100);
|
||||
}
|
||||
|
||||
// ── Branch coverage manquante ──────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* L118 branch manquante : formule == null → `if (formule != null && quotaMax == null)` → false (court-circuit)
|
||||
* → quotaMax reste null (ou tel quel), pas de NPE
|
||||
*/
|
||||
@Test
|
||||
@DisplayName("onCreate: formule == null → la branche quotaMax depuis formule n'est pas exécutée")
|
||||
void onCreate_formulesNull_quotaMaxUnchanged() throws Exception {
|
||||
SouscriptionOrganisation s = new SouscriptionOrganisation();
|
||||
s.setOrganisation(newOrganisation());
|
||||
s.setFormule(null); // formule == null → branche false (court-circuit)
|
||||
s.setDateDebut(LocalDate.now());
|
||||
s.setDateFin(LocalDate.now().plusYears(1));
|
||||
s.setStatut(null);
|
||||
s.setTypePeriode(null);
|
||||
s.setQuotaUtilise(null);
|
||||
s.setQuotaMax(null);
|
||||
|
||||
Method onCreate = SouscriptionOrganisation.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(s);
|
||||
|
||||
// les défauts sont positionnés, mais quotaMax reste null (formule est null)
|
||||
assertThat(s.getStatut()).isEqualTo(StatutSouscription.ACTIVE);
|
||||
assertThat(s.getTypePeriode()).isEqualTo(TypePeriodeAbonnement.MENSUEL);
|
||||
assertThat(s.getQuotaUtilise()).isEqualTo(0);
|
||||
assertThat(s.getQuotaMax()).isNull(); // formule null → quotaMax non initialisé
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.lions.unionflow.server.entity;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -26,6 +27,42 @@ class TemplateNotificationTest {
|
||||
assertThat(t.getLangue()).isEqualTo("fr");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: langue null → initialisée à 'fr'")
|
||||
void onCreate_langue_null_setsDefault() throws Exception {
|
||||
TemplateNotification t = new TemplateNotification();
|
||||
t.setCode("T1");
|
||||
t.setLangue(null);
|
||||
Method onCreate = TemplateNotification.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(t);
|
||||
assertThat(t.getLangue()).isEqualTo("fr");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: langue vide → initialisée à 'fr'")
|
||||
void onCreate_langue_empty_setsDefault() throws Exception {
|
||||
TemplateNotification t = new TemplateNotification();
|
||||
t.setCode("T2");
|
||||
t.setLangue("");
|
||||
Method onCreate = TemplateNotification.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(t);
|
||||
assertThat(t.getLangue()).isEqualTo("fr");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: langue déjà renseignée → non écrasée")
|
||||
void onCreate_langue_alreadySet_notOverwritten() throws Exception {
|
||||
TemplateNotification t = new TemplateNotification();
|
||||
t.setCode("T3");
|
||||
t.setLangue("en");
|
||||
Method onCreate = TemplateNotification.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(t);
|
||||
assertThat(t.getLangue()).isEqualTo("en");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("TransactionApproval")
|
||||
class TransactionApprovalTest {
|
||||
|
||||
private static Organisation newOrganisation() {
|
||||
Organisation o = new Organisation();
|
||||
o.setId(UUID.randomUUID());
|
||||
return o;
|
||||
}
|
||||
|
||||
private static ApproverAction approvedAction() {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setApproverId(UUID.randomUUID());
|
||||
a.setApproverName("Approver Test");
|
||||
a.setApproverRole("TRESORIER");
|
||||
a.setDecision("APPROVED");
|
||||
return a;
|
||||
}
|
||||
|
||||
private static ApproverAction pendingAction() {
|
||||
ApproverAction a = new ApproverAction();
|
||||
a.setApproverId(UUID.randomUUID());
|
||||
a.setApproverName("Approver Pending");
|
||||
a.setApproverRole("PRESIDENT");
|
||||
a.setDecision("PENDING");
|
||||
return a;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getRequiredApprovals
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("getRequiredApprovals: NONE renvoie 0")
|
||||
void getRequiredApprovals_none_returns0() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setRequiredLevel("NONE");
|
||||
assertThat(ta.getRequiredApprovals()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getRequiredApprovals: LEVEL1 renvoie 1")
|
||||
void getRequiredApprovals_level1_returns1() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setRequiredLevel("LEVEL1");
|
||||
assertThat(ta.getRequiredApprovals()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getRequiredApprovals: LEVEL2 renvoie 2")
|
||||
void getRequiredApprovals_level2_returns2() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setRequiredLevel("LEVEL2");
|
||||
assertThat(ta.getRequiredApprovals()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getRequiredApprovals: LEVEL3 renvoie 3")
|
||||
void getRequiredApprovals_level3_returns3() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setRequiredLevel("LEVEL3");
|
||||
assertThat(ta.getRequiredApprovals()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getRequiredApprovals: valeur inconnue renvoie 0 (default)")
|
||||
void getRequiredApprovals_default_returns0() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setRequiredLevel("INVALID");
|
||||
assertThat(ta.getRequiredApprovals()).isEqualTo(0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// countApprovals
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("countApprovals: aucun approbateur renvoie 0")
|
||||
void countApprovals_noApprovers_returns0() {
|
||||
TransactionApproval ta = TransactionApproval.builder()
|
||||
.transactionId(UUID.randomUUID())
|
||||
.transactionType("CONTRIBUTION")
|
||||
.amount(new BigDecimal("5000.00"))
|
||||
.requesterId(UUID.randomUUID())
|
||||
.requesterName("Test Requester")
|
||||
.requiredLevel("LEVEL1")
|
||||
.build();
|
||||
|
||||
assertThat(ta.countApprovals()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("countApprovals: seuls les APPROVED sont comptés")
|
||||
void countApprovals_mixedDecisions_countsApprovedOnly() {
|
||||
TransactionApproval ta = TransactionApproval.builder()
|
||||
.transactionId(UUID.randomUUID())
|
||||
.transactionType("DEPOSIT")
|
||||
.amount(new BigDecimal("10000.00"))
|
||||
.requesterId(UUID.randomUUID())
|
||||
.requesterName("Requester")
|
||||
.requiredLevel("LEVEL2")
|
||||
.build();
|
||||
|
||||
ta.addApproverAction(approvedAction());
|
||||
ta.addApproverAction(pendingAction());
|
||||
ta.addApproverAction(approvedAction());
|
||||
|
||||
assertThat(ta.countApprovals()).isEqualTo(2);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// hasAllApprovals
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("hasAllApprovals: NONE sans approbateur renvoie toujours true")
|
||||
void hasAllApprovals_none_alwaysTrue() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setRequiredLevel("NONE");
|
||||
assertThat(ta.hasAllApprovals()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("hasAllApprovals: LEVEL1 avec une approbation renvoie true")
|
||||
void hasAllApprovals_level1_oneApproval_true() {
|
||||
TransactionApproval ta = TransactionApproval.builder()
|
||||
.transactionId(UUID.randomUUID())
|
||||
.transactionType("CONTRIBUTION")
|
||||
.amount(new BigDecimal("1000.00"))
|
||||
.requesterId(UUID.randomUUID())
|
||||
.requesterName("Requester")
|
||||
.requiredLevel("LEVEL1")
|
||||
.build();
|
||||
|
||||
ta.addApproverAction(approvedAction());
|
||||
|
||||
assertThat(ta.hasAllApprovals()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("hasAllApprovals: LEVEL2 avec une seule approbation renvoie false")
|
||||
void hasAllApprovals_level2_onlyOneApproval_false() {
|
||||
TransactionApproval ta = TransactionApproval.builder()
|
||||
.transactionId(UUID.randomUUID())
|
||||
.transactionType("WITHDRAWAL")
|
||||
.amount(new BigDecimal("50000.00"))
|
||||
.requesterId(UUID.randomUUID())
|
||||
.requesterName("Requester")
|
||||
.requiredLevel("LEVEL2")
|
||||
.build();
|
||||
|
||||
ta.addApproverAction(approvedAction());
|
||||
|
||||
assertThat(ta.hasAllApprovals()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// addApproverAction
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("addApproverAction: ajoute l'action et positionne le parent")
|
||||
void addApproverAction_setsParentAndAdds() {
|
||||
TransactionApproval ta = TransactionApproval.builder()
|
||||
.transactionId(UUID.randomUUID())
|
||||
.transactionType("CONTRIBUTION")
|
||||
.amount(new BigDecimal("2000.00"))
|
||||
.requesterId(UUID.randomUUID())
|
||||
.requesterName("Requester")
|
||||
.requiredLevel("LEVEL1")
|
||||
.build();
|
||||
|
||||
ApproverAction action = pendingAction();
|
||||
ta.addApproverAction(action);
|
||||
|
||||
assertThat(ta.getApprovers()).hasSize(1);
|
||||
assertThat(action.getApproval()).isSameAs(ta);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isExpired
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isExpired: expiresAt null renvoie false")
|
||||
void isExpired_expiresAtNull_returnsFalse() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setExpiresAt(null);
|
||||
assertThat(ta.isExpired()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isExpired: expiresAt dans le passé renvoie true")
|
||||
void isExpired_expiredInPast_returnsTrue() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setExpiresAt(LocalDateTime.now().minusMinutes(1));
|
||||
assertThat(ta.isExpired()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isExpired: expiresAt dans le futur renvoie false")
|
||||
void isExpired_futureExpiry_returnsFalse() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setExpiresAt(LocalDateTime.now().plusDays(1));
|
||||
assertThat(ta.isExpired()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isPending
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isPending: statut PENDING renvoie true")
|
||||
void isPending_pending_returnsTrue() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setStatus("PENDING");
|
||||
assertThat(ta.isPending()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isPending: statut APPROVED renvoie false")
|
||||
void isPending_approved_returnsFalse() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setStatus("APPROVED");
|
||||
assertThat(ta.isPending()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// isCompleted
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("isCompleted: statut VALIDATED renvoie true")
|
||||
void isCompleted_validated_returnsTrue() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setStatus("VALIDATED");
|
||||
assertThat(ta.isCompleted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCompleted: statut REJECTED renvoie true")
|
||||
void isCompleted_rejected_returnsTrue() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setStatus("REJECTED");
|
||||
assertThat(ta.isCompleted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCompleted: statut CANCELLED renvoie true")
|
||||
void isCompleted_cancelled_returnsTrue() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setStatus("CANCELLED");
|
||||
assertThat(ta.isCompleted()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isCompleted: statut PENDING renvoie false")
|
||||
void isCompleted_pending_returnsFalse() {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setStatus("PENDING");
|
||||
assertThat(ta.isCompleted()).isFalse();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// onCreate (réflexion)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise createdAt, currency, status, expiresAt si null")
|
||||
void onCreate_initializesNullFields() throws Exception {
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setCreatedAt(null);
|
||||
ta.setCurrency(null);
|
||||
ta.setStatus(null);
|
||||
ta.setExpiresAt(null);
|
||||
|
||||
Method onCreate = TransactionApproval.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(ta);
|
||||
|
||||
assertThat(ta.getCreatedAt()).isNotNull();
|
||||
assertThat(ta.getCurrency()).isEqualTo("XOF");
|
||||
assertThat(ta.getStatus()).isEqualTo("PENDING");
|
||||
assertThat(ta.getExpiresAt()).isNotNull();
|
||||
// expiresAt doit être ~7 jours après createdAt
|
||||
assertThat(ta.getExpiresAt()).isAfter(ta.getCreatedAt());
|
||||
assertThat(ta.getExpiresAt()).isBeforeOrEqualTo(ta.getCreatedAt().plusDays(7).plusSeconds(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: ne remplace pas createdAt si déjà renseigné")
|
||||
void onCreate_doesNotOverrideExistingCreatedAt() throws Exception {
|
||||
LocalDateTime existingDate = LocalDateTime.of(2025, 3, 10, 9, 0);
|
||||
LocalDateTime existingExpiry = LocalDateTime.of(2025, 3, 17, 9, 0);
|
||||
|
||||
TransactionApproval ta = new TransactionApproval();
|
||||
ta.setCreatedAt(existingDate);
|
||||
ta.setCurrency("EUR");
|
||||
ta.setStatus("APPROVED");
|
||||
ta.setExpiresAt(existingExpiry);
|
||||
|
||||
Method onCreate = TransactionApproval.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(ta);
|
||||
|
||||
assertThat(ta.getCreatedAt()).isEqualTo(existingDate);
|
||||
assertThat(ta.getCurrency()).isEqualTo("EUR");
|
||||
assertThat(ta.getStatus()).isEqualTo("APPROVED");
|
||||
assertThat(ta.getExpiresAt()).isEqualTo(existingExpiry);
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,22 @@ import dev.lions.unionflow.server.api.enums.wave.StatutCompteWave;
|
||||
import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
|
||||
import dev.lions.unionflow.server.api.enums.wave.TypeTransactionWave;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("TransactionWave")
|
||||
@DisplayName("TransactionWave — couverture complète")
|
||||
class TransactionWaveTest {
|
||||
|
||||
// ─── Utilitaire ───────────────────────────────────────────────────────────
|
||||
|
||||
private static CompteWave newCompteWave() {
|
||||
CompteWave c = new CompteWave();
|
||||
c.setId(UUID.randomUUID());
|
||||
@@ -22,9 +28,7 @@ class TransactionWaveTest {
|
||||
return c;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("getters/setters")
|
||||
void gettersSetters() {
|
||||
private static TransactionWave baseTransaction() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setWaveTransactionId("wave-123");
|
||||
t.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
@@ -32,78 +36,545 @@ class TransactionWaveTest {
|
||||
t.setMontant(new BigDecimal("5000.00"));
|
||||
t.setCodeDevise("XOF");
|
||||
t.setCompteWave(newCompteWave());
|
||||
|
||||
assertThat(t.getWaveTransactionId()).isEqualTo("wave-123");
|
||||
assertThat(t.getTypeTransaction()).isEqualTo(TypeTransactionWave.DEPOT);
|
||||
assertThat(t.getStatutTransaction()).isEqualTo(StatutTransactionWave.REUSSIE);
|
||||
assertThat(t.getMontant()).isEqualByComparingTo("5000.00");
|
||||
return t;
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isReussie")
|
||||
void isReussie() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setWaveTransactionId("x");
|
||||
t.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
t.setMontant(BigDecimal.ONE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setCompteWave(newCompteWave());
|
||||
t.setStatutTransaction(StatutTransactionWave.REUSSIE);
|
||||
assertThat(t.isReussie()).isTrue();
|
||||
t.setStatutTransaction(StatutTransactionWave.ECHOUE);
|
||||
assertThat(t.isReussie()).isFalse();
|
||||
// ─── Getters / Setters ────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Getters et setters")
|
||||
class GettersSetters {
|
||||
|
||||
@Test
|
||||
@DisplayName("Champs de base déjà couverts")
|
||||
void champsDeBase() {
|
||||
TransactionWave t = baseTransaction();
|
||||
|
||||
assertThat(t.getWaveTransactionId()).isEqualTo("wave-123");
|
||||
assertThat(t.getTypeTransaction()).isEqualTo(TypeTransactionWave.DEPOT);
|
||||
assertThat(t.getStatutTransaction()).isEqualTo(StatutTransactionWave.REUSSIE);
|
||||
assertThat(t.getMontant()).isEqualByComparingTo("5000.00");
|
||||
assertThat(t.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(t.getCompteWave()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("waveRequestId et waveReference")
|
||||
void waveRequestIdEtReference() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setWaveRequestId("req-abc-456");
|
||||
t.setWaveReference("ref-xyz-789");
|
||||
|
||||
assertThat(t.getWaveRequestId()).isEqualTo("req-abc-456");
|
||||
assertThat(t.getWaveReference()).isEqualTo("ref-xyz-789");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("frais, montantNet")
|
||||
void fraisEtMontantNet() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setFrais(new BigDecimal("150.00"));
|
||||
t.setMontantNet(new BigDecimal("4850.00"));
|
||||
|
||||
assertThat(t.getFrais()).isEqualByComparingTo("150.00");
|
||||
assertThat(t.getMontantNet()).isEqualByComparingTo("4850.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("telephonePayeur et telephoneBeneficiaire")
|
||||
void telephones() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setTelephonePayeur("+22507111111");
|
||||
t.setTelephoneBeneficiaire("+22507222222");
|
||||
|
||||
assertThat(t.getTelephonePayeur()).isEqualTo("+22507111111");
|
||||
assertThat(t.getTelephoneBeneficiaire()).isEqualTo("+22507222222");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("metadonnees et reponseWaveApi")
|
||||
void metadonneesEtReponse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setMetadonnees("{\"key\":\"val\"}");
|
||||
t.setReponseWaveApi("{\"status\":\"success\"}");
|
||||
|
||||
assertThat(t.getMetadonnees()).isEqualTo("{\"key\":\"val\"}");
|
||||
assertThat(t.getReponseWaveApi()).isEqualTo("{\"status\":\"success\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("nombreTentatives, dateDerniereTentative, messageErreur")
|
||||
void tentativesEtErreur() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setNombreTentatives(3);
|
||||
t.setDateDerniereTentative(now);
|
||||
t.setMessageErreur("Délai dépassé");
|
||||
|
||||
assertThat(t.getNombreTentatives()).isEqualTo(3);
|
||||
assertThat(t.getDateDerniereTentative()).isEqualTo(now);
|
||||
assertThat(t.getMessageErreur()).isEqualTo("Délai dépassé");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("webhooks — liste modifiable")
|
||||
void webhooks() {
|
||||
TransactionWave t = baseTransaction();
|
||||
List<WebhookWave> webhooks = new ArrayList<>();
|
||||
WebhookWave wh = new WebhookWave();
|
||||
wh.setWaveEventId("evt-001");
|
||||
webhooks.add(wh);
|
||||
t.setWebhooks(webhooks);
|
||||
|
||||
assertThat(t.getWebhooks()).hasSize(1);
|
||||
assertThat(t.getWebhooks().get(0).getWaveEventId()).isEqualTo("evt-001");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Champs hérités de BaseEntity (id, dateCreation, creePar, modifiePar, version, actif)")
|
||||
void champsBaseEntity() {
|
||||
UUID id = UUID.randomUUID();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setId(id);
|
||||
t.setDateCreation(now);
|
||||
t.setDateModification(now);
|
||||
t.setCreePar("admin@test.com");
|
||||
t.setModifiePar("user@test.com");
|
||||
t.setVersion(1L);
|
||||
t.setActif(true);
|
||||
|
||||
assertThat(t.getId()).isEqualTo(id);
|
||||
assertThat(t.getDateCreation()).isEqualTo(now);
|
||||
assertThat(t.getDateModification()).isEqualTo(now);
|
||||
assertThat(t.getCreePar()).isEqualTo("admin@test.com");
|
||||
assertThat(t.getModifiePar()).isEqualTo("user@test.com");
|
||||
assertThat(t.getVersion()).isEqualTo(1L);
|
||||
assertThat(t.getActif()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee")
|
||||
void peutEtreRetentee() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setWaveTransactionId("x");
|
||||
t.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
t.setMontant(BigDecimal.ONE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setCompteWave(newCompteWave());
|
||||
t.setStatutTransaction(StatutTransactionWave.ECHOUE);
|
||||
t.setNombreTentatives(2);
|
||||
assertThat(t.peutEtreRetentee()).isTrue();
|
||||
t.setNombreTentatives(5);
|
||||
assertThat(t.peutEtreRetentee()).isFalse();
|
||||
// ─── Builder ──────────────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Builder Lombok")
|
||||
class BuilderTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Builder avec tous les champs obligatoires")
|
||||
void builderChampsObligatoires() {
|
||||
CompteWave compte = newCompteWave();
|
||||
TransactionWave t = TransactionWave.builder()
|
||||
.waveTransactionId("builder-wave-001")
|
||||
.typeTransaction(TypeTransactionWave.PAIEMENT)
|
||||
.statutTransaction(StatutTransactionWave.EN_ATTENTE)
|
||||
.montant(new BigDecimal("10000.00"))
|
||||
.codeDevise("XOF")
|
||||
.compteWave(compte)
|
||||
.build();
|
||||
|
||||
assertThat(t.getWaveTransactionId()).isEqualTo("builder-wave-001");
|
||||
assertThat(t.getTypeTransaction()).isEqualTo(TypeTransactionWave.PAIEMENT);
|
||||
assertThat(t.getStatutTransaction()).isEqualTo(StatutTransactionWave.EN_ATTENTE);
|
||||
assertThat(t.getMontant()).isEqualByComparingTo("10000.00");
|
||||
assertThat(t.getCodeDevise()).isEqualTo("XOF");
|
||||
assertThat(t.getCompteWave()).isEqualTo(compte);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Builder : valeurs @Builder.Default — statutTransaction=INITIALISE, nombreTentatives=0, webhooks vide")
|
||||
void builderDefaults() {
|
||||
CompteWave compte = newCompteWave();
|
||||
TransactionWave t = TransactionWave.builder()
|
||||
.waveTransactionId("builder-wave-defaults")
|
||||
.typeTransaction(TypeTransactionWave.RETRAIT)
|
||||
.montant(new BigDecimal("500.00"))
|
||||
.codeDevise("XOF")
|
||||
.compteWave(compte)
|
||||
.build();
|
||||
|
||||
assertThat(t.getStatutTransaction()).isEqualTo(StatutTransactionWave.INITIALISE);
|
||||
assertThat(t.getNombreTentatives()).isEqualTo(0);
|
||||
assertThat(t.getWebhooks()).isNotNull().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Builder avec tous les champs facultatifs")
|
||||
void builderChampsOptionnels() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
CompteWave compte = newCompteWave();
|
||||
TransactionWave t = TransactionWave.builder()
|
||||
.waveTransactionId("builder-wave-full")
|
||||
.waveRequestId("req-full-001")
|
||||
.waveReference("ref-full-001")
|
||||
.typeTransaction(TypeTransactionWave.TRANSFERT)
|
||||
.statutTransaction(StatutTransactionWave.REUSSIE)
|
||||
.montant(new BigDecimal("20000.00"))
|
||||
.frais(new BigDecimal("200.00"))
|
||||
.montantNet(new BigDecimal("19800.00"))
|
||||
.codeDevise("XOF")
|
||||
.telephonePayeur("+22507001001")
|
||||
.telephoneBeneficiaire("+22507002002")
|
||||
.metadonnees("{}")
|
||||
.reponseWaveApi("{\"code\":\"200\"}")
|
||||
.nombreTentatives(1)
|
||||
.dateDerniereTentative(now)
|
||||
.messageErreur(null)
|
||||
.compteWave(compte)
|
||||
.build();
|
||||
|
||||
assertThat(t.getWaveRequestId()).isEqualTo("req-full-001");
|
||||
assertThat(t.getWaveReference()).isEqualTo("ref-full-001");
|
||||
assertThat(t.getFrais()).isEqualByComparingTo("200.00");
|
||||
assertThat(t.getMontantNet()).isEqualByComparingTo("19800.00");
|
||||
assertThat(t.getTelephonePayeur()).isEqualTo("+22507001001");
|
||||
assertThat(t.getTelephoneBeneficiaire()).isEqualTo("+22507002002");
|
||||
assertThat(t.getMetadonnees()).isEqualTo("{}");
|
||||
assertThat(t.getReponseWaveApi()).isEqualTo("{\"code\":\"200\"}");
|
||||
assertThat(t.getNombreTentatives()).isEqualTo(1);
|
||||
assertThat(t.getDateDerniereTentative()).isEqualTo(now);
|
||||
assertThat(t.getMessageErreur()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
UUID id = UUID.randomUUID();
|
||||
CompteWave c = newCompteWave();
|
||||
TransactionWave a = new TransactionWave();
|
||||
a.setId(id);
|
||||
a.setWaveTransactionId("w1");
|
||||
a.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
a.setStatutTransaction(StatutTransactionWave.REUSSIE);
|
||||
a.setMontant(BigDecimal.ONE);
|
||||
a.setCodeDevise("XOF");
|
||||
a.setCompteWave(c);
|
||||
TransactionWave b = new TransactionWave();
|
||||
b.setId(id);
|
||||
b.setWaveTransactionId("w1");
|
||||
b.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
b.setStatutTransaction(StatutTransactionWave.REUSSIE);
|
||||
b.setMontant(BigDecimal.ONE);
|
||||
b.setCodeDevise("XOF");
|
||||
b.setCompteWave(c);
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
// ─── Méthodes métier ──────────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("Méthodes métier")
|
||||
class MethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("isReussie() retourne true si statut=REUSSIE")
|
||||
void isReussie_statutReussie_retourneTrue() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.REUSSIE);
|
||||
assertThat(t.isReussie()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isReussie() retourne false si statut=ECHOUE")
|
||||
void isReussie_statutEchoue_retourneFalse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.ECHOUE);
|
||||
assertThat(t.isReussie()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("isReussie() retourne false si statut=INITIALISE")
|
||||
void isReussie_statutInitialise_retourneFalse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
assertThat(t.isReussie()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne true si statut=ECHOUE et tentatives<5")
|
||||
void peutEtreRetentee_echoue_tentativesFaibles_retourneTrue() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.ECHOUE);
|
||||
t.setNombreTentatives(2);
|
||||
assertThat(t.peutEtreRetentee()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne true si statut=EXPIRED et tentatives<5")
|
||||
void peutEtreRetentee_expired_tentativesFaibles_retourneTrue() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.EXPIRED);
|
||||
t.setNombreTentatives(0);
|
||||
assertThat(t.peutEtreRetentee()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne false si tentatives=5")
|
||||
void peutEtreRetentee_tentativesMax_retourneFalse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.ECHOUE);
|
||||
t.setNombreTentatives(5);
|
||||
assertThat(t.peutEtreRetentee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne false si statut=REUSSIE")
|
||||
void peutEtreRetentee_statutReussie_retourneFalse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.REUSSIE);
|
||||
t.setNombreTentatives(1);
|
||||
assertThat(t.peutEtreRetentee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne true si nombreTentatives=null")
|
||||
void peutEtreRetentee_tentativesNull_retourneTrue() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.ECHOUE);
|
||||
t.setNombreTentatives(null);
|
||||
assertThat(t.peutEtreRetentee()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne false si statut=INITIALISE")
|
||||
void peutEtreRetentee_statutInitialise_retourneFalse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setNombreTentatives(1);
|
||||
assertThat(t.peutEtreRetentee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetentee() retourne false si statut=ANNULEE")
|
||||
void peutEtreRetentee_statutAnnulee_retourneFalse() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setStatutTransaction(StatutTransactionWave.ANNULEE);
|
||||
t.setNombreTentatives(0);
|
||||
assertThat(t.peutEtreRetentee()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString non null")
|
||||
void toString_nonNull() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setWaveTransactionId("x");
|
||||
t.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
t.setMontant(BigDecimal.ONE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setCompteWave(newCompteWave());
|
||||
assertThat(t.toString()).isNotNull().isNotEmpty();
|
||||
// ─── @PrePersist onCreate ─────────────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("@PrePersist onCreate()")
|
||||
class OnCreate {
|
||||
|
||||
@Test
|
||||
@DisplayName("statutTransaction=null est initialisé à INITIALISE")
|
||||
void statutTransactionNull_initialiseeAInitialise() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(null);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getStatutTransaction()).isEqualTo(StatutTransactionWave.INITIALISE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("statutTransaction déjà défini n'est pas écrasé")
|
||||
void statutTransactionDejaDefini_nonEcrase() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.EN_COURS);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getStatutTransaction()).isEqualTo(StatutTransactionWave.EN_COURS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("codeDevise=null est initialisé à XOF")
|
||||
void codeDeviseNull_initialiseeAXof() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise(null);
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("codeDevise vide ('') est initialisé à XOF")
|
||||
void codeDeviseVide_initialiseeAXof() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("codeDevise déjà défini n'est pas écrasé")
|
||||
void codeDeviseDejaDefini_nonEcrase() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("EUR");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getCodeDevise()).isEqualTo("EUR");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("nombreTentatives=null est initialisé à 0")
|
||||
void nombreTentativesNull_initialiseeAZero() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(null);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getNombreTentatives()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("nombreTentatives déjà défini n'est pas écrasé")
|
||||
void nombreTentativesDejaDefini_nonEcrase() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(3);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getNombreTentatives()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("montantNet=null est calculé quand montant et frais sont définis")
|
||||
void montantNetNull_calculeDepuisMontantEtFrais() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("5000.00"));
|
||||
t.setFrais(new BigDecimal("150.00"));
|
||||
t.setMontantNet(null);
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getMontantNet()).isEqualByComparingTo("4850.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("montantNet=null n'est pas calculé si frais=null")
|
||||
void montantNetNull_nonCalculeSiFraisNull() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("5000.00"));
|
||||
t.setFrais(null);
|
||||
t.setMontantNet(null);
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getMontantNet()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("montantNet=null n'est pas calculé si montant=null")
|
||||
void montantNetNull_nonCalculeSiMontantNull() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(null);
|
||||
t.setFrais(new BigDecimal("150.00"));
|
||||
t.setMontantNet(null);
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getMontantNet()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("montantNet déjà défini n'est pas recalculé")
|
||||
void montantNetDejaDefini_nonRecalcule() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("5000.00"));
|
||||
t.setFrais(new BigDecimal("150.00"));
|
||||
t.setMontantNet(new BigDecimal("9999.00"));
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getMontantNet()).isEqualByComparingTo("9999.00");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate() initialise aussi dateCreation et actif via BaseEntity")
|
||||
void onCreateInitialiseBaseEntity() {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setStatutTransaction(StatutTransactionWave.INITIALISE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setNombreTentatives(0);
|
||||
t.setMontant(new BigDecimal("1000.00"));
|
||||
t.setDateCreation(null);
|
||||
t.setActif(null);
|
||||
t.onCreate();
|
||||
|
||||
assertThat(t.getDateCreation()).isNotNull();
|
||||
assertThat(t.getActif()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Equals / HashCode / toString ────────────────────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("equals, hashCode et toString")
|
||||
class EgaliteEtToString {
|
||||
|
||||
@Test
|
||||
@DisplayName("Deux instances avec le même id sont égales")
|
||||
void equals_memeId_egales() {
|
||||
UUID id = UUID.randomUUID();
|
||||
CompteWave c = newCompteWave();
|
||||
|
||||
TransactionWave a = buildTransaction(id, "w1", c);
|
||||
TransactionWave b = buildTransaction(id, "w1", c);
|
||||
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Deux instances avec des id différents ne sont pas égales")
|
||||
void equals_idsDifferents_pasEgales() {
|
||||
TransactionWave a = buildTransaction(UUID.randomUUID(), "w1", newCompteWave());
|
||||
TransactionWave b = buildTransaction(UUID.randomUUID(), "w2", newCompteWave());
|
||||
|
||||
assertThat(a).isNotEqualTo(b);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString() n'est pas null ni vide")
|
||||
void toString_nonNullNonVide() {
|
||||
TransactionWave t = baseTransaction();
|
||||
assertThat(t.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("toString() contient le waveTransactionId")
|
||||
void toString_contientWaveTransactionId() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.setWaveTransactionId("wave-toString-test");
|
||||
assertThat(t.toString()).contains("wave-toString-test");
|
||||
}
|
||||
|
||||
private TransactionWave buildTransaction(UUID id, String waveId, CompteWave compte) {
|
||||
TransactionWave t = new TransactionWave();
|
||||
t.setId(id);
|
||||
t.setWaveTransactionId(waveId);
|
||||
t.setTypeTransaction(TypeTransactionWave.DEPOT);
|
||||
t.setStatutTransaction(StatutTransactionWave.REUSSIE);
|
||||
t.setMontant(BigDecimal.ONE);
|
||||
t.setCodeDevise("XOF");
|
||||
t.setCompteWave(compte);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── marquerCommeModifie (hérité de BaseEntity) ──────────────────────────
|
||||
|
||||
@Nested
|
||||
@DisplayName("marquerCommeModifie() — hérité de BaseEntity")
|
||||
class MarquerCommeModifie {
|
||||
|
||||
@Test
|
||||
@DisplayName("marquerCommeModifie() met à jour dateModification et modifiePar")
|
||||
void marquerCommeModifie_metAJourChamps() {
|
||||
TransactionWave t = baseTransaction();
|
||||
t.marquerCommeModifie("agent@unionflow.dev");
|
||||
|
||||
assertThat(t.getDateModification()).isNotNull();
|
||||
assertThat(t.getModifiePar()).isEqualTo("agent@unionflow.dev");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.lions.unionflow.server.entity;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -29,6 +30,34 @@ class TypeReferenceTest {
|
||||
assertThat(tr.getEstDefaut()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: domaine et code non-null → normalisés en majuscules")
|
||||
void onCreate_normalisesDomaineAndCode() throws Exception {
|
||||
TypeReference tr = new TypeReference();
|
||||
tr.setDomaine("statut_org");
|
||||
tr.setCode("active");
|
||||
tr.setLibelle("Actif");
|
||||
Method onCreate = TypeReference.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(tr);
|
||||
assertThat(tr.getDomaine()).isEqualTo("STATUT_ORG");
|
||||
assertThat(tr.getCode()).isEqualTo("ACTIVE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: domaine null → skipped (no NPE), code null → skipped")
|
||||
void onCreate_nullDomaineAndCode_skipped() throws Exception {
|
||||
TypeReference tr = new TypeReference();
|
||||
tr.setDomaine(null);
|
||||
tr.setCode(null);
|
||||
tr.setLibelle("L");
|
||||
Method onCreate = TypeReference.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(tr);
|
||||
assertThat(tr.getDomaine()).isNull();
|
||||
assertThat(tr.getCode()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
|
||||
@@ -6,6 +6,8 @@ import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -83,4 +85,69 @@ class ValidationEtapeDemandeTest {
|
||||
v.setStatut(StatutValidationEtape.EN_ATTENTE);
|
||||
assertThat(v.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estFinalisee: true pour REJETEE")
|
||||
void estFinalisee_rejetee() {
|
||||
ValidationEtapeDemande v = new ValidationEtapeDemande();
|
||||
v.setDemandeAide(newDemandeAide());
|
||||
v.setEtapeNumero(1);
|
||||
v.setStatut(StatutValidationEtape.REJETEE);
|
||||
assertThat(v.estFinalisee()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estFinalisee: true pour DELEGUEE")
|
||||
void estFinalisee_deleguee() {
|
||||
ValidationEtapeDemande v = new ValidationEtapeDemande();
|
||||
v.setDemandeAide(newDemandeAide());
|
||||
v.setEtapeNumero(1);
|
||||
v.setStatut(StatutValidationEtape.DELEGUEE);
|
||||
assertThat(v.estFinalisee()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("estFinalisee: true pour EXPIREE")
|
||||
void estFinalisee_expiree() {
|
||||
ValidationEtapeDemande v = new ValidationEtapeDemande();
|
||||
v.setDemandeAide(newDemandeAide());
|
||||
v.setEtapeNumero(1);
|
||||
v.setStatut(StatutValidationEtape.EXPIREE);
|
||||
assertThat(v.estFinalisee()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate (PrePersist) - statut null est initialisé à EN_ATTENTE via réflexion")
|
||||
void onCreate_withNullStatut_setsEnAttente() throws Exception {
|
||||
ValidationEtapeDemande v = new ValidationEtapeDemande();
|
||||
v.setDemandeAide(newDemandeAide());
|
||||
v.setEtapeNumero(1);
|
||||
|
||||
// Forcer statut à null via le champ Lombok
|
||||
Field statutField = ValidationEtapeDemande.class.getDeclaredField("statut");
|
||||
statutField.setAccessible(true);
|
||||
statutField.set(v, null);
|
||||
assertThat(v.getStatut()).isNull();
|
||||
|
||||
Method onCreate = ValidationEtapeDemande.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(v);
|
||||
|
||||
assertThat(v.getStatut()).isEqualTo(StatutValidationEtape.EN_ATTENTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate (PrePersist) - statut déjà défini n'est pas écrasé")
|
||||
void onCreate_withExistingStatut_keepsStatut() throws Exception {
|
||||
ValidationEtapeDemande v = new ValidationEtapeDemande();
|
||||
v.setDemandeAide(newDemandeAide());
|
||||
v.setEtapeNumero(1);
|
||||
v.setStatut(StatutValidationEtape.APPROUVEE);
|
||||
|
||||
Method onCreate = ValidationEtapeDemande.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(v);
|
||||
|
||||
assertThat(v.getStatut()).isEqualTo(StatutValidationEtape.APPROUVEE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.lions.unionflow.server.api.enums.wave.StatutWebhook;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -51,6 +52,16 @@ class WebhookWaveTest {
|
||||
assertThat(w.peutEtreRetente()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetente: false si statut TRAITE (ni ECHOUE ni EN_ATTENTE)")
|
||||
void peutEtreRetente_false_whenTraite() {
|
||||
WebhookWave w = new WebhookWave();
|
||||
w.setWaveEventId("x");
|
||||
w.setStatutTraitement(StatutWebhook.TRAITE.name());
|
||||
w.setNombreTentatives(1);
|
||||
assertThat(w.peutEtreRetente()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("equals et hashCode")
|
||||
void equalsHashCode() {
|
||||
@@ -75,4 +86,32 @@ class WebhookWaveTest {
|
||||
w.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
|
||||
assertThat(w.toString()).isNotNull().isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("peutEtreRetente: true si nombreTentatives null et EN_ATTENTE")
|
||||
void peutEtreRetente_nombreTentativesNull_returnsTrue() {
|
||||
WebhookWave w = new WebhookWave();
|
||||
w.setWaveEventId("x");
|
||||
w.setStatutTraitement(StatutWebhook.EN_ATTENTE.name());
|
||||
w.setNombreTentatives(null);
|
||||
assertThat(w.peutEtreRetente()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("onCreate: initialise les défauts si null")
|
||||
void onCreate_setsDefaults() throws Exception {
|
||||
WebhookWave w = new WebhookWave();
|
||||
w.setWaveEventId("evt-onc");
|
||||
w.setStatutTraitement(null);
|
||||
w.setDateReception(null);
|
||||
w.setNombreTentatives(null);
|
||||
|
||||
Method onCreate = WebhookWave.class.getDeclaredMethod("onCreate");
|
||||
onCreate.setAccessible(true);
|
||||
onCreate.invoke(w);
|
||||
|
||||
assertThat(w.getStatutTraitement()).isEqualTo(StatutWebhook.EN_ATTENTE.name());
|
||||
assertThat(w.getDateReception()).isNotNull();
|
||||
assertThat(w.getNombreTentatives()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,16 +48,19 @@ class CampagneCollecteTest {
|
||||
void equalsHashCode() {
|
||||
UUID id = UUID.randomUUID();
|
||||
Organisation o = newOrganisation();
|
||||
LocalDateTime dateOuverture = LocalDateTime.of(2026, 1, 1, 0, 0, 0);
|
||||
CampagneCollecte a = new CampagneCollecte();
|
||||
a.setId(id);
|
||||
a.setOrganisation(o);
|
||||
a.setTitre("T");
|
||||
a.setStatut(StatutCampagneCollecte.BROUILLON);
|
||||
a.setDateOuverture(dateOuverture);
|
||||
CampagneCollecte b = new CampagneCollecte();
|
||||
b.setId(id);
|
||||
b.setOrganisation(o);
|
||||
b.setTitre("T");
|
||||
b.setStatut(StatutCampagneCollecte.BROUILLON);
|
||||
b.setDateOuverture(dateOuverture);
|
||||
assertThat(a).isEqualTo(b);
|
||||
assertThat(a.hashCode()).isEqualTo(b.hashCode());
|
||||
}
|
||||
|
||||
@@ -2,10 +2,16 @@ package dev.lions.unionflow.server.entity.listener;
|
||||
|
||||
import dev.lions.unionflow.server.entity.Adresse;
|
||||
import dev.lions.unionflow.server.entity.BaseEntity;
|
||||
import dev.lions.unionflow.server.service.KeycloakService;
|
||||
import io.quarkus.arc.Arc;
|
||||
import io.quarkus.arc.ArcContainer;
|
||||
import io.quarkus.arc.InstanceHandle;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour AuditEntityListener (avantCreation, avantModification, toutes les branches).
|
||||
@@ -80,4 +86,129 @@ class AuditEntityListenerTest {
|
||||
|
||||
assertThat(entity.getModifiePar()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
@DisplayName("avantCreation: retourne l'email quand KeycloakService authentifié et email non vide")
|
||||
void avantCreation_authenticated_withEmail_setsEmail() {
|
||||
ArcContainer mockContainer = mock(ArcContainer.class);
|
||||
InstanceHandle<KeycloakService> mockHandle = mock(InstanceHandle.class);
|
||||
KeycloakService mockService = mock(KeycloakService.class);
|
||||
|
||||
when(mockContainer.instance(KeycloakService.class)).thenReturn(mockHandle);
|
||||
when(mockHandle.get()).thenReturn(mockService);
|
||||
when(mockService.isAuthenticated()).thenReturn(true);
|
||||
when(mockService.getCurrentUserEmail()).thenReturn("user@example.com");
|
||||
|
||||
try (MockedStatic<Arc> arcMock = mockStatic(Arc.class)) {
|
||||
arcMock.when(Arc::container).thenReturn(mockContainer);
|
||||
|
||||
BaseEntity entity = new Adresse();
|
||||
entity.setCreePar(null);
|
||||
new AuditEntityListener().avantCreation(entity);
|
||||
|
||||
assertThat(entity.getCreePar()).isEqualTo("user@example.com");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Branches manquantes dans obtenirUtilisateurCourant()
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
@DisplayName("obtenirUtilisateurCourant: keycloakService null → retourne 'system' (L92 branche keycloakService==null)")
|
||||
void avantCreation_keycloakServiceNull_returnsSystem() {
|
||||
ArcContainer mockContainer = mock(ArcContainer.class);
|
||||
InstanceHandle<KeycloakService> mockHandle = mock(InstanceHandle.class);
|
||||
|
||||
when(mockContainer.instance(KeycloakService.class)).thenReturn(mockHandle);
|
||||
// get() retourne null → L92 condition (keycloakService != null) = false → retourne "system"
|
||||
when(mockHandle.get()).thenReturn(null);
|
||||
|
||||
try (MockedStatic<Arc> arcMock = mockStatic(Arc.class)) {
|
||||
arcMock.when(Arc::container).thenReturn(mockContainer);
|
||||
|
||||
BaseEntity entity = new Adresse();
|
||||
entity.setCreePar(null);
|
||||
new AuditEntityListener().avantCreation(entity);
|
||||
|
||||
// keycloakService null → fallback "system"
|
||||
assertThat(entity.getCreePar()).isEqualTo("system");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
@DisplayName("obtenirUtilisateurCourant: authentifié mais email blank → retourne 'system' (L95 branche email.isBlank)")
|
||||
void avantCreation_authenticated_blankEmail_returnsSystem() {
|
||||
ArcContainer mockContainer = mock(ArcContainer.class);
|
||||
InstanceHandle<KeycloakService> mockHandle = mock(InstanceHandle.class);
|
||||
KeycloakService mockService = mock(KeycloakService.class);
|
||||
|
||||
when(mockContainer.instance(KeycloakService.class)).thenReturn(mockHandle);
|
||||
when(mockHandle.get()).thenReturn(mockService);
|
||||
when(mockService.isAuthenticated()).thenReturn(true);
|
||||
// email blank → L95 condition !email.isBlank() = false → ne retourne pas email → tombe sur "system"
|
||||
when(mockService.getCurrentUserEmail()).thenReturn(" ");
|
||||
|
||||
try (MockedStatic<Arc> arcMock = mockStatic(Arc.class)) {
|
||||
arcMock.when(Arc::container).thenReturn(mockContainer);
|
||||
|
||||
BaseEntity entity = new Adresse();
|
||||
entity.setCreePar(null);
|
||||
new AuditEntityListener().avantCreation(entity);
|
||||
|
||||
assertThat(entity.getCreePar()).isEqualTo("system");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
@DisplayName("obtenirUtilisateurCourant: authentifié mais email null → retourne 'system' (L95 branche email==null)")
|
||||
void avantCreation_authenticated_nullEmail_returnsSystem() {
|
||||
ArcContainer mockContainer = mock(ArcContainer.class);
|
||||
InstanceHandle<KeycloakService> mockHandle = mock(InstanceHandle.class);
|
||||
KeycloakService mockService = mock(KeycloakService.class);
|
||||
|
||||
when(mockContainer.instance(KeycloakService.class)).thenReturn(mockHandle);
|
||||
when(mockHandle.get()).thenReturn(mockService);
|
||||
when(mockService.isAuthenticated()).thenReturn(true);
|
||||
// email null → L95 condition (email != null && !email.isBlank()) = false → retourne "system"
|
||||
when(mockService.getCurrentUserEmail()).thenReturn(null);
|
||||
|
||||
try (MockedStatic<Arc> arcMock = mockStatic(Arc.class)) {
|
||||
arcMock.when(Arc::container).thenReturn(mockContainer);
|
||||
|
||||
BaseEntity entity = new Adresse();
|
||||
entity.setCreePar(null);
|
||||
new AuditEntityListener().avantCreation(entity);
|
||||
|
||||
assertThat(entity.getCreePar()).isEqualTo("system");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
@DisplayName("obtenirUtilisateurCourant: non authentifié → retourne 'system' (L93 branche isAuthenticated=false)")
|
||||
void avantCreation_notAuthenticated_returnsSystem() {
|
||||
ArcContainer mockContainer = mock(ArcContainer.class);
|
||||
InstanceHandle<KeycloakService> mockHandle = mock(InstanceHandle.class);
|
||||
KeycloakService mockService = mock(KeycloakService.class);
|
||||
|
||||
when(mockContainer.instance(KeycloakService.class)).thenReturn(mockHandle);
|
||||
when(mockHandle.get()).thenReturn(mockService);
|
||||
// isAuthenticated=false → L93 condition false → ne rentre pas dans le if → retourne "system"
|
||||
when(mockService.isAuthenticated()).thenReturn(false);
|
||||
|
||||
try (MockedStatic<Arc> arcMock = mockStatic(Arc.class)) {
|
||||
arcMock.when(Arc::container).thenReturn(mockContainer);
|
||||
|
||||
BaseEntity entity = new Adresse();
|
||||
entity.setCreePar(null);
|
||||
new AuditEntityListener().avantCreation(entity);
|
||||
|
||||
assertThat(entity.getCreePar()).isEqualTo("system");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user