b9137204a0
- FilePreview.vue: add normalizedFileType computed to handle backend returning uppercase HTML/MD/PPTX (fixes preview/download buttons) - FilePreview.vue: bg-gradient-to-r from-orange-500 -> bg-orange-500 (Tailwind v4 gradient + CSS variable = transparent) - ReportCard.vue: bg-gradient-to-r -> bg-orange-600 for selected state - Add .opencode/, node_modules/, dist/ to .gitignore - Initial git setup for publish project
276 lines
10 KiB
Java
276 lines
10 KiB
Java
package com.reportdist.service;
|
|
|
|
import com.reportdist.dto.ProjectRequest;
|
|
import com.reportdist.dto.ProjectResponse;
|
|
import com.reportdist.entity.Project;
|
|
import com.reportdist.repository.ProjectRepository;
|
|
import com.reportdist.repository.ReportRepository;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
import org.mockito.Mock;
|
|
import org.mockito.junit.jupiter.MockitoExtension;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.Mockito.*;
|
|
|
|
@ExtendWith(MockitoExtension.class)
|
|
class ProjectServiceTest {
|
|
|
|
@Mock
|
|
private ProjectRepository projectRepository;
|
|
|
|
@Mock
|
|
private ReportRepository reportRepository;
|
|
|
|
private ProjectService projectService;
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
projectService = new ProjectService(projectRepository, reportRepository);
|
|
}
|
|
|
|
// ==================== createProject Tests ====================
|
|
|
|
@Test
|
|
void createProject_shouldCreateAndReturnProject() {
|
|
// Given
|
|
ProjectRequest request = new ProjectRequest("Test Project", "Test Description");
|
|
Project savedProject = new Project(1L, "Test Project", "Test Description", LocalDateTime.now());
|
|
|
|
when(projectRepository.save(any(Project.class))).thenReturn(savedProject);
|
|
|
|
// When
|
|
ProjectResponse response = projectService.createProject(request);
|
|
|
|
// Then
|
|
assertNotNull(response);
|
|
assertEquals(1L, response.getId());
|
|
assertEquals("Test Project", response.getName());
|
|
assertEquals("Test Description", response.getDescription());
|
|
verify(projectRepository, times(1)).save(any(Project.class));
|
|
}
|
|
|
|
@Test
|
|
void createProject_shouldHandleDuplicateName() {
|
|
// Given - Note: The service doesn't explicitly handle duplicates,
|
|
// but we test the normal flow still works
|
|
ProjectRequest request = new ProjectRequest("Duplicate Project", "Description");
|
|
Project savedProject = new Project(2L, "Duplicate Project", "Description", LocalDateTime.now());
|
|
|
|
when(projectRepository.save(any(Project.class))).thenReturn(savedProject);
|
|
|
|
// When
|
|
ProjectResponse response = projectService.createProject(request);
|
|
|
|
// Then
|
|
assertNotNull(response);
|
|
assertEquals("Duplicate Project", response.getName());
|
|
verify(projectRepository, times(1)).save(any(Project.class));
|
|
}
|
|
|
|
// ==================== getAllProjects Tests ====================
|
|
|
|
@Test
|
|
void getAllProjects_shouldReturnEmptyList() {
|
|
// Given
|
|
when(projectRepository.findAll()).thenReturn(Collections.emptyList());
|
|
|
|
// When
|
|
List<ProjectResponse> result = projectService.getAllProjects();
|
|
|
|
// Then
|
|
assertNotNull(result);
|
|
assertTrue(result.isEmpty());
|
|
}
|
|
|
|
@Test
|
|
void getAllProjects_shouldReturnSingleProject() {
|
|
// Given
|
|
Project project = new Project(1L, "Single Project", "Description", LocalDateTime.now());
|
|
when(projectRepository.findAll()).thenReturn(Collections.singletonList(project));
|
|
|
|
// When
|
|
List<ProjectResponse> result = projectService.getAllProjects();
|
|
|
|
// Then
|
|
assertNotNull(result);
|
|
assertEquals(1, result.size());
|
|
assertEquals("Single Project", result.get(0).getName());
|
|
}
|
|
|
|
@Test
|
|
void getAllProjects_shouldReturnMultipleProjects() {
|
|
// Given
|
|
Project project1 = new Project(1L, "Project One", "Description 1", LocalDateTime.now());
|
|
Project project2 = new Project(2L, "Project Two", "Description 2", LocalDateTime.now());
|
|
Project project3 = new Project(3L, "Project Three", "Description 3", LocalDateTime.now());
|
|
when(projectRepository.findAll()).thenReturn(Arrays.asList(project1, project2, project3));
|
|
|
|
// When
|
|
List<ProjectResponse> result = projectService.getAllProjects();
|
|
|
|
// Then
|
|
assertNotNull(result);
|
|
assertEquals(3, result.size());
|
|
assertEquals("Project One", result.get(0).getName());
|
|
assertEquals("Project Two", result.get(1).getName());
|
|
assertEquals("Project Three", result.get(2).getName());
|
|
}
|
|
|
|
// ==================== updateProject Tests ====================
|
|
|
|
@Test
|
|
void updateProject_shouldUpdateAndReturnProject() {
|
|
// Given
|
|
Long projectId = 1L;
|
|
ProjectRequest request = new ProjectRequest("Updated Name", "Updated Description");
|
|
Project existingProject = new Project(1L, "Original Name", "Original Description", LocalDateTime.now());
|
|
Project updatedProject = new Project(1L, "Updated Name", "Updated Description", existingProject.getCreatedAt());
|
|
|
|
when(projectRepository.findById(projectId)).thenReturn(java.util.Optional.of(existingProject));
|
|
when(projectRepository.save(any(Project.class))).thenReturn(updatedProject);
|
|
|
|
// When
|
|
ProjectResponse response = projectService.updateProject(projectId, request);
|
|
|
|
// Then
|
|
assertNotNull(response);
|
|
assertEquals("Updated Name", response.getName());
|
|
assertEquals("Updated Description", response.getDescription());
|
|
verify(projectRepository, times(1)).findById(projectId);
|
|
verify(projectRepository, times(1)).save(any(Project.class));
|
|
}
|
|
|
|
@Test
|
|
void updateProject_shouldThrowExceptionWhenNotFound() {
|
|
// Given
|
|
Long projectId = 999L;
|
|
ProjectRequest request = new ProjectRequest("Updated Name", "Updated Description");
|
|
|
|
when(projectRepository.findById(projectId)).thenReturn(java.util.Optional.empty());
|
|
|
|
// When & Then
|
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> {
|
|
projectService.updateProject(projectId, request);
|
|
});
|
|
|
|
assertTrue(exception.getMessage().contains("Project not found"));
|
|
verify(projectRepository, times(1)).findById(projectId);
|
|
verify(projectRepository, never()).save(any(Project.class));
|
|
}
|
|
|
|
@Test
|
|
void getAllProjects_shouldIncludeReportCount() {
|
|
// Given
|
|
Project project1 = new Project(1L, "Project One", "Description 1", LocalDateTime.now());
|
|
Project project2 = new Project(2L, "Project Two", "Description 2", LocalDateTime.now());
|
|
when(projectRepository.findAll()).thenReturn(Arrays.asList(project1, project2));
|
|
when(reportRepository.countByProjectId(1L)).thenReturn(5L);
|
|
when(reportRepository.countByProjectId(2L)).thenReturn(3L);
|
|
|
|
// When
|
|
List<ProjectResponse> result = projectService.getAllProjects();
|
|
|
|
// Then
|
|
assertNotNull(result);
|
|
assertEquals(2, result.size());
|
|
assertEquals(5L, result.get(0).getReportCount());
|
|
assertEquals(3L, result.get(1).getReportCount());
|
|
verify(reportRepository, times(1)).countByProjectId(1L);
|
|
verify(reportRepository, times(1)).countByProjectId(2L);
|
|
}
|
|
|
|
@Test
|
|
void getProjectById_shouldIncludeReportCount() {
|
|
// Given
|
|
Long projectId = 1L;
|
|
Project project = new Project(1L, "Test Project", "Description", LocalDateTime.now());
|
|
when(projectRepository.findById(projectId)).thenReturn(java.util.Optional.of(project));
|
|
when(reportRepository.countByProjectId(projectId)).thenReturn(10L);
|
|
|
|
// When
|
|
ProjectResponse response = projectService.getProjectById(projectId);
|
|
|
|
// Then
|
|
assertNotNull(response);
|
|
assertEquals(10L, response.getReportCount());
|
|
verify(reportRepository, times(1)).countByProjectId(projectId);
|
|
}
|
|
|
|
@Test
|
|
void getAllProjects_withNoReports_shouldHaveZeroReportCount() {
|
|
// Given
|
|
Project project = new Project(1L, "Empty Project", "No reports", LocalDateTime.now());
|
|
when(projectRepository.findAll()).thenReturn(Collections.singletonList(project));
|
|
when(reportRepository.countByProjectId(1L)).thenReturn(0L);
|
|
|
|
// When
|
|
List<ProjectResponse> result = projectService.getAllProjects();
|
|
|
|
// Then
|
|
assertNotNull(result);
|
|
assertEquals(1, result.size());
|
|
assertEquals(0L, result.get(0).getReportCount());
|
|
}
|
|
|
|
@Test
|
|
void updateProject_withMultipartCoverImage_shouldReturnUpdatedProjectWithReportCount() {
|
|
// Given
|
|
Long projectId = 1L;
|
|
Project existingProject = new Project(1L, "Original Name", "Description", LocalDateTime.now());
|
|
Project updatedProject = new Project(1L, "Updated Name", "Description", existingProject.getCreatedAt());
|
|
updatedProject.setCoverImage("/uploads/covers/1/test.png");
|
|
|
|
when(projectRepository.findById(projectId)).thenReturn(java.util.Optional.of(existingProject));
|
|
when(projectRepository.save(any(Project.class))).thenReturn(updatedProject);
|
|
when(reportRepository.countByProjectId(projectId)).thenReturn(5L);
|
|
|
|
// When
|
|
ProjectResponse response = projectService.updateProject(projectId, "Updated Name", null, null);
|
|
|
|
// Then
|
|
assertNotNull(response);
|
|
assertEquals(5L, response.getReportCount());
|
|
verify(reportRepository, times(1)).countByProjectId(projectId);
|
|
}
|
|
|
|
// ==================== deleteProject Tests ====================
|
|
|
|
@Test
|
|
void deleteProject_shouldDeleteSuccessfully() {
|
|
// Given
|
|
Long projectId = 1L;
|
|
when(projectRepository.existsById(projectId)).thenReturn(true);
|
|
doNothing().when(projectRepository).deleteById(projectId);
|
|
|
|
// When
|
|
projectService.deleteProject(projectId);
|
|
|
|
// Then
|
|
verify(projectRepository, times(1)).existsById(projectId);
|
|
verify(projectRepository, times(1)).deleteById(projectId);
|
|
}
|
|
|
|
@Test
|
|
void deleteProject_shouldThrowExceptionWhenNotFound() {
|
|
// Given
|
|
Long projectId = 999L;
|
|
when(projectRepository.existsById(projectId)).thenReturn(false);
|
|
|
|
// When & Then
|
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> {
|
|
projectService.deleteProject(projectId);
|
|
});
|
|
|
|
assertTrue(exception.getMessage().contains("Project not found"));
|
|
verify(projectRepository, times(1)).existsById(projectId);
|
|
verify(projectRepository, never()).deleteById(any());
|
|
}
|
|
} |