11package com .itasocialacademy .oitassist .logfile .controller ;
22
33import static org .assertj .core .api .Assertions .assertThat ;
4+ import static org .hamcrest .Matchers .containsString ;
45import static org .mockito .ArgumentMatchers .any ;
56import static org .mockito .ArgumentMatchers .eq ;
67import static org .mockito .Mockito .verify ;
78import static org .mockito .Mockito .verifyNoInteractions ;
89import static org .mockito .Mockito .when ;
10+ import static org .springframework .security .test .web .servlet .request .SecurityMockMvcRequestPostProcessors .user ;
911import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .get ;
10- import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .content ;
11- import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .jsonPath ;
12- import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .status ;
12+ import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .*;
1313
1414import com .itasocialacademy .oitassist .core .web .AppExceptionHttpStatusMapper ;
1515import com .itasocialacademy .oitassist .logfile .api .LogFileResponse ;
1616import com .itasocialacademy .oitassist .logfile .api .PageResponse ;
17+ import com .itasocialacademy .oitassist .logfile .dao .model .LogFileDownloadResult ;
18+ import com .itasocialacademy .oitassist .logfile .exceptions .InvalidLogFileNameException ;
19+ import com .itasocialacademy .oitassist .logfile .exceptions .LogFileNotFoundException ;
1720import com .itasocialacademy .oitassist .logfile .service .LogFileService ;
1821import com .itasocialacademy .oitassist .security .jwt .JwtFilter ;
22+ import java .nio .charset .StandardCharsets ;
1923import java .time .Instant ;
2024import java .util .List ;
2125import org .junit .jupiter .api .Test ;
2832import org .springframework .context .annotation .ComponentScan ;
2933import org .springframework .context .annotation .FilterType ;
3034import org .springframework .context .annotation .Import ;
35+ import org .springframework .core .io .ByteArrayResource ;
3136import org .springframework .data .domain .Pageable ;
3237import org .springframework .data .domain .Sort ;
38+ import org .springframework .http .HttpHeaders ;
3339import org .springframework .http .MediaType ;
3440import org .springframework .security .config .annotation .method .configuration .EnableMethodSecurity ;
3541import org .springframework .security .config .annotation .web .builders .HttpSecurity ;
4551 excludeFilters = @ ComponentScan .Filter (
4652 type = FilterType .ASSIGNABLE_TYPE ,
4753 classes = JwtFilter .class ))
48- @ Import (LogFileControllerTest .SecurityTestConfiguration .class )
54+ @ Import ({
55+ LogFileControllerTest .SecurityTestConfiguration .class ,
56+ AppExceptionHttpStatusMapper .class
57+ })
4958class LogFileControllerTest {
5059
5160 private static final String ENDPOINT =
@@ -62,9 +71,6 @@ class LogFileControllerTest {
6271 @ MockitoBean
6372 private LogFileService logFileService ;
6473
65- @ MockitoBean
66- private AppExceptionHttpStatusMapper appExceptionHttpStatusMapper ;
67-
6874 @ Test
6975 void shouldLoadControllerThroughMethodSecurityProxy () {
7076 assertThat (AopUtils .isAopProxy (logFileController ))
@@ -476,4 +482,90 @@ void shouldReturnBadRequestWhenSearchNameIsMissing()
476482
477483 verifyNoInteractions (logFileService );
478484 }
485+
486+ @ Test
487+ void shouldDownloadLogFile () throws Exception {
488+ byte [] fileContent =
489+ "test log content"
490+ .getBytes (StandardCharsets .UTF_8 );
491+
492+ LogFileDownloadResult downloadResult =
493+ new LogFileDownloadResult (
494+ "app.log" ,
495+ new ByteArrayResource (fileContent ));
496+
497+ when (logFileService .downloadFile ("app.log" ))
498+ .thenReturn (downloadResult );
499+
500+ mockMvc .perform (
501+ get ("/api/v1/admin/log-files/app.log/download" )
502+ .with (
503+ user ("admin" )
504+ .roles ("ADMIN" )))
505+ .andExpect (status ().isOk ())
506+ .andExpect (
507+ content ().contentType (
508+ MediaType .APPLICATION_OCTET_STREAM ))
509+ .andExpect (
510+ header ().string (
511+ HttpHeaders .CONTENT_DISPOSITION ,
512+ containsString ("attachment" )))
513+ .andExpect (
514+ header ().string (
515+ HttpHeaders .CONTENT_DISPOSITION ,
516+ containsString ("app.log" )))
517+ .andExpect (
518+ content ().bytes (fileContent ));
519+
520+ verify (logFileService )
521+ .downloadFile ("app.log" );
522+ }
523+
524+ @ Test
525+ void shouldReturnBadRequestForInvalidDownloadFileName ()
526+ throws Exception {
527+
528+ when (logFileService .downloadFile ("app..log" ))
529+ .thenThrow (
530+ new InvalidLogFileNameException ());
531+
532+ mockMvc .perform (
533+ get ("/api/v1/admin/log-files/app..log/download" )
534+ .with (
535+ user ("admin" )
536+ .roles ("ADMIN" )))
537+ .andExpect (
538+ status ().isBadRequest ())
539+ .andExpect (
540+ jsonPath ("$.code" )
541+ .value ("INVALID_LOG_FILE_NAME" ));
542+
543+ verify (logFileService )
544+ .downloadFile ("app..log" );
545+ }
546+
547+ @ Test
548+ void shouldReturnNotFoundWhenDownloadFileDoesNotExist ()
549+ throws Exception {
550+
551+ when (logFileService .downloadFile ("missing.log" ))
552+ .thenThrow (
553+ new LogFileNotFoundException (
554+ "missing.log" ));
555+
556+ mockMvc .perform (
557+ get ("/api/v1/admin/log-files/missing.log/download" )
558+ .with (
559+ user ("admin" )
560+ .roles ("ADMIN" )))
561+ .andExpect (
562+ status ().isNotFound ())
563+ .andExpect (
564+ jsonPath ("$.code" )
565+ .value ("LOG_FILE_NOT_FOUND" ));
566+
567+ verify (logFileService )
568+ .downloadFile ("missing.log" );
569+ }
570+
479571}
0 commit comments