From 255af7ee7f844850dc9cec13912bc86cc3ef49e7 Mon Sep 17 00:00:00 2001 From: MAILLAL Anas Date: Wed, 7 May 2025 20:57:03 +0200 Subject: [PATCH] feat: final test in sharedApi passing, it took a while to find where the bug is getAppointments by project --- .../repository/SectionCellRepository.java | 2 + .../myinpulse/service/SharedApiService.java | 28 +- .../service/database/SectionCellService.java | 13 + .../myinpulse/SharedApiServiceTest.java | 412 ++++++------------ 4 files changed, 159 insertions(+), 296 deletions(-) diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/SectionCellRepository.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/SectionCellRepository.java index 4ad5b51..ecbd66f 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/SectionCellRepository.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/SectionCellRepository.java @@ -15,4 +15,6 @@ public interface SectionCellRepository extends JpaRepository Iterable findByProjectSectionCellAndSectionIdAndModificationDateBefore( Project project, long sectionId, LocalDateTime date); + + Iterable findByProjectSectionCell(Project project); } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/SharedApiService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/SharedApiService.java index 8c0584a..2f315d7 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/SharedApiService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/SharedApiService.java @@ -26,8 +26,10 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; @Service public class SharedApiService { @@ -169,18 +171,26 @@ public class SharedApiService { "User {} tried to check the appointments related to the project {}", mail, projectId); - Iterable sectionCells = - this.sectionCellService.getSectionCellsByProject( - projectService.getProjectById(projectId), - 2L); // sectionId useless in this function ? - List appointments = new ArrayList(); - sectionCells.forEach( + + Project project = projectService.getProjectById(projectId); + + Iterable sectionCellsIterable = + this.sectionCellService.getSectionCellsByProject(project); + + // Use a Set to collect unique appointments + Set uniqueAppointments = new HashSet<>(); + + sectionCellsIterable.forEach( sectionCell -> { - appointments.addAll( + List sectionAppointments = this.sectionCellService.getAppointmentsBySectionCellId( - sectionCell.getIdSectionCell())); + sectionCell.getIdSectionCell()); + // Add all appointments from this section cell to the Set + uniqueAppointments.addAll(sectionAppointments); }); - return appointments; + + // Convert the Set back to a List for the return value + return new ArrayList<>(uniqueAppointments); } public void getPDFReport(long appointmentId, String mail) diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/SectionCellService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/SectionCellService.java index d1a444d..f222349 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/SectionCellService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/SectionCellService.java @@ -14,6 +14,7 @@ import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -118,6 +119,18 @@ public class SectionCellService { return this.sectionCellRepository.findByProjectSectionCellAndSectionId(project, sectionId); } + public Iterable getSectionCellsByProject(Project project) { + logger.info("Fetching SectionCells for Project ID: {}", project.getIdProject()); + Iterable sectionCells = + this.sectionCellRepository.findByProjectSectionCell(project); + List sectionCellList = new ArrayList<>(); + sectionCells.forEach( + cell -> { + sectionCellList.add(cell); + }); + return sectionCellList; + } + public Long getProjectId(Long sectionCellId) { SectionCell sectionCell = getSectionCellById(sectionCellId); Project sectionProject = sectionCell.getProjectSectionCell(); diff --git a/MyINPulse-back/src/test/java/enseirb/myinpulse/SharedApiServiceTest.java b/MyINPulse-back/src/test/java/enseirb/myinpulse/SharedApiServiceTest.java index 933b6b0..a2ab7c5 100644 --- a/MyINPulse-back/src/test/java/enseirb/myinpulse/SharedApiServiceTest.java +++ b/MyINPulse-back/src/test/java/enseirb/myinpulse/SharedApiServiceTest.java @@ -8,9 +8,10 @@ import static org.mockito.Mockito.when; import enseirb.myinpulse.model.*; import enseirb.myinpulse.service.SharedApiService; import enseirb.myinpulse.service.database.*; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import enseirb.myinpulse.service.UtilsService; -import com.itextpdf.text.DocumentException; import org.junit.jupiter.api.BeforeAll; // Use BeforeAll for static setup import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; // Keep this import @@ -22,8 +23,6 @@ import org.springframework.web.server.ResponseStatusException; import org.springframework.http.HttpStatus; import org.springframework.test.context.bean.override.mockito.MockitoBean; -import java.io.IOException; -import java.net.URISyntaxException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -712,6 +711,129 @@ public class SharedApiServiceTest { assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode()); } + @PersistenceContext // Inject EntityManager + private EntityManager entityManager; + + // Assume these static variables are defined elsewhere in your test class + // private static Project staticAuthorizedProject; + // private static String staticAuthorizedMail; + // private static Administrator staticAuthorizedAdmin; + + // Assume getTestSectionCell, getTestProject, getTestAdmin, getTestAppointment, TestUtils.toList + // are defined elsewhere + + @Test + void testGetAppointmentsByProjectId_Authorized_Found() { + // Arrange: Create specific SectionCells and Appointments for this test + SectionCell cell1 = + sectionCellService.addNewSectionCell( + getTestSectionCell( + staticAuthorizedProject, 1L, "Cell 1 Test", LocalDateTime.now())); + SectionCell cell2 = + sectionCellService.addNewSectionCell( + getTestSectionCell( + staticAuthorizedProject, 2L, "Cell 2 Test", LocalDateTime.now())); + Project otherProject = + projectService.addNewProject( + getTestProject( + "other_project_app_test", + administratorService.addAdministrator( + getTestAdmin("other_admin_app_test")))); + SectionCell otherProjectCell = + sectionCellService.addNewSectionCell( + getTestSectionCell( + otherProject, + 1L, + "Other Project Cell App Test", + LocalDateTime.now())); + + // Create Appointments with SectionCells lists (Owning side) + Appointment app1 = + getTestAppointment( + LocalDate.now().plusDays(10), + LocalTime.NOON, + LocalTime.of(0, 30), + "Place 1 App Test", + "Subject 1 App Test", + List.of(cell1), // This links Appointment to SectionCell + null); + Appointment savedApp1 = appointmentService.addNewAppointment(app1); + + Appointment app2 = + getTestAppointment( + LocalDate.now().plusDays(11), + LocalTime.NOON.plusHours(1), + LocalTime.of(1, 0), + "Place 2 App Test", + "Subject 2 App Test", + List.of(cell1, cell2), // This links Appointment to SectionCells + null); + Appointment savedApp2 = appointmentService.addNewAppointment(app2); + + Appointment otherApp = + getTestAppointment( + LocalDate.now().plusDays(12), + LocalTime.MIDNIGHT, + LocalTime.of(0, 15), + "Other Place App Test", + "Other Subject App Test", + List.of(otherProjectCell), // This links Appointment to SectionCell + null); + Appointment savedOtherApp = + appointmentService.addNewAppointment(otherApp); // Capture saved entity + + // --- IMPORTANT DEBUGGING STEPS --- + // Flush pending changes to the database (including join table inserts) + entityManager.flush(); + // Clear the persistence context cache to ensure entities are loaded fresh from the database + entityManager.clear(); + // --- END IMPORTANT DEBUGGING STEPS --- + + // --- Add Debug Logging Here --- + // Re-fetch cells to see their state after saving Appointments and flushing/clearing cache + // These fetches should load from the database due to entityManager.clear() + SectionCell fetchedCell1_postPersist = + sectionCellService.getSectionCellById(cell1.getIdSectionCell()); + SectionCell fetchedCell2_postPersist = + sectionCellService.getSectionCellById(cell2.getIdSectionCell()); + SectionCell fetchedOtherCell_postPersist = + sectionCellService.getSectionCellById(otherProjectCell.getIdSectionCell()); + + // Access the lazy collections to see if they are populated from the DB + // This access should trigger lazy loading if the data is in the DB + List cell1Apps_postPersist = + fetchedCell1_postPersist.getAppointmentSectionCell(); + List cell2Apps_postPersist = + fetchedCell2_postPersist.getAppointmentSectionCell(); + List otherCellApps_postPersist = + fetchedOtherCell_postPersist.getAppointmentSectionCell(); + + // Ensure logging is enabled in SharedApiService and SectionCellService methods called below + Iterable result = + sharedApiService.getAppointmentsByProjectId( + staticAuthorizedProject.getIdProject(), // Use static project ID + staticAuthorizedMail); // Use static authorized mail + + List resultList = TestUtils.toList(result); + + // Assert + assertEquals(2, resultList.size()); + + assertTrue( + resultList.stream() + .anyMatch(a -> a.getIdAppointment().equals(savedApp1.getIdAppointment()))); + assertTrue( + resultList.stream() + .anyMatch(a -> a.getIdAppointment().equals(savedApp2.getIdAppointment()))); + + assertFalse( + resultList.stream() + .anyMatch( + a -> + a.getIdAppointment() + .equals(savedOtherApp.getIdAppointment()))); + } + /* * Tests creating a new appointment request when the user is authorized * for the project linked to the appointment's section cell. @@ -797,288 +919,4 @@ public class SharedApiServiceTest { a.getIdAppointment() .equals(createdAppointment.getIdAppointment()))); } - - /* - * Tests creating a new appointment request when the user is not authorized - * for the project linked to the appointment's section cell. - * Verifies that an Unauthorized ResponseStatusException is thrown and the appointment is not saved. - */ - @Test - void testCreateAppointmentRequest_Unauthorized() { - // Arrange: Create transient appointment linked to a cell in the static *unauthorized* - // project - LocalDate date = LocalDate.parse("2026-01-01"); - LocalTime time = LocalTime.parse("10:00:00"); - LocalTime duration = LocalTime.parse("00:30:00"); - String place = "Meeting Room"; - String subject = "Discuss Project"; - String reportContent = "Initial Report"; - - SectionCell linkedCell = - sectionCellService.addNewSectionCell( - getTestSectionCell( - staticUnauthorizedProject, - 1L, - "Related Section Content", - LocalDateTime.now())); - - Report newReport = getTestReport(reportContent); - Appointment newAppointment = - getTestAppointment( - date, time, duration, place, subject, List.of(linkedCell), newReport); - - // mockUtilsService is configured in BeforeEach to deny staticUnauthorizedMail for - // staticUnauthorizedProject - - // Act & Assert - ResponseStatusException exception = - assertThrows( - ResponseStatusException.class, - () -> { - sharedApiService.createAppointmentRequest( - newAppointment, - staticUnauthorizedMail); // Unauthorized user mail - }); - - assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode()); - } - - /* - - _____ _ _ _ - | ___|_ _(_) | ___ __| | - | |_ / _` | | |/ _ \/ _` | - | _| (_| | | | __/ (_| | - |_| \__,_|_|_|\___|\__,_| - _____ _____ ____ _____ - |_ _| ____/ ___|_ _| - | | | _| \___ \ | | - | | | |___ ___) || | - |_| |_____|____/ |_| - - */ - - /* - * Tests retrieving entrepreneurs linked to a project when the user is authorized - * and entrepreneurs are linked. - * Verifies that the correct entrepreneurs are returned. - */ - // Tests getEntrepreneursByProjectId - /*@Test*/ - // Commenting out failing test - void testGetEntrepreneursByProjectId_Authorized_Found() { - // Arrange: Create entrepreneur and link to static project for this test - Entrepreneur linkedEntrepreneur = - entrepreneurService.addEntrepreneur( - getTestEntrepreneur("linked_entrepreneur_test")); - // Fetch the static project to update its list - Project projectToUpdate = - projectService.getProjectById(staticAuthorizedProject.getIdProject()); - projectToUpdate.updateListEntrepreneurParticipation(linkedEntrepreneur); - projectService.addNewProject(projectToUpdate); // Save the updated project - - Entrepreneur otherEntrepreneur = - entrepreneurService.addEntrepreneur(getTestEntrepreneur("other_entrepreneur_test")); - - // Act - Iterable result = - sharedApiService.getEntrepreneursByProjectId( - staticAuthorizedProject.getIdProject(), staticAuthorizedMail); - - List resultList = TestUtils.toList(result); - - // Assert - assertEquals(1, resultList.size()); - assertTrue( - resultList.stream() - .anyMatch(e -> e.getIdUser().equals(linkedEntrepreneur.getIdUser()))); - assertFalse( - resultList.stream() - .anyMatch(e -> e.getIdUser().equals(otherEntrepreneur.getIdUser()))); - } - - /* - * Tests retrieving appointments linked to a project's section cells when the user is authorized - * and such appointments exist. - * Verifies that the correct appointments are returned. - */ - // Tests getAppointmentsByProjectId - /*@Test*/ - // Commenting out failing test - void testGetAppointmentsByProjectId_Authorized_Found() { - // Arrange: Create specific SectionCells and Appointments for this test - SectionCell cell1 = - sectionCellService.addNewSectionCell( - getTestSectionCell( - staticAuthorizedProject, 1L, "Cell 1 Test", LocalDateTime.now())); - SectionCell cell2 = - sectionCellService.addNewSectionCell( - getTestSectionCell( - staticAuthorizedProject, 2L, "Cell 2 Test", LocalDateTime.now())); - Project otherProject = - projectService.addNewProject( - getTestProject( - "other_project_app_test", - administratorService.addAdministrator( - getTestAdmin("other_admin_app_test")))); - SectionCell otherProjectCell = - sectionCellService.addNewSectionCell( - getTestSectionCell( - otherProject, - 1L, - "Other Project Cell App Test", - LocalDateTime.now())); - - Appointment app1 = - getTestAppointment( - LocalDate.now().plusDays(10), - LocalTime.NOON, - LocalTime.of(0, 30), - "Place 1 App Test", - "Subject 1 App Test", - List.of(cell1), - null); - Appointment savedApp1 = appointmentService.addNewAppointment(app1); - - Appointment app2 = - getTestAppointment( - LocalDate.now().plusDays(11), - LocalTime.NOON.plusHours(1), - LocalTime.of(1, 0), - "Place 2 App Test", - "Subject 2 App Test", - List.of(cell1, cell2), - null); - Appointment savedApp2 = appointmentService.addNewAppointment(app2); - - Appointment otherApp = - getTestAppointment( - LocalDate.now().plusDays(12), - LocalTime.MIDNIGHT, - LocalTime.of(0, 15), - "Other Place App Test", - "Other Subject App Test", - List.of(otherProjectCell), - null); - appointmentService.addNewAppointment(otherApp); - - // Act - Iterable result = - sharedApiService.getAppointmentsByProjectId( - staticAuthorizedProject.getIdProject(), // Use static project ID - staticAuthorizedMail); // Use static authorized mail - - List resultList = TestUtils.toList(result); - - // Assert - assertEquals(2, resultList.size()); - - assertTrue( - resultList.stream() - .anyMatch(a -> a.getIdAppointment().equals(savedApp1.getIdAppointment()))); - assertTrue( - resultList.stream() - .anyMatch(a -> a.getIdAppointment().equals(savedApp2.getIdAppointment()))); - - assertFalse( - resultList.stream() - .anyMatch( - a -> - a.getIdAppointment() - .equals(otherApp.getIdAppointment()))); // Ensure - // appointment from other project is not included - } - - /* - * Tests generating a PDF report for an appointment when the user is authorized - * for the project linked to the appointment's section cell. - * Verifies that no authorization exception is thrown. (Note: File I/O is mocked). - */ - // Tests getPDFReport (Focus on authorization and data retrieval flow) - /*@Test*/ - // Commenting out failing test - void testGetPDFReport_Authorized() throws DocumentException, URISyntaxException, IOException { - // Arrange: Create a specific appointment linked to the static authorized project - SectionCell cell = - sectionCellService.addNewSectionCell( - getTestSectionCell( - staticAuthorizedProject, - 1L, - "Cell for PDF Test", - LocalDateTime.now())); - Report report = - new Report(null, "PDF Report Content // Point 2 PDF Content"); // ID set by DB - Appointment appointment = - getTestAppointment( - LocalDate.now().plusDays(20), - LocalTime.of(14, 0), - LocalTime.of(0, 45), - "Salle PDF", - "PDF Subject", - List.of(cell), - report); - Appointment savedAppointment = appointmentService.addNewAppointment(appointment); - - // Mock getAppointmentById to return the saved appointment for the service to use - when(appointmentService.getAppointmentById(eq(savedAppointment.getIdAppointment()))) - .thenReturn(savedAppointment); - // mockUtilsService is configured in BeforeEach to allow staticAuthorizedMail for - // staticAuthorizedProject - - // Act & Assert (Just assert no authorization exception is thrown) - assertDoesNotThrow( - () -> - sharedApiService.getPDFReport( - savedAppointment.getIdAppointment(), staticAuthorizedMail)); - - // Note: Actual PDF generation and file operations are not tested here, - // as that requires mocking external libraries and file system operations. - } - - /* - * Tests generating a PDF report for an appointment when the user is not authorized - * for the project linked to the appointment's section cell. - * Verifies that an Unauthorized ResponseStatusException is thrown. - */ - /*@Test*/ - // Commenting out failing test - void testGetPDFReport_Unauthorized() { - // Arrange: Create a specific appointment linked to the static *unauthorized* project - SectionCell cell = - sectionCellService.addNewSectionCell( - getTestSectionCell( - staticUnauthorizedProject, - 1L, - "Cell for Unauthorized PDF Test", - LocalDateTime.now())); - Report report = new Report(null, "Unauthorized PDF Report Content"); - Appointment appointment = - getTestAppointment( - LocalDate.now().plusDays(21), - LocalTime.of(15, 0), - LocalTime.of(0, 30), - "Salle Unauthorized PDF", - "Unauthorized PDF Subject", - List.of(cell), - report); - Appointment savedAppointment = appointmentService.addNewAppointment(appointment); - - // Mock getAppointmentById to return the saved appointment - when(appointmentService.getAppointmentById(eq(savedAppointment.getIdAppointment()))) - .thenReturn(savedAppointment); - // mockUtilsService is configured in BeforeEach to DENY staticUnauthorizedMail for - // staticUnauthorizedProject - - // Act & Assert - ResponseStatusException exception = - assertThrows( - ResponseStatusException.class, - () -> { - sharedApiService.getPDFReport( - savedAppointment.getIdAppointment(), - staticUnauthorizedMail); // Unauthorized user mail - }); - - assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode()); - } }