From 24444a3ac350156f9d6c1ee58864dc5e617317ef Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Wed, 25 Sep 2024 10:29:22 -0300 Subject: [PATCH] test: fix exclusions and add auth sign-up test cases issue #46 --- java-api/pom.xml | 7 +--- .../controller/AuthenticationController.java | 6 ++-- .../controller/RestExceptionController.java | 17 +++++++++ .../java_api/response/FieldIssueResponse.java | 6 ++++ .../response/ValidationExceptionResponse.java | 34 ++++++++++++++++++ .../java_api/service/AuthService.java | 5 ++- .../service/impl/AuthServiceImpl.java | 6 ++-- .../AuthenticationControllerTest.java | 35 +++++++++++++++++-- 8 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 java-api/src/main/java/br/com/tasknoteapp/java_api/controller/RestExceptionController.java create mode 100644 java-api/src/main/java/br/com/tasknoteapp/java_api/response/FieldIssueResponse.java create mode 100644 java-api/src/main/java/br/com/tasknoteapp/java_api/response/ValidationExceptionResponse.java diff --git a/java-api/pom.xml b/java-api/pom.xml index c82c601..ea3d8d2 100644 --- a/java-api/pom.xml +++ b/java-api/pom.xml @@ -263,15 +263,10 @@ ${jacoco.skip} **/config/** - **/dto/** - **/entity/** - **/exception/** **/filter/** - **/interceptor/** - **/response/** **/*$*Builder* **/RestExceptionEndpoint.* - **/BackendStartApiApplication.* + **/JavaApiApiApplication.* diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/AuthenticationController.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/AuthenticationController.java index 6a113ba..e81d302 100644 --- a/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/AuthenticationController.java +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/AuthenticationController.java @@ -55,7 +55,7 @@ public class AuthenticationController { }) public ResponseEntity signUp( @RequestBody @Valid LoginRequest loginRequest) { - String token = authService.create(loginRequest); + String token = authService.signUpNewUser(loginRequest); return ResponseEntity.status(HttpStatus.CREATED).body(new JwtAuthenticationResponse(token)); } @@ -86,7 +86,7 @@ public class AuthenticationController { content = @Content(schema = @Schema(implementation = Void.class))) }) public JwtAuthenticationResponse signIn(@RequestBody @Valid LoginRequest loginRequest) { - String token = authService.signin(loginRequest); + String token = authService.signInUser(loginRequest); return new JwtAuthenticationResponse(token); - } + } } diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/RestExceptionController.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/RestExceptionController.java new file mode 100644 index 0000000..1f78731 --- /dev/null +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/controller/RestExceptionController.java @@ -0,0 +1,17 @@ +package br.com.tasknoteapp.java_api.controller; + +import br.com.tasknoteapp.java_api.response.ValidationExceptionResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class RestExceptionController { + + @ExceptionHandler(MethodArgumentNotValidException.class) + ResponseEntity handleValidationException( + MethodArgumentNotValidException ex) { + return ResponseEntity.badRequest().body(new ValidationExceptionResponse(ex.getFieldErrors())); + } +} diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/response/FieldIssueResponse.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/response/FieldIssueResponse.java new file mode 100644 index 0000000..9f8ba9d --- /dev/null +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/response/FieldIssueResponse.java @@ -0,0 +1,6 @@ +package br.com.tasknoteapp.java_api.response; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "An object with fields name and the respective error massages") +record FieldIssueResponse(String fieldName, String fieldMessage) {} diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/response/ValidationExceptionResponse.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/response/ValidationExceptionResponse.java new file mode 100644 index 0000000..85393b9 --- /dev/null +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/response/ValidationExceptionResponse.java @@ -0,0 +1,34 @@ +package br.com.tasknoteapp.java_api.response; + +import java.util.List; + +import org.springframework.validation.FieldError; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema(description = "An object containing the error message and the invalid fields") +public class ValidationExceptionResponse { + + private static final String MESSAGE_TEMPLATE = "%d field(s) with validation problems!"; + + @Schema(description = "The error message") + private final String errorMessage; + + @Schema(description = "An array of 'FieldIssue' with the invalid fields") + private final List fields; + + /** + * The sole constructor of this class. + * + * @param errors all the validation problems to be listed as a response + */ + public ValidationExceptionResponse(List errors) { + this.fields = + errors.stream() + .map(error -> new FieldIssueResponse(error.getField(), error.getDefaultMessage())) + .toList(); + this.errorMessage = String.format(MESSAGE_TEMPLATE, fields.size()); + } +} diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/service/AuthService.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/service/AuthService.java index 0575089..007f179 100644 --- a/java-api/src/main/java/br/com/tasknoteapp/java_api/service/AuthService.java +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/service/AuthService.java @@ -3,7 +3,6 @@ package br.com.tasknoteapp.java_api.service; import br.com.tasknoteapp.java_api.entity.UserEntity; import br.com.tasknoteapp.java_api.request.LoginRequest; import br.com.tasknoteapp.java_api.response.UserResponse; - import java.util.List; import java.util.Optional; import org.springframework.security.core.userdetails.User; @@ -17,7 +16,7 @@ public interface AuthService { * @param login User details with email and password. * @return Token */ - public String create(LoginRequest login); + public String signUpNewUser(LoginRequest login); /** * Find a user by email in the database. @@ -41,7 +40,7 @@ public interface AuthService { * @param login User details with email and password. * @return Token */ - public String signin(LoginRequest login); + public String signInUser(LoginRequest login); /** * Get all registered users. diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/AuthServiceImpl.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/AuthServiceImpl.java index b4a374e..f64dca5 100644 --- a/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/AuthServiceImpl.java +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/AuthServiceImpl.java @@ -46,8 +46,8 @@ class AuthServiceImpl implements AuthService { * @return Token */ @Override - public String create(LoginRequest login) { - log.info("Creating user! {}", login.email()); + public String signUpNewUser(LoginRequest login) { + log.info("Signing up new user! {}", login.email()); if (findByEmail(login.email()).isPresent()) { throw new UserAlreadyExistsException(); @@ -105,7 +105,7 @@ class AuthServiceImpl implements AuthService { * @return Token */ @Override - public String signin(LoginRequest login) { + public String signInUser(LoginRequest login) { log.info("Signing in user! {}", login.email()); Optional user = findByEmail(login.email()); diff --git a/java-api/src/test/java/br/com/tasknoteapp/java_api/controller/AuthenticationControllerTest.java b/java-api/src/test/java/br/com/tasknoteapp/java_api/controller/AuthenticationControllerTest.java index 728fb1d..7a6f0ef 100644 --- a/java-api/src/test/java/br/com/tasknoteapp/java_api/controller/AuthenticationControllerTest.java +++ b/java-api/src/test/java/br/com/tasknoteapp/java_api/controller/AuthenticationControllerTest.java @@ -2,6 +2,7 @@ package br.com.tasknoteapp.java_api.controller; import static org.mockito.Mockito.when; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -32,7 +33,7 @@ class AuthenticationControllerTest { LoginRequest request = new LoginRequest("user@domain.com", "abcde123456"); final String token = "xaxbxcxdx1x2x3A@"; - when(authService.create(request)).thenReturn(token); + when(authService.signUpNewUser(request)).thenReturn(token); String jsonString = """ @@ -60,7 +61,7 @@ class AuthenticationControllerTest { LoginRequest request = new LoginRequest("user@domain..com", "abcde123456"); final String token = "xaxbxcxdx1x2x3@A"; - when(authService.create(request)).thenReturn(token); + when(authService.signUpNewUser(request)).thenReturn(token); String jsonString = """ @@ -86,7 +87,7 @@ class AuthenticationControllerTest { void signup_userAlreadyExists_shouldFail() throws Exception { LoginRequest request = new LoginRequest("user@domain.com", "abcde123456"); - when(authService.create(request)).thenThrow(new UserAlreadyExistsException()); + when(authService.signUpNewUser(request)).thenThrow(new UserAlreadyExistsException()); String jsonString = """ @@ -106,4 +107,32 @@ class AuthenticationControllerTest { .andExpect(status().isBadRequest()) .andReturn(); } + + @Test + @DisplayName("Sign in happy path should succeed") + void signin_happyPath_shouldSucceed() throws Exception { + LoginRequest request = new LoginRequest("user@domain.com", "abcde123456"); + final String token = "xaxbxcxdx1x2x3A@"; + + when(authService.signInUser(request)).thenReturn(token); + + String jsonString = + """ + { + "email": "user@domain.com", + "password": "abcde123456" + } + """; + + mockMvc + .perform( + post("/auth/sign-in") + .with(csrf().asHeader()) + .header("Content-Type", MediaType.APPLICATION_JSON_VALUE) + .accept(MediaType.APPLICATION_JSON) + .content(jsonString)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.token").value(token)) + .andReturn(); + } }