View Javadoc
1   package fr.tiogars.chat.domains.task.controllers;
2   
3   import static org.mockito.Mockito.verifyNoInteractions;
4   import static org.mockito.Mockito.when;
5   import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
6   import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
7   import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
8   import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
9   import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
10  
11  import java.nio.charset.StandardCharsets;
12  import java.util.List;
13  import java.util.Optional;
14  
15  import org.junit.jupiter.api.Test;
16  import org.junit.jupiter.params.ParameterizedTest;
17  import org.junit.jupiter.params.provider.ValueSource;
18  import org.springframework.beans.factory.annotation.Autowired;
19  import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
20  import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
21  import org.springframework.http.MediaType;
22  import org.springframework.http.HttpStatus;
23  import org.springframework.security.core.userdetails.UserDetailsService;
24  import org.springframework.test.context.bean.override.mockito.MockitoBean;
25  import org.springframework.test.web.servlet.MockMvc;
26  import org.springframework.web.server.ResponseStatusException;
27  
28  import fr.tiogars.chat.domains.auth.services.JwtTokenService;
29  import fr.tiogars.chat.domains.task.services.TaskPrintService;
30  import fr.tiogars.chat.domains.task.services.TasksPrintAllService;
31  import fr.tiogars.chat.domains.task.services.TasksPrintSelectedService;
32  
33  @WebMvcTest(TaskPrintController.class)
34  @AutoConfigureMockMvc(addFilters = false)
35  class TaskPrintControllerTest {
36  
37      private static final byte[] PDF = "%PDF-1.7\nTest PDF bytes".getBytes(StandardCharsets.UTF_8);
38  
39      @Autowired
40      private MockMvc mvc;
41  
42      @MockitoBean
43      private TaskPrintService printService;
44  
45      @MockitoBean
46      private TasksPrintAllService printAllService;
47  
48      @MockitoBean
49      private TasksPrintSelectedService printSelectedService;
50  
51      @MockitoBean
52      private JwtTokenService jwtTokenService;
53  
54      @MockitoBean
55      private UserDetailsService userDetailsService;
56  
57      @Test
58      void print_should_returnInlinePdfForCurrentRecord() throws Exception {
59          when(printService.print(42L)).thenReturn(Optional.of(PDF));
60  
61          mvc.perform(get("/api/v1/task/42/print.pdf"))
62                  .andExpect(status().isOk())
63                  .andExpect(content().contentType(MediaType.APPLICATION_PDF))
64                  .andExpect(content().bytes(PDF))
65                  .andExpect(header().string("Content-Disposition", "inline; filename=\"task-42.pdf\""))
66                  .andExpect(header().string("Cache-Control", "no-store"));
67      }
68  
69      @Test
70      void printAll_should_returnInlinePdf() throws Exception {
71          when(printAllService.printAll()).thenReturn(PDF);
72  
73          mvc.perform(get("/api/v1/task/print.pdf"))
74                  .andExpect(status().isOk())
75                  .andExpect(content().contentType(MediaType.APPLICATION_PDF))
76                  .andExpect(content().bytes(PDF))
77                  .andExpect(header().string("Content-Disposition", "inline; filename=\"tasks.pdf\""));
78      }
79  
80      @Test
81      void printSelected_should_returnInlinePdfForRequestedIds() throws Exception {
82          when(printSelectedService.printSelected(List.of(1L, 2L))).thenReturn(Optional.of(PDF));
83  
84          mvc.perform(post("/api/v1/task/print-selected.pdf")
85                  .contentType(MediaType.APPLICATION_JSON).content("{\"ids\":[1,2]}"))
86                  .andExpect(status().isOk())
87                  .andExpect(content().contentType(MediaType.APPLICATION_PDF))
88                  .andExpect(content().bytes(PDF))
89                  .andExpect(header().string("Content-Disposition", "inline; filename=\"tasks-selected.pdf\""));
90      }
91  
92      @ParameterizedTest
93      @ValueSource(strings = {"{}", "{\"ids\":null}", "{\"ids\":[]}", "{\"ids\":[null]}",
94              "{\"ids\":[0]}", "{\"ids\":[-1]}"})
95      void printSelected_should_rejectInvalidSelections(String body) throws Exception {
96          mvc.perform(post("/api/v1/task/print-selected.pdf")
97                  .contentType(MediaType.APPLICATION_JSON).content(body))
98                  .andExpect(status().isBadRequest());
99  
100         verifyNoInteractions(printSelectedService);
101     }
102 
103     @Test
104     void printSelected_should_rejectOversizedSelection() throws Exception {
105         String body = "{\"ids\":[" + String.join(",", java.util.Collections.nCopies(1001, "1")) + "]}";
106         mvc.perform(post("/api/v1/task/print-selected.pdf")
107                 .contentType(MediaType.APPLICATION_JSON).content(body))
108                 .andExpect(status().isBadRequest());
109         verifyNoInteractions(printSelectedService);
110     }
111 
112     @Test
113     void print_should_returnNotFoundWhenCurrentRecordIsMissing() throws Exception {
114         when(printService.print(99L)).thenReturn(Optional.empty());
115 
116         mvc.perform(get("/api/v1/task/99/print.pdf")).andExpect(status().isNotFound());
117     }
118 
119     @Test
120     void printSelected_should_returnNotFoundWhenAnySelectedRecordIsMissing() throws Exception {
121         when(printSelectedService.printSelected(List.of(1L, 99L))).thenReturn(Optional.empty());
122 
123         mvc.perform(post("/api/v1/task/print-selected.pdf")
124                 .contentType(MediaType.APPLICATION_JSON).content("{\"ids\":[1,99]}"))
125                 .andExpect(status().isNotFound());
126     }
127 
128     @Test
129     void print_should_reportUnsupportedCharactersAsUnprocessableContent() throws Exception {
130         when(printService.print(42L)).thenThrow(new ResponseStatusException(
131                 HttpStatus.UNPROCESSABLE_CONTENT, "Unsupported PDF characters."));
132 
133         mvc.perform(get("/api/v1/task/42/print.pdf"))
134                 .andExpect(status().is(HttpStatus.UNPROCESSABLE_CONTENT.value()));
135     }
136 }