Files
MyINPulse/MyINPulse-back/src/test/java/enseirb/myinpulse/SharedApiServiceTest.java
MAILLAL Anas 255af7ee7f
All checks were successful
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 41s
CI / build (push) Successful in 11s
feat: final test in sharedApi passing, it took a while to find where the bug is getAppointments by project
2025-05-07 20:57:03 +02:00

923 lines
40 KiB
Java

package enseirb.myinpulse;
import static enseirb.myinpulse.model.ProjectDecisionValue.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
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 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
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
// Helper to easily convert Iterable to List
class TestUtils {
static <T> List<T> toList(Iterable<T> iterable) {
List<T> list = new ArrayList<>();
if (iterable != null) {
iterable.forEach(list::add);
}
return list;
}
}
@SpringBootTest
@Transactional // Each @Test method runs in a transaction that is rolled back
public class SharedApiServiceTest {
@Autowired private SharedApiService sharedApiService;
// Autowire actual services to use in setup and test verification
@Autowired private ProjectService projectService;
@Autowired private AdministratorService administratorService;
@Autowired private EntrepreneurService entrepreneurService;
@Autowired private SectionCellService sectionCellService;
@Autowired private AppointmentService appointmentService;
// Mock UtilsService to control authorization logic
@MockitoBean private UtilsService mockUtilsService;
// Static variables for data created once before all tests
private static Project staticAuthorizedProject;
private static String staticAuthorizedMail;
private static Administrator staticAuthorizedAdmin;
private static Project staticUnauthorizedProject;
private static String staticUnauthorizedMail;
// --- Static Setup (Runs once before all tests) ---
// Use @BeforeAll static method with injected services
@BeforeAll
static void setupOnce(
@Autowired AdministratorService administratorService,
@Autowired ProjectService projectService,
@Autowired EntrepreneurService entrepreneurService) {
// Create and Save core test data here using injected services
staticAuthorizedAdmin =
administratorService.addAdministrator(getTestAdmin("static_authorized_admin"));
staticAuthorizedMail = staticAuthorizedAdmin.getPrimaryMail();
staticUnauthorizedProject =
projectService.addNewProject(
getTestProject(
"static_unauthorized_project",
administratorService.addAdministrator(
getTestAdmin("static_unauthorized_admin"))));
staticUnauthorizedMail =
administratorService
.addAdministrator(getTestAdmin("static_unauthorized_user"))
.getPrimaryMail(); // User who is NOT admin of the unauthorized project
staticAuthorizedProject =
projectService.addNewProject(
getTestProject("static_authorized_project", staticAuthorizedAdmin));
// Link a static entrepreneur to the authorized project if needed for some tests
// Entrepreneur staticLinkedEntrepreneur =
// entrepreneurService.addEntrepreneur(getTestEntrepreneur("static_linked_entrepreneur"));
// staticAuthorizedProject.updateListEntrepreneurParticipation(staticLinkedEntrepreneur);
// projectService.addNewProject(staticAuthorizedProject); // Re-save the project after
// updating lists
}
// --- Per-Test Setup (Runs before each test method) ---
@BeforeEach
void setupForEach() {
// Reset mock expectations before each test
MockitoAnnotations.openMocks(
this); // Needed for mocks if not using @ExtendWith(MockitoExtension.class)
// --- Configure the mock UtilsService based on the actual authorization rules ---
// Rule: Any admin can check any project.
// Assuming staticAuthorizedMail is an admin:
when(mockUtilsService.isAllowedToCheckProject(eq(staticAuthorizedMail), anyLong()))
.thenReturn(true); // Admin allowed for ANY project ID
// Rule: An entrepreneur can only check their own stuff.
// Assuming staticUnauthorizedMail is an entrepreneur NOT linked to staticAuthorizedProject
// or staticUnauthorizedProject:
when(mockUtilsService.isAllowedToCheckProject(eq(staticUnauthorizedMail), anyLong()))
.thenReturn(false); // Unauthorized entrepreneur NOT allowed for ANY project ID by
// default
}
// --- Helper Methods (Can remain non-static or static as needed) ---
private static Administrator getTestAdmin(String name) {
return new Administrator(
name + "_surname",
name,
name + "@example.com",
"secondary_" + name + "@example.com",
"0123456789");
}
private static Entrepreneur getTestEntrepreneur(String name) {
return new Entrepreneur(
name + "_surname",
name,
name + "@example.com",
"secondary_" + name + "@example.com",
"0123456789",
"Test School",
"Test Course",
false);
}
private static Project getTestProject(String name, Administrator admin) {
Project project = new Project(name, null, LocalDate.now(), ACTIVE, admin);
return project;
}
private static SectionCell getTestSectionCell(
Project project, Long sectionId, String content, LocalDateTime date) {
SectionCell sectionCell = new SectionCell();
sectionCell.setProjectSectionCell(project);
sectionCell.setSectionId(sectionId);
sectionCell.setContentSectionCell(content);
sectionCell.setModificationDate(date);
return sectionCell;
}
private static SectionCell getTestSectionCell(
Project project, Long sectionId, String content, LocalDateTime date, Long refrenceId) {
SectionCell sectionCell = new SectionCell();
sectionCell.setProjectSectionCell(project);
sectionCell.setSectionId(sectionId);
sectionCell.setContentSectionCell(content);
sectionCell.setModificationDate(date);
sectionCell.setIdReference(refrenceId);
return sectionCell;
}
private static Appointment getTestAppointment(
LocalDate date,
LocalTime time,
LocalTime duration,
String place,
String subject,
List<SectionCell> sectionCells,
Report report) {
Appointment appointment = new Appointment();
appointment.setAppointmentDate(date);
appointment.setAppointmentTime(time);
appointment.setAppointmentDuration(duration);
appointment.setAppointmentPlace(place);
appointment.setAppointmentSubject(subject);
if (sectionCells != null) {
sectionCells.forEach(appointment::updateListSectionCell);
}
if (report != null) {
appointment.setAppointmentReport(report);
report.setAppointmentReport(appointment);
}
return appointment;
}
private static Report getTestReport(String content) {
Report report = new Report();
report.setReportContent(content);
return report;
}
/*
* _____ _ ____ _ _ ____ _ _
* |_ _|__ ___| |_/ ___| ___ ___| |_(_) ___ _ __ / ___|___| | |
* | |/ _ \/ __| __\___ \ / _ \/ __| __| |/ _ \| '_ \| | / _ \ | |
* | | __/\__ \ |_ ___) | __/ (__| |_| | (_) | | | | |__| __/ | |
* |_|\___||___/\__|____/ \___|\___|\__|_|\___/|_| |_|\____\___|_|_|
*/
/*
* Tests retrieving section cells for a specific project and section ID before a given date
* when the user is authorized but no matching cells exist.
* Verifies that an empty list is returned.
*/
@Test
void testGetSectionCells_Authorized_NotFound() {
// Arrange: No specific section cells needed for this test, rely on clean @BeforeEach state
Long targetSectionId = 1L;
LocalDateTime dateFilter = LocalDateTime.now().plusDays(1);
// Act
Iterable<SectionCell> result =
sharedApiService.getSectionCells(
staticAuthorizedProject.getIdProject(),
targetSectionId,
dateFilter.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
staticAuthorizedMail);
List<SectionCell> resultList = TestUtils.toList(result);
// Assert
assertTrue(resultList.isEmpty());
}
/*
* Tests retrieving section cells when the user is not authorized for the project.
* Verifies that an Unauthorized ResponseStatusException is thrown.
*/
@Test
void testGetSectionCells_Unauthorized() {
// Arrange: mockUtilsService configured in BeforeEach
// Act & Assert
ResponseStatusException exception =
assertThrows(
ResponseStatusException.class,
() -> {
sharedApiService.getSectionCells(
staticAuthorizedProject
.getIdProject(), // Project static user is not
// authorized for
1L,
LocalDateTime.now()
.format(
DateTimeFormatter.ofPattern(
"yyyy-MM-dd HH:mm")),
staticUnauthorizedMail); // Static unauthorized user mail
});
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
}
/*
* Tests retrieving all section cells for a project when the user is authorized
* but the project has no section cells.
* Verifies that an empty list is returned.
*/
@Test
void testGetAllSectionCells_Authorized_NoCells() {
// Arrange: staticAuthorizedProject has no section cells initially in BeforeAll
// Act
Iterable<SectionCell> result =
sharedApiService.getAllSectionCells(
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
List<SectionCell> resultList = TestUtils.toList(result);
// Assert
assertTrue(resultList.isEmpty());
}
/*
* Tests retrieving all section cells when the user is not authorized for the project.
* Verifies that an Unauthorized ResponseStatusException is thrown.
*/
@Test
void testGetAllSectionCells_Unauthorized() {
// Arrange: mockUtilsService configured in BeforeEach
// Act & Assert
ResponseStatusException exception =
assertThrows(
ResponseStatusException.class,
() -> {
sharedApiService.getAllSectionCells(
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
});
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
}
/*
* Tests retrieving section cells for a specific project and section ID before a given date
* when the user is authorized and matching cells exist.
* Verifies that only the correct cells are returned.
*/
@Test
// Commenting out failing test
void testGetSectionCells_Authorized_Found() {
Long targetSectionId = 1L;
// Set a date filter slightly in the future so our "latest before" cell is included
LocalDateTime dateFilter = LocalDateTime.now().plusMinutes(5);
// Creating versions of the SAME SectionCell (share the same idReference)
// the first version. This will get a GENERATED idReference.
SectionCell firstVersion =
getTestSectionCell(
staticAuthorizedProject,
targetSectionId,
"Content V1 (Oldest)",
LocalDateTime.now().minusDays(3) // Oldest date
);
sectionCellService.addNewSectionCell(firstVersion);
Long sharedIdReference = firstVersion.getIdReference();
assertNotNull(
sharedIdReference,
"idReference should be generated after saving the first version");
System.out.println("Generated sharedIdReference: " + sharedIdReference);
// Create subsequent versions and MANUALLY set the SAME idReference.
// These represent updates to the cell identified by sharedIdReference.
SectionCell middleVersion =
getTestSectionCell(
staticAuthorizedProject,
targetSectionId,
"Content V2 (Middle)",
LocalDateTime.now().minusDays(2), // Middle date, before filter
sharedIdReference);
middleVersion = sectionCellService.addNewSectionCell(middleVersion);
sectionCellService.updateSectionCellReferenceId(
middleVersion.getIdSectionCell(), sharedIdReference);
SectionCell latestBeforeFilter =
getTestSectionCell(
staticAuthorizedProject,
targetSectionId,
"Content V3 (Latest Before Filter)",
LocalDateTime.now().minusDays(1), // Latest date before filter
sharedIdReference);
latestBeforeFilter = sectionCellService.addNewSectionCell(latestBeforeFilter);
sectionCellService.updateSectionCellReferenceId(
latestBeforeFilter.getIdSectionCell(), sharedIdReference);
SectionCell futureVersion =
getTestSectionCell(
staticAuthorizedProject,
targetSectionId,
"Content V4 (Future - Should Be Excluded)",
LocalDateTime.now().plusDays(1), // Date is AFTER the filter
sharedIdReference);
futureVersion = sectionCellService.addNewSectionCell(futureVersion);
sectionCellService.updateSectionCellReferenceId(
futureVersion.getIdSectionCell(), sharedIdReference);
// --- Create other SectionCells that should NOT be included (different sectionId or
// project) ---
// Cell in a different section ID
sectionCellService.addNewSectionCell(
getTestSectionCell(
staticAuthorizedProject,
99L, // Different sectionId
"Content in Different Section",
LocalDateTime.now()));
// Act
Iterable<SectionCell> result =
sharedApiService.getSectionCells(
staticAuthorizedProject.getIdProject(), // Use static project ID
targetSectionId,
dateFilter.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
staticAuthorizedMail); // Use static authorized mail
List<SectionCell> resultList = TestUtils.toList(result);
assertEquals(1, resultList.size());
// Verify that the returned cell is the 'latestBeforeFilter' cell
// Comparing by idSectionCell is a good way to verify the exact entity
assertEquals(
latestBeforeFilter.getIdSectionCell(),
resultList.get(0).getIdSectionCell(),
"The returned SectionCell should be the one with the latest modification date before the filter.");
// Also assert the idReference and content
assertEquals(
sharedIdReference,
resultList.get(0).getIdReference(),
"The returned cell should have the shared idReference.");
assertEquals(
"Content V3 (Latest Before Filter)",
resultList.get(0).getContentSectionCell(),
"The returned cell should have the correct content.");
}
/*
* Tests retrieving the most recent section cell for each unique idReference
* within a project when the user is authorized and cells exist.
* Verifies that only the latest version of each referenced cell is returned.
*/
// Tests getAllSectionCells
@Test
// Commenting out failing test - Removed this comment as we are fixing it
void testGetAllSectionCells_Authorized_FoundLatest() {
// Arrange: Create specific SectionCells for this test
// Define the idReference values we will use for grouping
Long refIdGroup1 = 101L;
Long refIdGroup2 = 102L;
Long refIdOtherProject = 103L;
// --- Create and Add Cells for Group 1 (refIdGroup1) ---
// Create the older cell for group 1
SectionCell tempOldCell1 =
getTestSectionCell(
staticAuthorizedProject, // Project
1L, // Section ID (assuming this groups by section within refId)
"Ref1 Old", // Name
LocalDateTime.now().minusDays(3), // Date (older)
null); // Pass null or let getTestSectionCell handle it, we'll set
// idReference later
final SectionCell oldCell1 =
sectionCellService.addNewSectionCell(tempOldCell1); // Add to DB
// Create the newer cell for group 1
SectionCell tempNewerCell1 =
getTestSectionCell(
staticAuthorizedProject, // Project
1L, // Section ID
"Ref1 Newer", // Name
LocalDateTime.now().minusDays(2), // Date (newer than oldCell1)
null); // Pass null
final SectionCell newerCell1 =
sectionCellService.addNewSectionCell(tempNewerCell1); // Add to DB
// Now, update the idReference for both cells in Group 1 to the desired value
sectionCellService.updateSectionCellReferenceId(oldCell1.getIdSectionCell(), refIdGroup1);
sectionCellService.updateSectionCellReferenceId(newerCell1.getIdSectionCell(), refIdGroup1);
// --- Create and Add Cells for Group 2 (refIdGroup2) ---
// Create the older cell for group 2
SectionCell tempOldCell2 =
getTestSectionCell(
staticAuthorizedProject, // Project
2L, // Section ID (different section)
"Ref2 Old", // Name
LocalDateTime.now().minusDays(1), // Date (older than newerCell2)
null); // Pass null
final SectionCell oldCell2 =
sectionCellService.addNewSectionCell(tempOldCell2); // Add to DB
// Create the newer cell for group 2
SectionCell tempNewerCell2 =
getTestSectionCell(
staticAuthorizedProject, // Project
2L, // Section ID
"Ref2 Newer", // Name
LocalDateTime.now(), // Date (latest)
null); // Pass null
final SectionCell newerCell2 =
sectionCellService.addNewSectionCell(tempNewerCell2); // Add to DB
// Now, update the idReference for both cells in Group 2 to the desired value
sectionCellService.updateSectionCellReferenceId(oldCell2.getIdSectionCell(), refIdGroup2);
sectionCellService.updateSectionCellReferenceId(newerCell2.getIdSectionCell(), refIdGroup2);
// --- Create and Add Cell for Other Project (refIdOtherProject) ---
Project otherProject =
projectService.addNewProject(
getTestProject(
"other_project_for_cell_test",
administratorService.addAdministrator(
getTestAdmin("other_admin_cell_test"))));
SectionCell tempOtherProjectCell =
getTestSectionCell(
otherProject, // DIFFERENT Project
1L, // Section ID
"Other Project Cell", // Name
LocalDateTime.now(), // Date
null); // Pass null
final SectionCell otherProjectCell =
sectionCellService.addNewSectionCell(tempOtherProjectCell); // Add to DB
// Now, update the idReference for the Other Project cell
sectionCellService.updateSectionCellReferenceId(
otherProjectCell.getIdSectionCell(), refIdOtherProject);
// Act
// Ensure the service call uses the correct project ID and mail
Iterable<SectionCell> result =
sharedApiService.getAllSectionCells(
staticAuthorizedProject.getIdProject(), // Use static project ID
staticAuthorizedMail); // Use static authorized mail
List<SectionCell> resultList = TestUtils.toList(result);
// Assert
// We expect 2 cells from the staticAuthorizedProject:
// - The latest one from refIdGroup1 (newerCell1)
// - The latest one from refIdGroup2 (newerCell2)
assertEquals(2, resultList.size());
// Assert that the result list contains the LATEST cell from each group within the correct
// project
assertTrue(
resultList.stream()
.anyMatch(
cell ->
cell.getIdSectionCell()
.equals(newerCell1.getIdSectionCell())),
"Should contain the latest cell for Group 1"); // Add assertion message
assertTrue(
resultList.stream()
.anyMatch(
cell ->
cell.getIdSectionCell()
.equals(newerCell2.getIdSectionCell())),
"Should contain the latest cell for Group 2"); // Add assertion message
// Assert that the result list does NOT contain the OLDER cells from the correct project
assertFalse(
resultList.stream()
.anyMatch(
cell ->
cell.getIdSectionCell()
.equals(oldCell1.getIdSectionCell())),
"Should not contain the older cell for Group 1"); // Add assertion message
assertFalse(
resultList.stream()
.anyMatch(
cell ->
cell.getIdSectionCell()
.equals(oldCell2.getIdSectionCell())),
"Should not contain the older cell for Group 2"); // Add assertion message
// Assert that the result list does NOT contain the cell from the other project
assertFalse(
resultList.stream()
.anyMatch(
cell ->
cell.getIdSectionCell()
.equals(otherProjectCell.getIdSectionCell())),
"Should not contain cells from other projects"); // Add assertion message
}
/*
* _____ _ ____ _ ____ _ _ ____
* |_ _|__ ___| |_ / ___| ___| |_| _ \ _ __ ___ (_) ___ ___| |_| __ ) _ _
* | |/ _ \/ __| __| | _ / _ \ __| |_) | '__/ _ \| |/ _ \/ __| __| _ \| | | |
* | | __/\__ \ |_| |_| | __/ |_| __/| | | (_) | | __/ (__| |_| |_) | |_| |
* _|_|\___||___/\__|\____|\___|\__|_| |_| \___// |\___|\___|\__|____/ \__, |
* |_ _| _ \ |__/ |___/
* | || | | |
* | || |_| |
* |___|____/
*/
/*
* Tests retrieving entrepreneurs linked to a project when the user is authorized
* but no entrepreneurs are linked.
* Verifies that an empty list is returned.
*/
@Test
void testGetEntrepreneursByProjectId_Authorized_NotFound() {
// Arrange: staticAuthorizedProject has no entrepreneurs linked initially in BeforeAll
// Act
Iterable<Entrepreneur> result =
sharedApiService.getEntrepreneursByProjectId(
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
List<Entrepreneur> resultList = TestUtils.toList(result);
// Assert
assertTrue(resultList.isEmpty());
}
/*
* Tests retrieving entrepreneurs linked to a project when the user is not authorized.
* Verifies that an Unauthorized ResponseStatusException is thrown.
*/
@Test
void testGetEntrepreneursByProjectId_Unauthorized() {
// Arrange: mockUtilsService configured in BeforeEach
// Act & Assert
ResponseStatusException exception =
assertThrows(
ResponseStatusException.class,
() -> {
sharedApiService.getEntrepreneursByProjectId(
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
});
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
}
/*
* _____ _ ____ _ _ _ _ ____
* |_ _|__ ___| |_ / ___| ___| |_ / \ __| |_ __ ___ (_)_ __ | __ ) _ _
* | |/ _ \/ __| __| | _ / _ \ __| / _ \ / _` | '_ ` _ \| | '_ \| _ \| | | |
* | | __/\__ \ |_| |_| | __/ |_ / ___ \ (_| | | | | | | | | | | |_) | |_| |
* _|_|\___||___/\__|\____|\___|\__/_/ \_\__,_|_| |_| |_|_|_| |_|____/ \__, |
* |_ _| _ \ |___/
* | || | | |
* | || |_| |
* |___|____/
*
*/
/*
* Tests retrieving appointments linked to a project's section cells when the user is authorized
* but no such appointments exist.
* Verifies that an empty list is returned.
*/
@Test
void testGetAppointmentsByProjectId_Authorized_NotFound() {
// Arrange: staticAuthorizedProject has no linked section cells or appointments initially
// Act
Iterable<Appointment> result =
sharedApiService.getAppointmentsByProjectId(
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
List<Appointment> resultList = TestUtils.toList(result);
// Assert
assertTrue(resultList.isEmpty());
}
/*
* Tests retrieving the administrator linked to a project when the user is authorized
* and an administrator is linked.
* Verifies that the correct administrator is returned.
*/
// Tests getAdminByProjectId
@Test
void testGetAdminByProjectId_Authorized_Found() {
// Arrange: staticAuthorizedProject is created with staticAuthorizedAdmin in BeforeAll
// Act
Administrator result =
sharedApiService.getAdminByProjectId(
staticAuthorizedProject.getIdProject(), staticAuthorizedMail);
// Assert
assertNotNull(result);
assertEquals(staticAuthorizedAdmin.getIdUser(), result.getIdUser());
}
/*
* Tests retrieving the administrator linked to a project when the user is not authorized.
* Verifies that an Unauthorized ResponseStatusException is thrown.
*/
@Test
void testGetAdminByProjectId_Unauthorized() {
// Arrange: mockUtilsService configured in BeforeEach
// Act & Assert
ResponseStatusException exception =
assertThrows(
ResponseStatusException.class,
() -> {
sharedApiService.getAdminByProjectId(
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
});
assertEquals(HttpStatus.UNAUTHORIZED, exception.getStatusCode());
}
/*
* _____ _
* |_ _|__ ___| |_
* | |/ _ \/ __| __|
* | | __/\__ \ |_
* |_|\___||___/\__| _ _ _
* / \ _ __ _ __ ___ (_)_ __ | |_ ___ _ __ ___ ___ _ __ | |_ ___
* / _ \ | '_ \| '_ \ / _ \| | '_ \| __/ _ \ '_ ` _ \ / _ \ '_ \| __/ __|
* / ___ \| |_) | |_) | (_) | | | | | || __/ | | | | | __/ | | | |_\__ \
* /_/ \_\ .__/| .__/ \___/|_|_| |_|\__\___|_| |_| |_|\___|_| |_|\__|___/
* |_| |_|
*/
/*
* Tests retrieving appointments linked to a project's section cells when the user is not authorized.
* Verifies that an Unauthorized ResponseStatusException is thrown.
*/
@Test
void testGetAppointmentsByProjectId_Unauthorized() {
// Arrange: mockUtilsService configured in BeforeEach
// Act & Assert
ResponseStatusException exception =
assertThrows(
ResponseStatusException.class,
() -> {
sharedApiService.getAppointmentsByProjectId(
staticAuthorizedProject.getIdProject(), staticUnauthorizedMail);
});
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<Appointment> cell1Apps_postPersist =
fetchedCell1_postPersist.getAppointmentSectionCell();
List<Appointment> cell2Apps_postPersist =
fetchedCell2_postPersist.getAppointmentSectionCell();
List<Appointment> otherCellApps_postPersist =
fetchedOtherCell_postPersist.getAppointmentSectionCell();
// Ensure logging is enabled in SharedApiService and SectionCellService methods called below
Iterable<Appointment> result =
sharedApiService.getAppointmentsByProjectId(
staticAuthorizedProject.getIdProject(), // Use static project ID
staticAuthorizedMail); // Use static authorized mail
List<Appointment> 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.
* Verifies that the appointment and its relationships are saved correctly in the database.
*/
// Tests createAppointmentRequest
@Test
// Commenting out failing test
void testCreateAppointmentRequest_Authorized_Success() {
// Arrange: Create transient appointment linked to a cell in the static authorized 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 Integrated";
String subject = "Discuss Project Integrated";
SectionCell linkedCell =
sectionCellService.addNewSectionCell(
getTestSectionCell(
staticAuthorizedProject,
0L,
"Related Section Content Integrated",
LocalDateTime.now()));
Report newReport = null; // getTestReport(reportContent); // Uses no-arg constructor
Appointment newAppointment =
getTestAppointment(
date, time, duration, place, subject, List.of(linkedCell), newReport);
// mockUtilsService is configured in BeforeEach to allow staticAuthorizedMail for
// staticAuthorizedProject
// Act
// Allow the service method to call the actual appointmentService.addNewAppointment
assertDoesNotThrow(
() ->
sharedApiService.createAppointmentRequest(
newAppointment, staticAuthorizedMail));
// Assert: Retrieve the appointment from the DB and verify it and its relationships were
// saved
// We find it by looking for appointments linked to the authorized project's cells
Iterable<SectionCell> projectCells =
sectionCellService.getSectionCellsByProject(
staticAuthorizedProject, linkedCell.getSectionId()); // Fetch relevant cells
List<Appointment> projectAppointmentsList = new ArrayList<>();
projectCells.forEach(
cell ->
projectAppointmentsList.addAll(
sectionCellService.getAppointmentsBySectionCellId(
cell.getIdSectionCell()))); // Get appointments for
// those cells
Optional<Appointment> createdAppointmentOpt =
projectAppointmentsList.stream()
.filter(
a ->
a.getAppointmentDate().equals(date)
&& a.getAppointmentTime().equals(time)
&& a.getAppointmentPlace().equals(place)
&& a.getAppointmentSubject().equals(subject))
.findFirst();
assertTrue(createdAppointmentOpt.isPresent());
Appointment createdAppointment = createdAppointmentOpt.get();
// FIX: Corrected bidirectional link check
assertEquals(1, createdAppointment.getAppointmentListSectionCell().size());
assertTrue(
createdAppointment.getAppointmentListSectionCell().stream()
.anyMatch(
sc -> sc.getIdSectionCell().equals(linkedCell.getIdSectionCell())));
List<Appointment> appointmentsLinkedToCell =
TestUtils.toList(
sectionCellService.getAppointmentsBySectionCellId(
linkedCell.getIdSectionCell()));
assertTrue(
appointmentsLinkedToCell.stream()
.anyMatch(
a ->
a.getIdAppointment()
.equals(createdAppointment.getIdAppointment())));
}
}