test(#240): add TranscriptionQueueControllerTest

Verifies 401/403/200 responses for all four endpoints. Matches
the @WebMvcTest + @RequirePermission pattern used across the project.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-16 12:07:14 +02:00
parent 2e4d9a8375
commit 4cf01a0f1d

View File

@@ -0,0 +1,151 @@
package org.raddatz.familienarchiv.controller;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.config.SecurityConfig;
import org.raddatz.familienarchiv.dto.TranscriptionQueueItemDTO;
import org.raddatz.familienarchiv.dto.TranscriptionWeeklyStatsDTO;
import org.raddatz.familienarchiv.repository.DocumentRepository;
import org.raddatz.familienarchiv.repository.PersonRepository;
import org.raddatz.familienarchiv.security.PermissionAspect;
import org.raddatz.familienarchiv.service.CustomUserDetailsService;
import org.raddatz.familienarchiv.service.TranscriptionQueueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(TranscriptionQueueController.class)
@Import({SecurityConfig.class, PermissionAspect.class, AopAutoConfiguration.class})
class TranscriptionQueueControllerTest {
@Autowired MockMvc mockMvc;
@MockitoBean TranscriptionQueueService transcriptionQueueService;
@MockitoBean DocumentRepository documentRepository;
@MockitoBean PersonRepository personRepository;
@MockitoBean CustomUserDetailsService customUserDetailsService;
private static final TranscriptionQueueItemDTO ITEM = new TranscriptionQueueItemDTO(
UUID.fromString("00000000-0000-0000-0000-000000000001"),
"Testbrief",
LocalDate.of(1920, 6, 15),
3, 1, 0
);
private static final TranscriptionWeeklyStatsDTO STATS = new TranscriptionWeeklyStatsDTO(2L, 5L, 1L);
// ─── segmentation-queue ───────────────────────────────────────────────────
@Test
void getSegmentationQueue_returns401_whenUnauthenticated() throws Exception {
mockMvc.perform(get("/api/transcription/segmentation-queue"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser
void getSegmentationQueue_returns403_whenNoReadAllPermission() throws Exception {
mockMvc.perform(get("/api/transcription/segmentation-queue"))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser(authorities = "READ_ALL")
void getSegmentationQueue_returns200_withItems() throws Exception {
when(transcriptionQueueService.getSegmentationQueue()).thenReturn(List.of(ITEM));
mockMvc.perform(get("/api/transcription/segmentation-queue"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].title").value("Testbrief"))
.andExpect(jsonPath("$[0].annotationCount").value(3));
}
// ─── transcription-queue ──────────────────────────────────────────────────
@Test
void getTranscriptionQueue_returns401_whenUnauthenticated() throws Exception {
mockMvc.perform(get("/api/transcription/transcription-queue"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser
void getTranscriptionQueue_returns403_whenNoReadAllPermission() throws Exception {
mockMvc.perform(get("/api/transcription/transcription-queue"))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser(authorities = "READ_ALL")
void getTranscriptionQueue_returns200_withItems() throws Exception {
when(transcriptionQueueService.getTranscriptionQueue()).thenReturn(List.of(ITEM));
mockMvc.perform(get("/api/transcription/transcription-queue"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].title").value("Testbrief"));
}
// ─── ready-to-read ────────────────────────────────────────────────────────
@Test
void getReadyToRead_returns401_whenUnauthenticated() throws Exception {
mockMvc.perform(get("/api/transcription/ready-to-read"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser
void getReadyToRead_returns403_whenNoReadAllPermission() throws Exception {
mockMvc.perform(get("/api/transcription/ready-to-read"))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser(authorities = "READ_ALL")
void getReadyToRead_returns200_withItems() throws Exception {
when(transcriptionQueueService.getReadyToReadQueue()).thenReturn(List.of(ITEM));
mockMvc.perform(get("/api/transcription/ready-to-read"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].reviewedBlockCount").value(0));
}
// ─── weekly-stats ─────────────────────────────────────────────────────────
@Test
void getWeeklyStats_returns401_whenUnauthenticated() throws Exception {
mockMvc.perform(get("/api/transcription/weekly-stats"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser
void getWeeklyStats_returns403_whenNoReadAllPermission() throws Exception {
mockMvc.perform(get("/api/transcription/weekly-stats"))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser(authorities = "READ_ALL")
void getWeeklyStats_returns200_withStats() throws Exception {
when(transcriptionQueueService.getWeeklyStats()).thenReturn(STATS);
mockMvc.perform(get("/api/transcription/weekly-stats"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.segmentationCount").value(2))
.andExpect(jsonPath("$.transcriptionCount").value(5))
.andExpect(jsonPath("$.readyCount").value(1));
}
}